From arigo at codespeak.net Sun Jun 1 18:30:00 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 1 Jun 2003 18:30:00 +0200 (MEST) Subject: [pypy-svn] rev 745 - in pypy/trunk/src/pypy: interpreter module objspaceobjspace/std objspace/std/test Message-ID: <20030601163000.20FA55A186@thoth.codespeak.net> Author: arigo Date: Sun Jun 1 18:29:57 2003 New Revision: 745 Added: pypy/trunk/src/pypy/objspace/std/functype.py (contents, props changed) pypy/trunk/src/pypy/objspace/std/instmethtype.py (contents, props changed) pypy/trunk/src/pypy/objspace/std/itertype.py (contents, props changed) pypy/trunk/src/pypy/objspace/std/objectobject.py - copied, changed from rev 741, pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/objecttype.py (contents, props changed) Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py pypy/trunk/src/pypy/module/builtin.py pypy/trunk/src/pypy/objspace/std/boolobject.py pypy/trunk/src/pypy/objspace/std/booltype.py pypy/trunk/src/pypy/objspace/std/cpythonobject.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/floatobject.py pypy/trunk/src/pypy/objspace/std/funcobject.py pypy/trunk/src/pypy/objspace/std/instmethobject.py pypy/trunk/src/pypy/objspace/std/intobject.py pypy/trunk/src/pypy/objspace/std/iterobject.py pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/moduleobject.py pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/noneobject.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py pypy/trunk/src/pypy/objspace/std/tupleobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/typetype.py pypy/trunk/src/pypy/objspace/std/userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py pypy/trunk/src/pypy/objspace/trivial.py Log: classes and inheritance, still missing __init__() support Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sun Jun 1 18:29:57 2003 @@ -57,7 +57,7 @@ self.w_type = w_type self.w_value = w_value self.application_traceback = [] - self.debug_tb = None + self.debug_tbs = [] def record_application_traceback(self, frame, last_instruction): self.application_traceback.append((frame, last_instruction)) @@ -88,8 +88,7 @@ """Records the current traceback inside the interpreter. This traceback is only useful to debug the interpreter, not the application.""" - if self.debug_tb is None: - self.debug_tb = sys.exc_info()[2] + self.debug_tbs.append(sys.exc_info()[2]) def print_application_traceback(self, space, file=None): "Dump a standard application-level traceback." @@ -127,12 +126,12 @@ """Dump a nice detailed interpreter- and application-level traceback, useful to debug the interpreter.""" if file is None: file = sys.stderr - self.print_app_tb_only(file) - if self.debug_tb: + for i in range(len(self.debug_tbs)-1, -1, -1): import traceback interpr_file = LinePrefixer(file, '||') print >> interpr_file, "Traceback (interpreter-level):" - traceback.print_tb(self.debug_tb, file=interpr_file) + traceback.print_tb(self.debug_tbs[i], file=interpr_file) + self.print_app_tb_only(file) if space is None: exc_typename = str(self.w_type) exc_value = self.w_value @@ -218,7 +217,7 @@ # installing the excepthook for OperationErrors def operr_excepthook(exctype, value, traceback): if issubclass(exctype, OperationError): - value.debug_tb = value.debug_tb or traceback + value.debug_tbs.append(traceback) value.print_detailed_traceback() else: old_excepthook(exctype, value, traceback) Modified: pypy/trunk/src/pypy/module/builtin.py ============================================================================== --- pypy/trunk/src/pypy/module/builtin.py (original) +++ pypy/trunk/src/pypy/module/builtin.py Sun Jun 1 18:29:57 2003 @@ -104,10 +104,6 @@ return self.space.len(w_obj) len = appmethod(len) - def str(self, w_obj): - return self.space.str(w_obj) - str = appmethod(str) - def delattr(self, w_object, w_name): return self.space.delattr(w_object, w_name) delattr = appmethod(delattr) @@ -178,8 +174,8 @@ # we have None! But leave these at the bottom, otherwise the default # arguments of the above-defined functions will see this new None... None = appdata(_b.None) - False = appdata(_b.False) - True = appdata(_b.True) - dict = appdata(_b.dict) # XXX temporary - tuple = appdata(_b.tuple) # XXX temporary - int = appdata(_b.int) # XXX temporary +## False = appdata(_b.False) +## True = appdata(_b.True) +## dict = appdata(_b.dict) # XXX temporary +## tuple = appdata(_b.tuple) # XXX temporary +## int = appdata(_b.int) # XXX temporary Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Sun Jun 1 18:29:57 2003 @@ -1,26 +1,29 @@ from pypy.objspace.std.objspace import * from booltype import W_BoolType +import intobject class W_BoolObject(W_Object): - delegate_once = {} statictype = W_BoolType def __init__(w_self, space, boolval):# please pass in a real bool, not an int W_Object.__init__(w_self, space) w_self.boolval = boolval - def __eq__(w_self, w_other): - "Implements 'is'." - # all w_False wrapped values are equal ('is'-identical) - # and so do all w_True wrapped values - return (isinstance(w_other, W_BoolObject) and - w_self.boolval == w_other.boolval) - def __nonzero__(w_self): raise Exception, "you cannot do that, you must use space.is_true()" +registerimplementation(W_BoolObject) + +# bool-to-int delegation requires translating the .boolvar attribute +# to an .intval one +def bool_to_int(space, w_bool): + return intobject.W_IntObject(space, int(w_bool.boolval)) + +W_BoolObject.delegate_once[intobject.W_IntObject] = bool_to_int + + def bool_is_true(space, w_bool): return w_bool.boolval Modified: pypy/trunk/src/pypy/objspace/std/booltype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/booltype.py (original) +++ pypy/trunk/src/pypy/objspace/std/booltype.py Sun Jun 1 18:29:57 2003 @@ -1,10 +1,9 @@ from pypy.objspace.std.objspace import * from typeobject import W_TypeObject +from inttype import W_IntType class W_BoolType(W_TypeObject): typename = 'bool' - - def getbases(w_self, space): - return (space.w_int,) + staticbases = (W_IntType,) Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py Sun Jun 1 18:29:57 2003 @@ -4,8 +4,6 @@ class W_CPythonObject(W_Object): "This class wraps an arbitrary CPython object." - - delegate_once = {} def __init__(w_self, space, cpyobj): W_Object.__init__(w_self, space) @@ -16,6 +14,9 @@ return "wrap(%r)" % (w_self.cpyobj,) +registerimplementation(W_CPythonObject) + + def cpython_unwrap(space, w_obj): return w_obj.cpyobj Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Sun Jun 1 18:29:57 2003 @@ -3,6 +3,10 @@ from pypy.objspace.std.objspace import * +# These are operations that must fall back to some default behavior that +# should not appear in the explicit object.__xxx__ methods. + + # 'eq' falls back to 'is' def default_eq(space, w_a, w_b): @@ -53,45 +57,6 @@ StdObjSpace.is_true.register(default_is_true, W_ANY) -# give objects some default attributes and a default way to complain -# about missing attributes - -def default_getattr(space, w_obj, w_attr): - # XXX build a nicer error message along these lines: - #w_type = space.type(w_obj) - #w_typename = space.getattr(w_type, space.wrap('__name__')) - #... - - w_type = space.type(w_obj) - if space.is_true(space.eq(w_attr, space.wrap('__class__'))): - return w_type - - # XXX implement lookup as a multimethod - from typeobject import W_TypeObject - if isinstance(w_type, W_TypeObject): # XXX must always be true at some point - try: - w_value = w_type.lookup(space, w_attr) - except KeyError: - pass - else: - return space.get(w_value, w_obj, w_type) - - raise OperationError(space.w_AttributeError, w_attr) - - -StdObjSpace.getattr.register(default_getattr, W_ANY, W_ANY) - -def default_setattr(space, w_obj, w_attr, w_value): - raise OperationError(space.w_AttributeError, w_attr) - -StdObjSpace.setattr.register(default_setattr, W_ANY, W_ANY, W_ANY) - -def default_delattr(space, w_obj, w_attr, w_value): - raise OperationError(space.w_AttributeError, w_attr) - -StdObjSpace.delattr.register(default_delattr, W_ANY, W_ANY) - - # in-place operators fall back to their non-in-place counterpart for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: @@ -123,27 +88,3 @@ return w_descr StdObjSpace.get.register(default_get, W_ANY, W_ANY, W_ANY) - - -# static types - -def default_type(space, w_obj): - if w_obj.statictype is None: - # XXX remove me, temporary - return space.wrap(space.unwrap(w_obj).__class__) - else: - w_type = space.get_typeinstance(w_obj.statictype) - return w_type - -StdObjSpace.type.register(default_type, W_ANY) - -def default_str(space, w_obj): - return space.repr(w_obj) - -StdObjSpace.str.register(default_str, W_ANY) - -def default_repr(space, w_obj): - return space.wrap('<%s object at %s>'%( - space.type(w_obj).typename, space.unwrap(space.id(w_obj)))) - -StdObjSpace.repr.register(default_repr, W_ANY) Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Sun Jun 1 18:29:57 2003 @@ -12,7 +12,7 @@ def get(self): if self.is_empty(): - raise OperatioError(w_SystemError) + raise ValueError, "get() from an empty cell" return self.w_value def set(self,w_value): @@ -20,7 +20,7 @@ def make_empty(self): if self.is_empty(): - raise OperatioError(w_SystemError) + raise ValueError, "make_empty() on an empty cell" self.w_value = _NoValueInCell def is_empty(self): @@ -33,34 +33,41 @@ class W_DictObject(W_Object): - delegate_once = {} statictype = W_DictType def __init__(w_self, space, list_pairs_w): W_Object.__init__(w_self, space) - w_self.data = [ (w_key,Cell(w_value)) for w_key,w_value in list_pairs_w ] + w_self.data = [ (w_key, space.unwrap(space.hash(w_key)), Cell(w_value)) + for w_key,w_value in list_pairs_w ] def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, w_self.data) def non_empties(self): - return [ (w_key,cell) for w_key,cell in self.data if not cell.is_empty()] + return [ (w_key,cell) for w_key,hash,cell in self.data + if not cell.is_empty()] def _cell(self,space,w_lookup): data = self.data - for w_key, cell in data: - if space.is_true(space.eq(w_lookup, w_key)): + # this lookup is where most of the start-up time is consumed. + # Hashing helps a lot. + lookup_hash = space.unwrap(space.hash(w_lookup)) + for w_key, hash, cell in data: + if lookup_hash == hash and space.is_true(space.eq(w_lookup, w_key)): break else: cell = Cell() - data.append((w_lookup,cell)) + data.append((w_lookup,lookup_hash,cell)) return cell def cell(self,space,w_lookup): return space.wrap(self._cell(space,w_lookup)) +registerimplementation(W_DictObject) + + def dict_is_true(space, w_dict): return not not w_dict.non_empties() @@ -133,7 +140,7 @@ def eq_dict_dict(space, w_left, w_right): if len(w_left.data) != len(w_right.data): return space.newbool(0) - for w_k, cell in w_left.data: + for w_k, hash, cell in w_left.data: try: w_v = space.getitem(w_right, w_k) except OperationError: Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/floatobject.py Sun Jun 1 18:29:57 2003 @@ -16,14 +16,15 @@ """This is a reimplementation of the CPython "PyFloatObject" it is assumed that the constructor takes a real Python float as an argument""" - - delegate_once = {} statictype = W_FloatType def __init__(w_self, space, floatval): W_Object.__init__(w_self, space) w_self.floatval = floatval + +registerimplementation(W_FloatObject) + # int-to-float delegation def int_to_float(space, w_intobj): return W_FloatObject(space, float(w_intobj.intval)) Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Sun Jun 1 18:29:57 2003 @@ -1,10 +1,13 @@ from __future__ import nested_scopes from pypy.objspace.std.objspace import * +from functype import W_FuncType import pypy.interpreter.pyframe from pypy.objspace.std.instmethobject import W_InstMethObject class W_FuncObject(W_Object): + statictype = W_FuncType + def __init__(w_self, space, code, w_globals, w_defaultarguments, w_closure): W_Object.__init__(w_self, space) w_self.code = code @@ -13,6 +16,9 @@ w_self.w_closure = w_closure +registerimplementation(W_FuncObject) + + def function_unwrap(space, w_function): # XXX this is probably a temporary hack def proxy_function(*args, **kw): Added: pypy/trunk/src/pypy/objspace/std/functype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/functype.py Sun Jun 1 18:29:57 2003 @@ -0,0 +1,7 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_FuncType(W_TypeObject): + + typename = 'FunctionType' Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Sun Jun 1 18:29:57 2003 @@ -1,14 +1,20 @@ from __future__ import nested_scopes from pypy.objspace.std.objspace import * +from instmethtype import W_InstMethType class W_InstMethObject(W_Object): + statictype = W_InstMethType + def __init__(w_self, space, w_im_self, w_im_func): W_Object.__init__(w_self, space) w_self.w_im_self = w_im_self w_self.w_im_func = w_im_func +registerimplementation(W_InstMethObject) + + #def function_unwrap(space, w_function): # # XXX this is probably a temporary hack # def proxy_function(*args, **kw): Added: pypy/trunk/src/pypy/objspace/std/instmethtype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/instmethtype.py Sun Jun 1 18:29:57 2003 @@ -0,0 +1,7 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_InstMethType(W_TypeObject): + + typename = 'MethodType' Modified: pypy/trunk/src/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/intobject.py Sun Jun 1 18:29:57 2003 @@ -1,7 +1,6 @@ from pypy.objspace.std.objspace import * from inttype import W_IntType from noneobject import W_NoneObject -from boolobject import W_BoolObject from restricted_int import r_int, LONG_BIT applicationfile = StdObjSpace.AppFile(__name__) @@ -22,8 +21,6 @@ """ class W_IntObject(W_Object): - - delegate_once = {} statictype = W_IntType def __init__(w_self, space, intval): @@ -35,9 +32,7 @@ return "%s(%d)" % (w_self.__class__.__name__, w_self.intval) -def bool_to_int(space, w_bool): - return W_IntObject(space, int(w_bool.boolval)) -W_BoolObject.delegate_once[W_IntObject] = bool_to_int +registerimplementation(W_IntObject) """ Modified: pypy/trunk/src/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/iterobject.py Sun Jun 1 18:29:57 2003 @@ -1,8 +1,9 @@ -from objspace import * +from pypy.objspace.std.objspace import * +from itertype import W_SeqIterType class W_SeqIterObject(W_Object): - delegate_once = {} + statictype = W_SeqIterType def __init__(w_self, space, w_seq, index=0): W_Object.__init__(w_self, space) @@ -10,6 +11,9 @@ w_self.index = index +registerimplementation(W_SeqIterObject) + + def iter_seqiter(space, w_seqiter): return w_seqiter Added: pypy/trunk/src/pypy/objspace/std/itertype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/itertype.py Sun Jun 1 18:29:57 2003 @@ -0,0 +1,7 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_SeqIterType(W_TypeObject): + + typename = 'SeqIterType' Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Sun Jun 1 18:29:57 2003 @@ -8,7 +8,6 @@ class W_ListObject(W_Object): - delegate_once = {} statictype = W_ListType def __init__(w_self, space, wrappeditems): @@ -30,6 +29,9 @@ return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist)) +registerimplementation(W_ListObject) + + def list_unwrap(space, w_list): items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]] return list(items) Modified: pypy/trunk/src/pypy/objspace/std/moduleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/moduleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/moduleobject.py Sun Jun 1 18:29:57 2003 @@ -4,7 +4,6 @@ class W_ModuleObject(W_Object): - delegate_once = {} statictype = W_ModuleType def __init__(w_self, space, w_name): @@ -16,6 +15,9 @@ w_self.w_dict = W_DictObject(w_self.space, items) +registerimplementation(W_ModuleObject) + + def getattr_module_any(space, w_module, w_attr): if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): return w_module.w_dict Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Sun Jun 1 18:29:57 2003 @@ -7,6 +7,8 @@ class MultiMethod(object): + ASSERT_BASE_TYPE = None + def __init__(self, operatorsymbol, arity, specialnames=None): "MultiMethod dispatching on the first 'arity' arguments." self.arity = arity @@ -15,6 +17,8 @@ if specialnames is None: specialnames = [operatorsymbol] self.specialnames = specialnames # list like ['__xxx__', '__rxxx__'] + self.cache_dependencies = {} + self.cache_table = {} def register(self, function, *types): # W_ANY can be used as a placeholder to dispatch on any value. @@ -22,19 +26,30 @@ raise error, "we already got an implementation for %r %r" % ( self.operatorsymbol, types) self.dispatch_table[types] = function + # clear caches + self.cache_table.clear() + for cache in self.cache_dependencies: + cache.cleardependency() + self.cache_dependencies.clear() def __get__(self, space, cls): if space is None: return self # <-------------------------- Hack return BoundMultiMethod(space, self) + def cache_dependency(self, cache): + self.cache_dependencies[cache] = 1 + def buildchoices(self, types): """Build a list of all possible combinations of delegated types, sorted by cost.""" - result = [] - self.internal_buildchoices(types, (), (), result) - # the result is sorted by costs by construction. - # it is a list of (delegator, function) pairs. + try: + result = self.cache_table[types] # try from the cache first + except KeyError: + result = self.cache_table[types] = [] + self.internal_buildchoices(types, (), (), result) + # the result is sorted by costs by construction. + # it is a list of (delegator, function) pairs. return result def internal_buildchoices(self, initialtypes, currenttypes, @@ -45,7 +60,9 @@ except KeyError: pass else: - result.append((currentdelegators, function)) + newentry = (currentdelegators, function) + if newentry not in result: # don't add duplicates + result.append(newentry) else: nexttype = initialtypes[len(currenttypes)] delegators = {} @@ -53,12 +70,20 @@ self.internal_buildchoices(initialtypes, currenttypes + (nexttype,), currentdelegators + (None,), result) - delegators.update(getattr(nexttype, "delegate_once", {})) + #assert "delegate_once" in nexttype.__dict__, ( + # "you must call registerimplementation() to initialize %r" % + # nexttype) + if "delegate_once" in nexttype.__dict__: + for key, value in nexttype.__dict__["delegate_once"].items(): + if key not in delegators: + delegators[key] = value # before general delegation, try superclasses if not nexttype.__bases__: # debugging assertion - assert nexttype.__name__ == 'W_Object', \ - "calling a multimethod with an argument which is not wrapped" + if self.ASSERT_BASE_TYPE: + assert nexttype is self.ASSERT_BASE_TYPE, ( + "calling a multimethod with an argument " + "which is not wrapped") break nexttype, = nexttype.__bases__ # no multiple inheritance pleeease for othertype, delegator in delegators.items(): @@ -70,8 +95,7 @@ def slicetable(self, position, slicetype): m = MultiMethod(self.operatorsymbol, self.arity, self.specialnames) for key, value in self.dispatch_table.iteritems(): - if (key[position].statictype is not None and - issubclass(key[position].statictype, slicetype.__class__)): + if slicetype.acceptclass(key[position]): m.dispatch_table[key] = value return m @@ -101,10 +125,10 @@ plural = "" else: plural = "s" - typenames = [t.__name__ for t in initialtypes] - message = "unsupported operand type%s for %s: %s" % ( + debugtypenames = [t.__name__ for t in initialtypes] + message = "unsupported operand type%s for %s (%s)" % ( plural, self.multimethod.operatorsymbol, - ', '.join(typenames)) + ', '.join(debugtypenames)) w_value = self.space.wrap(message) raise OperationError(self.space.w_TypeError, w_value) @@ -130,10 +154,6 @@ firstfailure = e raise firstfailure or FailedToImplement() - def slicetable(self, position, slicetype): - return BoundMultiMethod(self.space, - self.multimethod.slicetable(position, slicetype)) - def is_empty(self): return self.multimethod.is_empty() Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/noneobject.py Sun Jun 1 18:29:57 2003 @@ -3,10 +3,12 @@ class W_NoneObject(W_Object): - delegate_once = {} statictype = W_NoneType +registerimplementation(W_NoneObject) + + def none_unwrap(space, w_none): return None Copied: pypy/trunk/src/pypy/objspace/std/objectobject.py (from rev 741, pypy/trunk/src/pypy/objspace/std/default.py) ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/objectobject.py Sun Jun 1 18:29:57 2003 @@ -1,62 +1,31 @@ -"""Default implementation for some operation.""" - from pypy.objspace.std.objspace import * -# 'eq' falls back to 'is' - -def default_eq(space, w_a, w_b): - return space.is_(w_a, w_b) - -StdObjSpace.eq.register(default_eq, W_ANY, W_ANY) - - -# 'ne' -> 'eq', 'le/gt/ge' -> 'lt' - -def default_ne(space, w_a, w_b): - return space.not_(space.eq(w_a, w_b)) -def default_le(space, w_a, w_b): - return space.not_(space.lt(w_b, w_a)) -def default_gt(space, w_a, w_b): - return space.lt(w_b, w_a) -def default_ge(space, w_a, w_b): - return space.not_(space.lt(w_a, w_b)) - -StdObjSpace.ne.register(default_ne, W_ANY, W_ANY) -StdObjSpace.le.register(default_le, W_ANY, W_ANY) -StdObjSpace.gt.register(default_gt, W_ANY, W_ANY) -StdObjSpace.ge.register(default_ge, W_ANY, W_ANY) - - -# 'id' falls back to the address of the wrapper - -def default_id(space, w_obj): - import intobject - return intobject.W_IntObject(space, id(w_obj)) - -StdObjSpace.id.register(default_id, W_ANY) +class W_ObjectObject(W_Object): + """Instances of this class are what the user can directly see with an + 'object()' call. Internally, they play the important role of ,,,, + types. All such instances are implemented by the present W_UserObject + class.""" + #statictype = W_ObjectType (hacked into place below) -# this 'not' implementation should be fine for most cases +import objecttype +W_ObjectObject.statictype = objecttype.W_ObjectType +registerimplementation(W_ObjectObject) -def default_not(space, w_obj): - return space.newbool(not space.is_true(w_obj)) -StdObjSpace.not_.register(default_not, W_ANY) +# default global delegation from W_ANY to W_ObjectObject +W_ANY.delegate_once[W_ObjectObject] = None # None means identity function -# everything is True unless otherwise specified - -def default_is_true(space, w_obj): - return True - -StdObjSpace.is_true.register(default_is_true, W_ANY) +# these are the globally-defined operations that must appear as object.__xxx__. +# See also default.py. # give objects some default attributes and a default way to complain # about missing attributes -def default_getattr(space, w_obj, w_attr): +def object_getattr(space, w_obj, w_attr): # XXX build a nicer error message along these lines: #w_type = space.type(w_obj) #w_typename = space.getattr(w_type, space.wrap('__name__')) @@ -66,11 +35,29 @@ if space.is_true(space.eq(w_attr, space.wrap('__class__'))): return w_type - # XXX implement lookup as a multimethod + try: + w_dict = space.getdict(w_obj) + except OperationError, e: + # catch TypeError("unsupported type for getdict") + if not e.match(space, space.w_TypeError): + raise + else: + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + return w_dict + try: + w_value = space.getitem(w_dict, w_attr) + except OperationError, e: + # catch KeyErrors + if not e.match(space, space.w_KeyError): + raise + else: + return w_value # got a value from 'obj.__dict__[attr]' + + # XXX implement lookup as a multimethod? from typeobject import W_TypeObject if isinstance(w_type, W_TypeObject): # XXX must always be true at some point try: - w_value = w_type.lookup(space, w_attr) + w_value = w_type.lookup(w_attr) except KeyError: pass else: @@ -78,56 +65,59 @@ raise OperationError(space.w_AttributeError, w_attr) +StdObjSpace.getattr.register(object_getattr, W_ObjectObject, W_ANY) -StdObjSpace.getattr.register(default_getattr, W_ANY, W_ANY) - -def default_setattr(space, w_obj, w_attr, w_value): - raise OperationError(space.w_AttributeError, w_attr) -StdObjSpace.setattr.register(default_setattr, W_ANY, W_ANY, W_ANY) +# set attributes, complaining about read-only ones -- +# a more declarative way to define attributes would be welcome -def default_delattr(space, w_obj, w_attr, w_value): +def object_setattr(space, w_obj, w_attr, w_value): + if space.is_true(space.eq(w_attr, space.wrap('__class__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + try: + w_dict = space.getdict(w_obj) + except OperationError, e: + # catch TypeError("unsupported type for getdict") + if not e.match(space, space.w_TypeError): + raise + else: + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + space.setitem(w_dict, w_attr, w_value) + return + raise OperationError(space.w_AttributeError, w_attr) -StdObjSpace.delattr.register(default_delattr, W_ANY, W_ANY) +StdObjSpace.setattr.register(object_setattr, W_ObjectObject, W_ANY, W_ANY) -# in-place operators fall back to their non-in-place counterpart - -for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: - if _name.startswith('inplace_'): - def default_inplace(space, w_1, w_2, baseop=_name[8:]): - op = getattr(space, baseop) - return op(w_1, w_2) - getattr(StdObjSpace, _name).register(default_inplace, W_ANY, W_ANY) - - -# 'contains' falls back to iteration - -def default_contains(space, w_iterable, w_lookfor): - w_iter = space.iter(w_iterable) - while 1: - try: - w_next = space.next(w_iter) - except NoValue: - return space.w_False - if space.is_true(space.eq(w_next, w_lookfor)): - return space.w_True - -StdObjSpace.contains.register(default_contains, W_ANY, W_ANY) - - -# '__get__(descr, inst, cls)' returns 'descr' by default - -def default_get(space, w_descr, w_inst, w_cls): - return w_descr +def object_delattr(space, w_obj, w_attr): + if space.is_true(space.eq(w_attr, space.wrap('__class__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + try: + w_dict = space.getdict(w_obj) + except OperationError, e: + # catch TypeError("unsupported type for getdict") + if not e.match(space, space.w_TypeError): + raise + else: + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + space.delitem(w_dict, w_attr) + return + + raise OperationError(space.w_AttributeError, w_attr) -StdObjSpace.get.register(default_get, W_ANY, W_ANY, W_ANY) +StdObjSpace.delattr.register(object_delattr, W_ObjectObject, W_ANY) # static types -def default_type(space, w_obj): +def object_type(space, w_obj): if w_obj.statictype is None: # XXX remove me, temporary return space.wrap(space.unwrap(w_obj).__class__) @@ -135,15 +125,28 @@ w_type = space.get_typeinstance(w_obj.statictype) return w_type -StdObjSpace.type.register(default_type, W_ANY) +StdObjSpace.type.register(object_type, W_ObjectObject) -def default_str(space, w_obj): - return space.repr(w_obj) -StdObjSpace.str.register(default_str, W_ANY) +# repr() -def default_repr(space, w_obj): +def object_repr(space, w_obj): return space.wrap('<%s object at %s>'%( space.type(w_obj).typename, space.unwrap(space.id(w_obj)))) -StdObjSpace.repr.register(default_repr, W_ANY) +StdObjSpace.repr.register(object_repr, W_ObjectObject) + + +# str() defaults to repr() and hash() defaults to id(). +# these should really be defined in default.py, but in CPython they +# are visible in the 'object' class. + +def object_str(space, w_obj): + return space.repr(w_obj) + +StdObjSpace.str.register(object_str, W_ObjectObject) + +def object_hash(space, w_obj): + return space.id(w_obj) + +StdObjSpace.hash.register(object_hash, W_ObjectObject) Added: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Sun Jun 1 18:29:57 2003 @@ -0,0 +1,19 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_ObjectType(W_TypeObject): + """The single instance of W_ObjectType is what the user sees as + '__builtin__.object'.""" + + typename = 'object' + staticbases = () + + +# XXX we'll worry about the __new__/__init__ distinction later +def objecttype_new(space, w_objecttype, w_args, w_kwds): + # XXX 2.2 behavior: ignoring all arguments + from objectobject import W_ObjectObject + return W_ObjectObject(space) + +StdObjSpace.new.register(objecttype_new, W_ObjectType, W_ANY, W_ANY) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 1 18:29:57 2003 @@ -10,6 +10,7 @@ class W_Object: "Parent base class for wrapped objects." + delegate_once = {} statictype = None def __init__(w_self, space): @@ -19,6 +20,14 @@ return w_self.__class__ W_ANY = W_Object # synonyms for use in .register() +MultiMethod.ASSERT_BASE_TYPE = W_Object + + +def registerimplementation(implcls): + # this function should ultimately register the implementation class somewhere + # right now its only purpose is to make sure there is a + # delegate_once attribute. + implcls.__dict__.setdefault("delegate_once", {}) ################################################################## @@ -38,6 +47,7 @@ class result: "Import here the types you want to have appear in __builtin__." + from objecttype import W_ObjectType from booltype import W_BoolType from inttype import W_IntType from floattype import W_FloatType @@ -87,8 +97,8 @@ # self.setitem(self.w_builtins, self.wrap("__import__"), w_import) def get_typeinstance(self, typeclass): - assert hasattr(typeclass, 'typename'), \ - "get_typeinstance() cannot be used for W_UserType" + assert typeclass.typename is not None, ( + "get_typeinstance() cannot be used for %r" % typeclass) # types_w maps each W_XxxType class to its unique-for-this-space instance try: w_type = self.types_w[typeclass] @@ -171,24 +181,15 @@ is_true = MultiMethod('nonzero', 1, []) # returns an unwrapped bool # XXX do something about __nonzero__ ! -## # handling of the common fall-back cases -## def compare_any_any(self, w_1, w_2, operation): -## if operation == "is": -## return self.newbool(w_1 == w_2) -## elif operation == "is not": -## return self.newbool(w_1 != w_2) -## else: -## raise FailedToImplement(self.w_TypeError, -## "unknown comparison operator %r" % operation) - -## compare.register(compare_any_any, W_ANY, W_ANY) + getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute # add all regular multimethods to StdObjSpace for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: setattr(StdObjSpace, _name, MultiMethod(_symbol, _arity, _specialnames)) +# import the common base W_ObjectObject as well as # default implementations of some multimethods for all objects # that don't explicitely override them or that raise FailedToImplement - +import pypy.objspace.std.objectobject import pypy.objspace.std.default Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 1 18:29:57 2003 @@ -13,7 +13,6 @@ applicationfile = StdObjSpace.AppFile(__name__) class W_StringObject(W_Object): - delegate_once = {} statictype = W_StringType def __init__(w_self, space, str): @@ -24,11 +23,9 @@ """ representation for debugging purposes """ return "%s(%r)" % (w_self.__class__.__name__, w_self._value.value()) - def nonzero(w_self): - return W_IntObject(self.space, w_self._value.len != 0) - def hash(w_self): - return W_IntObject(self, self._value.hash()) +registerimplementation(W_StringObject) + def _isspace(ch): return ord(ch) in (9, 10, 11, 12, 13, 32) @@ -182,6 +179,11 @@ StdObjSpace.is_true.register(str_is_true, W_StringObject) +def str_hash(space, w_str): + return W_IntObject(space, w_str._value.hash()) + +StdObjSpace.hash.register(str_hash, W_StringObject) + EQ = 1 LE = 2 Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Sun Jun 1 18:29:57 2003 @@ -3,6 +3,7 @@ from pypy.objspace.std.multimethod import * +MultiMethod.ASSERT_BASE_TYPE = None W_ANY = object Modified: pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Sun Jun 1 18:29:57 2003 @@ -16,8 +16,9 @@ def test_int_sub(self): w = self.space.wrap for i in range(2): - meth = tobj.PyMultimethodCode(self.space.sub, i, self.space.w_int) - self.assertEqual(meth.multimethod.is_empty(), False) + meth = tobj.PyMultimethodCode(self.space.sub.multimethod, + i, self.space.w_int) + self.assertEqual(meth.slice().is_empty(), False) # test int.__sub__ and int.__rsub__ self.assertEqual_w(meth.eval_code(self.space, None, w({'x1': 5, 'x2': 7})), @@ -31,16 +32,17 @@ def test_empty_inplace_add(self): for i in range(2): - meth = tobj.PyMultimethodCode(self.space.inplace_add, i, - self.space.w_int) - self.assertEqual(meth.multimethod.is_empty(), True) + meth = tobj.PyMultimethodCode(self.space.inplace_add.multimethod, + i, self.space.w_int) + self.assertEqual(meth.slice().is_empty(), True) def test_float_sub(self): w = self.space.wrap w(1.5) # force floatobject imported for i in range(2): - meth = tobj.PyMultimethodCode(self.space.sub, i, self.space.w_float) - self.assertEqual(meth.multimethod.is_empty(), False) + meth = tobj.PyMultimethodCode(self.space.sub.multimethod, + i, self.space.w_float) + self.assertEqual(meth.slice().is_empty(), False) # test float.__sub__ and float.__rsub__ # some of these tests are pointless for Python because Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Sun Jun 1 18:29:57 2003 @@ -5,7 +5,6 @@ class W_TupleObject(W_Object): - delegate_once = {} statictype = W_TupleType def __init__(w_self, space, wrappeditems): @@ -18,6 +17,9 @@ return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist)) +registerimplementation(W_TupleObject) + + def tuple_unwrap(space, w_tuple): items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] return tuple(items) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sun Jun 1 18:29:57 2003 @@ -3,93 +3,131 @@ class W_TypeObject(W_Object): - delegate_once = {} - #statictype = W_TypeType (hacked into place in typetype.py) + """This class is abstract. Subclasses are defined in 'xxxtype.py' files. + The instances of these subclasses are what the user sees as Python's + type objects. This class defines all general type-oriented behavior + like attribute lookup and method resolution order. Inheritance + relationships are implemented *only* with the getbases() methods of + W_TypeObject subclasses, *not* with interpreter-level inheritance between + X_Xxx classes *nor* with multimethod delegation.""" + + typename = None # to be overridden by subclasses or instances + #statictype = W_TypeType (hacked into place below) + staticbases = None # defaults to (W_ObjectType,) def __init__(w_self, space): W_Object.__init__(w_self, space) w_self.w_tpname = space.wrap(w_self.typename) w_self.multimethods = {} # import all multimethods of the space and of the type class - for multimethod in (hack_out_multimethods(space) + - hack_out_multimethods(w_self)): + for multimethod in (hack_out_multimethods(space.__class__) + + hack_out_multimethods(w_self.__class__)): for i in range(len(multimethod.specialnames)): - w_self.multimethods[multimethod.specialnames[i]] = multimethod, i + # each PyMultimethodCode bytecode is a (lazy, cached, + # dynamically recomputed) slice of a multimethod. + code = PyMultimethodCode(multimethod, i, w_self) + w_self.multimethods[multimethod.specialnames[i]] = code + + def getbases(w_self): + parents = w_self.staticbases + if parents is None: + import objecttype + parents = (objecttype.W_ObjectType,) + basetypes = [w_self.space.get_typeinstance(parent) for parent in parents] + return tuple(basetypes) - def getbases(w_self, space): - return () - - def getmro(w_self, space): + def getmro(w_self): # XXX this is something that works not too bad right now # XXX do the complete mro thing later mro = [w_self] - for w_parent in w_self.getbases(space): - mro += w_parent.getmro(space) + for w_parent in w_self.getbases(): + mro += w_parent.getmro() return tuple(mro) -## XXX remove me -## def setup_builtin_type(w_self, implementation): -## implementation.statictype = w_self -## w_self.builtin_implementations.append(implementation) -## -## for key, value in implementation.__dict__.iteritems(): -## if isinstance(value, implmethod): -## try: -## multimethod, bound_pos = w_self.multimethods[key] -## except KeyError: -## sample = value.dispatch_table.keys()[0] -## multimethod = MultiMethod('%s()' % key, len(sample)+1, []) -## w_self.multimethods[key] = multimethod, None -## for types, func in value.dispatch_table.iteritems(): -## multimethod.register(func, implementation, *types) - - def lookup(w_self, space, w_key): + def lookup(w_self, w_key): "XXX at some point, turn this into a multimethod" # note that this doesn't call __get__ on the result at all - for w_class in w_self.getmro(space): + for w_class in w_self.getmro(): try: - return w_class.lookup_exactly_here(space, w_key) + return w_class.lookup_exactly_here(w_key) except KeyError: pass raise KeyError - def lookup_exactly_here(w_self, space, w_key): + def lookup_exactly_here(w_self, w_key): + space = w_self.space key = space.unwrap(w_key) assert isinstance(key, str) try: - multimethod, bound_pos = w_self.multimethods[key] + code = w_self.multimethods[key] except KeyError: - raise KeyError - multimethod = multimethod.__get__(space, None) - code = PyMultimethodCode(multimethod, bound_pos, w_self) - if code.multimethod.is_empty(): + raise KeyError # pass on the KeyError + if code.slice().is_empty(): raise KeyError return space.newfunction(code, space.w_None, space.w_None) + def acceptclass(w_self, cls): + # For multimethod slicing. This checks whether a Python object of + # type 'w_self' would be acceptable for a multimethod implementation + # defined on the 'W_Xxx' class specified by 'cls'. + # Currently implemented by following the 'statictype' attribute. + # This results in operations defined on W_ObjectObject to be accepted, + # but operations defined on W_ANY to be rejected. + statictypeclass = cls.statictype + if statictypeclass is not None: + for w_parent in w_self.getmro(): + if isinstance(w_parent, statictypeclass): + return True + return False + + +import typetype, objecttype +W_TypeObject.statictype = typetype.W_TypeType +registerimplementation(W_TypeObject) + -def hack_out_multimethods(instance): - return [value for value in instance.__class__.__dict__.itervalues() +def hack_out_multimethods(cls): + return [value for value in cls.__dict__.itervalues() if isinstance(value, MultiMethod)] class PyMultimethodCode(pycode.PyBaseCode): - - def __init__(self, multimethod, bound_position=None, w_type=None): + + def __init__(self, multimethod, bound_position, w_type): pycode.PyBaseCode.__init__(self) - argnames = ['x%d'%(i+1) for i in range(multimethod.multimethod.arity)] - if w_type is not None: - multimethod = multimethod.slicetable(bound_position, w_type) - argnames.insert(0, argnames.pop(bound_position)) - self.multimethod = multimethod - self.co_name = multimethod.multimethod.operatorsymbol + argnames = ['x%d'%(i+1) for i in range(multimethod.arity)] + argnames.insert(0, argnames.pop(bound_position)) + self.co_name = multimethod.operatorsymbol self.co_flags = 0 self.co_varnames = tuple(argnames) - self.co_argcount = multimethod.multimethod.arity + self.co_argcount = multimethod.arity + self.basemultimethod = multimethod + self.slicedmultimethod = None + self.bound_position = bound_position + self.w_type = w_type + + def cleardependency(self): + # called when the underlying dispatch table is modified + self.slicedmultimethod = None + + def slice(self): + if self.slicedmultimethod is None: + multimethod = self.basemultimethod + print "pypy: slicing %r for a %r argument at position %d" % ( + multimethod.operatorsymbol, + self.w_type.typename, self.bound_position) + # slice the multimethod and cache the result + sliced = multimethod.slicetable(self.bound_position, self.w_type) + if sliced.is_empty(): + print "the slice is empty" + self.slicedmultimethod = sliced.__get__(self.w_type.space, None) + multimethod.cache_dependency(self) + return self.slicedmultimethod def eval_code(self, space, w_globals, w_locals): """Call the multimethod, ignoring all implementations that do not have exactly the expected type at the bound_position.""" - multimethod = self.multimethod + multimethod = self.slice() dispatchargs = [] initialtypes = [] for i in range(multimethod.multimethod.arity): @@ -99,43 +137,27 @@ dispatchargs = tuple(dispatchargs) initialtypes = tuple(initialtypes) try: - return multimethod.perform_call(dispatchargs, initialtypes) + w_result = multimethod.perform_call(dispatchargs, initialtypes) except FailedToImplement, e: if e.args: raise OperationError(*e.args) else: return space.w_NotImplemented + # XXX hack to accept real Nones from operations with no return value + if w_result is None: + w_result = space.w_None + return w_result def type_call(space, w_type, w_args, w_kwds): w_newobject = space.new(w_type, w_args, w_kwds) # XXX call __init__() later return w_newobject - -## # H H AA CCC K K -## # H H A A C K K -## # HHHH A A C KK -## # H H AAAA C K K -## # H H A A CCC K K - -## tpname = space.unwrap(w_type.w_tpname) -## args = space.unpackiterable(w_args) -## if tpname == 'type': -## assert len(args) == 1 -## return space.type(args[0]) -## if tpname == 'list': -## assert len(args) == 1 -## return space.newlist(space.unpackiterable(args[0])) -## if tpname == 'tuple': -## assert len(args) == 1 -## return space.newtuple(space.unpackiterable(args[0])) -## if tpname == 'str': -## assert len(args) == 1 -## return space.str(args[0]) - -## import __builtin__ -## hacky = getattr(__builtin__, tpname)( -## *space.unwrap(w_args), **space.unwrap(w_kwds)) -## return space.wrap(hacky) StdObjSpace.call.register(type_call, W_TypeObject, W_ANY, W_ANY) + + +def type_issubtype(space, w_type1, w_type2): + return space.newbool(w_type2 in w_type1.getmro()) + +StdObjSpace.issubtype.register(type_issubtype, W_TypeObject, W_TypeObject) Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Sun Jun 1 18:29:57 2003 @@ -3,14 +3,12 @@ class W_TypeType(W_TypeObject): + """The single instance of this class is the object the user sees as + '__builtin__.type'.""" typename = 'type' -# hack that in place -W_TypeObject.statictype = W_TypeType - - # XXX we'll worry about the __new__/__init__ distinction later def typetype_new(space, w_typetype, w_args, w_kwds): if space.is_true(w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Sun Jun 1 18:29:57 2003 @@ -4,40 +4,114 @@ class W_UserObject(W_Object): - delegate_once = {} - - def __init__(w_self, space, w_type): - W_Object.__init__(w_self, space) - w_self.w_type = w_type - w_self.w_dict = space.newdict([]) + """Instances of this class are what the user sees as instances of custom + types. All such instances are implemented by the present W_UserObject + class.""" + statictype = W_UserType + + # Nota Bene: we expect W_UserObject instances whose type inherits + # from a built-in type to also contain the attributes of the + # corresponding W_XxxObject class. This is a non-restricted-Python- + # compliant hack that we may have to rethink at some point. + # It is similar to CPython's instances of subtypes of built-in + # types whose memory layout start with what looks like an instance + # of the parent built-in type. + + def __init__(w_self, space, w_type, w_args, w_kwds): + # the restriction that a single built-in type is allowed among the + # bases is specific to our W_UserObject implementation of user + # objects, and should thus not be enforced in W_UserType. + w_builtintype = getsinglebuiltintype(space, w_type) + + # first create an instance of the parent built-in type + w_preself = space.call(w_builtintype, w_args, w_kwds) + if not space.is_true(space.is_(space.type(w_preself), w_builtintype)): + raise OperationError(space.w_TypeError, + space.wrap("instantiating a subtype of a type " + "with a misbehaving constructor")) + + # clone the instance layout into w_self + w_self.__dict__.update(w_preself.__dict__) + + # add custom attributes + w_self.w_uo_type = w_type + w_self.w_uo_dict = space.newdict([]) + w_self.w_uo_impl_class = w_preself.__class__ + + def get_builtin_impl_class(w_self): + return w_self.w_uo_impl_class + + +registerimplementation(W_UserObject) + + +def getsinglebuiltintype(space, w_type): + "Return the (asserted unique) built-in type that w_type inherits from." + mostspecialized = space.w_object + mro = list(w_type.getmro()) + mro.reverse() + for w_base in mro: + if not isinstance(w_base, W_UserType): + if not space.is_true(space.issubtype(w_base, mostspecialized)): + raise OperationError(space.w_TypeError, + space.wrap("instance layout conflicts in " + "multiple inheritance")) + mostspecialized = w_base + return mostspecialized def user_type(space, w_userobj): - return w_userobj.w_type + return w_userobj.w_uo_type StdObjSpace.type.register(user_type, W_UserObject) -def user_getattr(space, w_userobj, w_attr): - try: - w_value = space.getitem(w_userobj.w_dict, w_attr) - except OperationError, e: - # catch KeyErrors - if not e.match(space, space.w_KeyError): - raise - raise FailedToImplement(space.w_AttributeError) - return w_value - -StdObjSpace.getattr.register(user_getattr, W_UserObject, W_ANY) - - -def user_setattr(space, w_userobj, w_attr, w_value): - space.setitem(w_userobj.w_dict, w_attr, w_value) - -StdObjSpace.setattr.register(user_setattr, W_UserObject, W_ANY, W_ANY) - - -def user_delattr(space, w_userobj, w_attr): - space.delitem(w_userobj.w_dict, w_attr) - -StdObjSpace.delattr.register(user_delattr, W_UserObject, W_ANY) +def user_getdict(space, w_userobj): + # XXX check getdict() of the base built-in implementation + return w_userobj.w_uo_dict + +StdObjSpace.getdict.register(user_getdict, W_UserObject) + + +# We register here all multimethods with at least one W_UserObject. +# No multimethod must be explicitely registered on W_UserObject except +# here, unless you want to completely override a behavior for user-defined +# types, as in user_type and user_getdict. + +def build_user_operation(multimethod): + def user_operation(space, *args_w): + if len(args_w) != multimethod.arity: + raise TypeError, "wrong number of arguments" + for i in range(len(multimethod.specialnames)): + w_arg = args_w[i] + if isinstance(w_arg, W_UserObject): + specialname = multimethod.specialnames[i] + try: + w_value = w_arg.w_uo_type.lookup(space.wrap(specialname)) + except KeyError: + pass + else: + # 'w_value' is a __xxx__ function object + w_value = space.get(w_value, w_arg, w_arg.w_uo_type) + # 'w_value' is now a bound method. + # if it is a sliced multimethod it should do the + # get_builtin_impl_class() trick automatically, not + # dispatching again on W_UserObject. + rest_args = list(args_w) + del rest_args[i] + w_args_w = space.newtuple(rest_args) + w_result = space.call(w_value, w_args_w, space.newdict([])) + if not space.is_true(space.is_(w_result, + space.w_NotImplemented)): + return w_result # if w_result is not NotImplemented + raise FailedToImplement + return user_operation + +for multimethod in typeobject.hack_out_multimethods(StdObjSpace): + if multimethod not in (StdObjSpace.getdict, + StdObjSpace.type): + user_operation = build_user_operation(multimethod) + for i in range(multimethod.arity): + signature = [W_ANY] * multimethod.arity + signature[i] = W_UserObject + multimethod.register(user_operation, *signature) Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Sun Jun 1 18:29:57 2003 @@ -1,8 +1,14 @@ +from __future__ import nested_scopes from pypy.objspace.std.objspace import * +import typeobject, objecttype from typeobject import W_TypeObject class W_UserType(W_TypeObject): + """Instances of this class are user-defined Python type objects. + All user-defined types are instances of the present class. + Builtin-in types, on the other hand, each have their own W_XxxType + class.""" # 'typename' is an instance property here @@ -13,10 +19,15 @@ w_self.w_bases = w_bases w_self.w_dict = w_dict - def getbases(w_self, space): - return space.unpackiterable(w_self.w_bases) + def getbases(w_self): + bases = w_self.space.unpackiterable(w_self.w_bases) + if bases: + return bases + else: + return W_TypeObject.getbases(w_self) # defaults to (w_object,) - def lookup_exactly_here(w_self, space, w_key): + def lookup_exactly_here(w_self, w_key): + space = w_self.space try: w_value = space.getitem(w_self.w_dict, w_key) except OperationError, e: @@ -31,6 +42,6 @@ def usertype_new(space, w_usertype, w_args, w_kwds): # XXX no __init__ support at all here from userobject import W_UserObject - return W_UserObject(space, w_usertype) + return W_UserObject(space, w_usertype, w_args, w_kwds) StdObjSpace.new.register(usertype_new, W_UserType, W_ANY, W_ANY) Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Sun Jun 1 18:29:57 2003 @@ -21,7 +21,8 @@ "None" : self.w_None, } for n, c in __builtin__.__dict__.iteritems(): - if isinstance(c, types.ClassType) and issubclass(c, Exception): + if ((isinstance(c, types.ClassType) and issubclass(c, Exception)) or + isinstance(c, types.TypeType)): w_c = c setattr(self, 'w_' + c.__name__, w_c) newstuff[c.__name__] = w_c From arigo at codespeak.net Mon Jun 2 15:19:10 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Jun 2003 15:19:10 +0200 (MEST) Subject: [pypy-svn] rev 746 - in pypy/trunk/src/pypy/module: . test Message-ID: <20030602131910.E17355A126@thoth.codespeak.net> Author: arigo Date: Mon Jun 2 15:19:09 2003 New Revision: 746 Modified: pypy/trunk/src/pypy/module/builtin_app.py pypy/trunk/src/pypy/module/test/test_minmax.py Log: min([]) and max([]) raise ValueError Modified: pypy/trunk/src/pypy/module/builtin_app.py ============================================================================== --- pypy/trunk/src/pypy/module/builtin_app.py (original) +++ pypy/trunk/src/pypy/module/builtin_app.py Mon Jun 2 15:19:09 2003 @@ -169,8 +169,13 @@ if len(arr) == 1: arr = arr[0] - min = arr[0] - for i in arr: + iterator = iter(arr) + try: + min = iterator.next() + except StopIteration: + raise ValueError, 'min() arg is an empty sequence' + + for i in iterator: if min > i: min = i return min @@ -183,9 +188,14 @@ if len(arr) == 1: arr = arr[0] - - max = arr[0] - for i in arr: + + iterator = iter(arr) + try: + max = iterator.next() + except StopIteration: + raise ValueError, 'max() arg is an empty sequence' + + for i in iterator: if max < i: max = i return max @@ -210,6 +220,6 @@ raise TypeError, "vars() takes at most 1 argument." else: try: - return obj.__dict__ + return obj[0].__dict__ except AttributeError: raise TypeError, "vars() argument must have __dict__ attribute" Modified: pypy/trunk/src/pypy/module/test/test_minmax.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_minmax.py (original) +++ pypy/trunk/src/pypy/module/test/test_minmax.py Mon Jun 2 15:19:09 2003 @@ -36,6 +36,9 @@ def test_min_noargs(self): self.assertRaises(TypeError, min) + def test_min_empty(self): + self.assertRaises(ValueError, min, []) + class TestMax(testsupport.TestCase): def setUp(self): @@ -71,7 +74,8 @@ def test_max_noargs(self): self.assertRaises(TypeError, max) + def test_max_empty(self): + self.assertRaises(ValueError, max, []) + if __name__ == '__main__': testsupport.main() - - From arigo at codespeak.net Mon Jun 2 15:19:47 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Jun 2003 15:19:47 +0200 (MEST) Subject: [pypy-svn] rev 747 - in pypy/trunk/src/pypy: interpreter objspace/std Message-ID: <20030602131947.C74355A126@thoth.codespeak.net> Author: arigo Date: Mon Jun 2 15:19:47 2003 New Revision: 747 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: .next() crash fix Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Mon Jun 2 15:19:47 2003 @@ -139,7 +139,10 @@ exc_typename = space.unwrap(self.w_type).__name__ exc_value = space.unwrap(self.w_value) print >> file, '(application-level)', - print >> file, exc_typename+':', exc_value + if exc_value is None: + print >> file, exc_typename + else: + print >> file, exc_typename+':', exc_value class NoValue(Exception): Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Mon Jun 2 15:19:47 2003 @@ -143,6 +143,8 @@ raise OperationError(*e.args) else: return space.w_NotImplemented + except NoValue: + raise OperationError(space.w_StopIteration, space.w_None) # XXX hack to accept real Nones from operations with no return value if w_result is None: w_result = space.w_None From arigo at codespeak.net Mon Jun 2 15:40:13 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Jun 2003 15:40:13 +0200 (MEST) Subject: [pypy-svn] rev 748 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030602134013.BC95C5A126@thoth.codespeak.net> Author: arigo Date: Mon Jun 2 15:40:13 2003 New Revision: 748 Modified: pypy/trunk/src/pypy/objspace/std/listtype.py pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: object methods can now have (simple) default values Modified: pypy/trunk/src/pypy/objspace/std/listtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/listtype.py Mon Jun 2 15:40:13 2003 @@ -9,7 +9,7 @@ list_append = MultiMethod('append', 2) list_insert = MultiMethod('insert', 3) list_extend = MultiMethod('extend', 2) - list_pop = MultiMethod('pop', 2) + list_pop = MultiMethod('pop', 2, defaults=(-1,)) list_remove = MultiMethod('remove', 2) list_index = MultiMethod('index', 2) list_count = MultiMethod('count', 2) Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Mon Jun 2 15:40:13 2003 @@ -9,7 +9,7 @@ ASSERT_BASE_TYPE = None - def __init__(self, operatorsymbol, arity, specialnames=None): + def __init__(self, operatorsymbol, arity, specialnames=None, defaults=()): "MultiMethod dispatching on the first 'arity' arguments." self.arity = arity self.operatorsymbol = operatorsymbol @@ -17,6 +17,7 @@ if specialnames is None: specialnames = [operatorsymbol] self.specialnames = specialnames # list like ['__xxx__', '__rxxx__'] + self.defaults = defaults self.cache_dependencies = {} self.cache_table = {} Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 2 15:40:13 2003 @@ -307,7 +307,7 @@ r[i] = space.getitem(w_str, w(start + i*step)) w_r = space.newlist(r) w_empty = space.newstring([]) - return str_join(w_empty, w_r) + return str_join(space, w_empty, w_r) StdObjSpace.getitem.register(getitem_str_slice, W_StringObject, W_SliceObject) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Mon Jun 2 15:40:13 2003 @@ -7,7 +7,7 @@ typename = 'str' str_join = MultiMethod('join', 2) - str_split = MultiMethod('split', 2) + str_split = MultiMethod('split', 2, defaults=(None,)) str_isdigit = MultiMethod('isdigit', 1) str_isalpha = MultiMethod('isalpha', 1) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Mon Jun 2 15:40:13 2003 @@ -64,7 +64,7 @@ raise KeyError # pass on the KeyError if code.slice().is_empty(): raise KeyError - return space.newfunction(code, space.w_None, space.w_None) + return space.newfunction(code, space.w_None, code.getdefaults(space)) def acceptclass(w_self, cls): # For multimethod slicing. This checks whether a Python object of @@ -106,6 +106,9 @@ self.bound_position = bound_position self.w_type = w_type + def getdefaults(self, space): + return space.wrap(self.basemultimethod.defaults) + def cleardependency(self): # called when the underlying dispatch table is modified self.slicedmultimethod = None From mwh at codespeak.net Thu Jun 5 15:48:39 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 5 Jun 2003 15:48:39 +0200 (MEST) Subject: [pypy-svn] rev 749 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030605134839.89DC75A5B5@thoth.codespeak.net> Author: mwh Date: Thu Jun 5 15:48:38 2003 New Revision: 749 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: Make Exceptions UserTypes Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Thu Jun 5 15:48:38 2003 @@ -59,7 +59,41 @@ return [value for key, value in result.__dict__.items() if not key.startswith('_')] # don't look - + def clone_exception_heirachy(self): + import exceptions + from usertype import W_UserType + self.w_Exception = W_UserType(self, + self.wrap("Exception"), + self.newtuple([]), + self.newdict([])) + done = {'Exception': self.w_Exception} + self.w_IndexError = self.w_Exception + for k in dir(exceptions): + v = getattr(exceptions, k) + if isinstance(v, str): + continue + stack = [k] + while stack: + next = stack[-1] + nextv = getattr(exceptions, next) + if next in done: + stack.pop() + else: + nb = nextv.__bases__[0] + w_nb = done.get(nb.__name__) + if w_nb is None: + stack.append(nb.__name__) + else: + w_exc = self.call_function( + self.w_type, + self.wrap(next), + self.newtuple([w_nb]), + self.newdict([])) + setattr(self, 'w_' + next, w_exc) + done[next] = w_exc + stack.pop() + return done + def initialize(self): from noneobject import W_NoneObject from boolobject import W_BoolObject @@ -75,18 +109,18 @@ "None" : self.w_None, "NotImplemented": self.w_NotImplemented, } - for n, c in __builtin__.__dict__.iteritems(): - if isinstance(c, types.ClassType) and issubclass(c, Exception): - w_c = W_CPythonObject(self, c) - setattr(self, 'w_' + c.__name__, w_c) - newstuff[c.__name__] = w_c +# for n, c in __builtin__.__dict__.iteritems(): +# if isinstance(c, types.ClassType) and issubclass(c, Exception): +# w_c = W_CPythonObject(self, c) +# setattr(self, 'w_' + c.__name__, w_c) +# newstuff[c.__name__] = w_c # make the types self.types_w = {} for typeclass in self.standard_types(): w_type = self.get_typeinstance(typeclass) setattr(self, 'w_' + typeclass.typename, w_type) newstuff[typeclass.typename] = w_type - + newstuff.update(self.clone_exception_heirachy()) self.make_builtins() self.make_sys() # insert these into the newly-made builtins From arigo at codespeak.net Thu Jun 5 17:42:08 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Jun 2003 17:42:08 +0200 (MEST) Subject: [pypy-svn] rev 750 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030605154208.A90DF5A5B5@thoth.codespeak.net> Author: arigo Date: Thu Jun 5 17:42:08 2003 New Revision: 750 Modified: pypy/trunk/src/pypy/objspace/std/userobject.py Log: fixed subclassing problem described in pypy-dev Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Thu Jun 5 17:42:08 2003 @@ -30,16 +30,27 @@ space.wrap("instantiating a subtype of a type " "with a misbehaving constructor")) - # clone the instance layout into w_self - w_self.__dict__.update(w_preself.__dict__) - # add custom attributes - w_self.w_uo_type = w_type - w_self.w_uo_dict = space.newdict([]) - w_self.w_uo_impl_class = w_preself.__class__ + w_self.__dict__.update( + {'w_uo_preself': w_preself, + 'w_uo_type': w_type, + 'w_uo_dict': space.newdict([]), + }) + + def __getattr__(w_self, attr): + return getattr(w_self.w_uo_preself, attr) + + def __setattr__(w_self, attr, value): + if attr in w_self.__dict__: + w_self.__dict__[attr] = value + else: + setattr(w_self.w_preself, attr, value) + + def __delattr__(w_self, attr): + raise AttributeError, "we don't wants attribute deletion in RPython" def get_builtin_impl_class(w_self): - return w_self.w_uo_impl_class + return w_self.w_uo_preself.get_builtin_impl_class() registerimplementation(W_UserObject) From arigo at codespeak.net Thu Jun 5 17:48:30 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Jun 2003 17:48:30 +0200 (MEST) Subject: [pypy-svn] rev 751 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030605154830.5F9475A5B5@thoth.codespeak.net> Author: arigo Date: Thu Jun 5 17:48:29 2003 New Revision: 751 Added: pypy/trunk/src/pypy/objspace/std/slicetype.py Modified: pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/sliceobject.py Log: added slicetype.py Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Thu Jun 5 17:48:29 2003 @@ -56,6 +56,7 @@ from dicttype import W_DictType from stringtype import W_StringType from typetype import W_TypeType + from slicetype import W_SliceType return [value for key, value in result.__dict__.items() if not key.startswith('_')] # don't look Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Thu Jun 5 17:48:29 2003 @@ -2,11 +2,14 @@ from pypy.interpreter.appfile import AppFile from pypy.interpreter.extmodule import make_builtin_func from pypy.objspace.std.instmethobject import W_InstMethObject +from slicetype import W_SliceType appfile = AppFile(__name__, ["objspace.std"]) class W_SliceObject(W_Object): + statictype = W_SliceType + def __init__(w_self, space, w_start, w_stop, w_step): W_Object.__init__(w_self, space) w_self.w_start = w_start @@ -20,6 +23,9 @@ return w_self.space.newtuple(w_self.indices(w_length)[:-1]) +registerimplementation(W_SliceObject) + + def getattr_slice_any(space, w_slice, w_attr): if space.is_true(space.eq(w_attr, space.wrap('start'))): if w_slice.w_start is None: Added: pypy/trunk/src/pypy/objspace/std/slicetype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/slicetype.py Thu Jun 5 17:48:29 2003 @@ -0,0 +1,7 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_SliceType(W_TypeObject): + + typename = 'slice' From hpk at codespeak.net Sat Jun 7 08:46:55 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 7 Jun 2003 08:46:55 +0200 (MEST) Subject: [pypy-svn] rev 770 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607064655.AF7365AEBE@thoth.codespeak.net> Author: hpk Date: Sat Jun 7 08:46:54 2003 New Revision: 770 Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py Log: added a more correct "repr" so that when you do repr(list), repr(tuple) you get the usual output. I hope this was the correct way to do it. Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sat Jun 7 08:46:54 2003 @@ -166,3 +166,8 @@ return space.newbool(w_type2 in w_type1.getmro()) StdObjSpace.issubtype.register(type_issubtype, W_TypeObject, W_TypeObject) + +def type_repr(space, w_obj): + return space.wrap("" % w_obj.typename) + +StdObjSpace.repr.register(type_repr, W_TypeObject) From mwh at codespeak.net Sat Jun 7 19:49:54 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 19:49:54 +0200 (MEST) Subject: [pypy-svn] rev 772 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607174954.E2B905ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 19:49:54 2003 New Revision: 772 Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py Log: add boolean reprs Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Sat Jun 7 19:49:54 2003 @@ -29,3 +29,12 @@ StdObjSpace.is_true.register(bool_is_true, W_BoolObject) StdObjSpace.unwrap. register(bool_is_true, W_BoolObject) + +def bool_repr(space, w_bool): + if w_bool.boolval: + return space.wrap('True') + else: + return space.wrap('False') + +StdObjSpace.repr.register(bool_repr, W_BoolObject) + From mwh at codespeak.net Sat Jun 7 19:58:08 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 19:58:08 +0200 (MEST) Subject: [pypy-svn] rev 773 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607175808.D8FEC5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 19:58:08 2003 New Revision: 773 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: Tidy some things up. Add __init__ method to Exception. Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sat Jun 7 19:58:08 2003 @@ -61,75 +61,99 @@ if not key.startswith('_')] # don't look def clone_exception_heirachy(self): - import exceptions from usertype import W_UserType - self.w_Exception = W_UserType(self, - self.wrap("Exception"), - self.newtuple([]), - self.newdict([])) - done = {'Exception': self.w_Exception} + from funcobject import W_FuncObject + from pypy.interpreter.pycode import PyByteCode + w = self.wrap + def __init__(self, *args): + self.args = args + code = PyByteCode() + code._from_code(__init__.func_code) + w_init = W_FuncObject(self, code, + self.newdict([]), self.newtuple([]), None) +# w_init = w(__init__) # should this work? --mwh + import exceptions + + # to create types, we should call the standard type object; + # but being able to do that depends on the existence of some + # of the exceptions... + + self.w_Exception = W_UserType( + self, + w('Exception'), + self.newtuple([]), + self.newdict([(w('__init__'), w_init)])) self.w_IndexError = self.w_Exception + + done = {'Exception': self.w_Exception} + + # some of the complexity of the following is due to the fact + # that we need to create the tree root first, but the only + # connections we have go in the inconvenient direction... + for k in dir(exceptions): - v = getattr(exceptions, k) - if isinstance(v, str): - continue - stack = [k] - while stack: - next = stack[-1] - nextv = getattr(exceptions, next) - if next in done: - stack.pop() - else: - nb = nextv.__bases__[0] - w_nb = done.get(nb.__name__) - if w_nb is None: - stack.append(nb.__name__) + if k not in done: + v = getattr(exceptions, k) + if isinstance(v, str): + continue + stack = [k] + while stack: + next = stack[-1] + if next not in done: + v = getattr(exceptions, next) + b = v.__bases__[0] + if b.__name__ not in done: + stack.append(b.__name__) + continue + else: + base = done[b.__name__] + newtype = self.call_function( + self.w_type, + w(k), + self.newtuple([base]), + self.newdict([])) + setattr(self, + 'w_' + next, + newtype) + done[next] = newtype + stack.pop() else: - w_exc = self.call_function( - self.w_type, - self.wrap(next), - self.newtuple([w_nb]), - self.newdict([])) - setattr(self, 'w_' + next, w_exc) - done[next] = w_exc stack.pop() return done - + def initialize(self): from noneobject import W_NoneObject from boolobject import W_BoolObject from cpythonobject import W_CPythonObject + + # singletons self.w_None = W_NoneObject(self) self.w_False = W_BoolObject(self, False) self.w_True = W_BoolObject(self, True) self.w_NotImplemented = self.wrap(NotImplemented) # XXX do me - # hack in the exception classes - import __builtin__, types - newstuff = {"False": self.w_False, - "True" : self.w_True, - "None" : self.w_None, - "NotImplemented": self.w_NotImplemented, - } -# for n, c in __builtin__.__dict__.iteritems(): -# if isinstance(c, types.ClassType) and issubclass(c, Exception): -# w_c = W_CPythonObject(self, c) -# setattr(self, 'w_' + c.__name__, w_c) -# newstuff[c.__name__] = w_c - # make the types + + for_builtins = {"False": self.w_False, + "True" : self.w_True, + "None" : self.w_None, + "NotImplemented": self.w_NotImplemented, + } + + # types self.types_w = {} for typeclass in self.standard_types(): w_type = self.get_typeinstance(typeclass) setattr(self, 'w_' + typeclass.typename, w_type) - newstuff[typeclass.typename] = w_type - newstuff.update(self.clone_exception_heirachy()) + for_builtins[typeclass.typename] = w_type + + # exceptions + for_builtins.update(self.clone_exception_heirachy()) + self.make_builtins() self.make_sys() - # insert these into the newly-made builtins - for key, w_value in newstuff.items(): + + # insert stuff into the newly-made builtins + for key, w_value in for_builtins.items(): self.setitem(self.w_builtins, self.wrap(key), w_value) - # add a dummy __import__ XXX fixme -# w_import = self.wrap(__import__) -# self.setitem(self.w_builtins, self.wrap("__import__"), w_import) def get_typeinstance(self, typeclass): assert typeclass.typename is not None, ( From mwh at codespeak.net Sat Jun 7 20:00:15 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:00:15 +0200 (MEST) Subject: [pypy-svn] rev 774 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607180015.0EC195ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:00:14 2003 New Revision: 774 Modified: pypy/trunk/src/pypy/objspace/std/usertype.py Log: add debugging repr add support for __init__ Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Sat Jun 7 20:00:14 2003 @@ -19,6 +19,9 @@ w_self.w_bases = w_bases w_self.w_dict = w_dict + def __repr__(self): + return ''%(self.space.unwrap(self.w_name),) + def getbases(w_self): bases = w_self.space.unpackiterable(w_self.w_bases) if bases: @@ -40,8 +43,16 @@ # XXX we'll worry about the __new__/__init__ distinction later def usertype_new(space, w_usertype, w_args, w_kwds): - # XXX no __init__ support at all here from userobject import W_UserObject - return W_UserObject(space, w_usertype, w_args, w_kwds) + newobj = W_UserObject(space, w_usertype) + try: + init = space.getattr(newobj, space.wrap('__init__')) + except OperationError, err: + if not err.match(space, space.w_AttributeError): + raise + else: + space.call(init, w_args, w_kwds) + return newobj + StdObjSpace.new.register(usertype_new, W_UserType, W_ANY, W_ANY) From mwh at codespeak.net Sat Jun 7 20:04:37 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:04:37 +0200 (MEST) Subject: [pypy-svn] rev 775 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607180437.5FEFE5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:04:37 2003 New Revision: 775 Modified: pypy/trunk/src/pypy/objspace/std/usertype.py Log: fix mis-merge Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Sat Jun 7 20:04:37 2003 @@ -44,7 +44,7 @@ # XXX we'll worry about the __new__/__init__ distinction later def usertype_new(space, w_usertype, w_args, w_kwds): from userobject import W_UserObject - newobj = W_UserObject(space, w_usertype) + newobj = W_UserObject(space, w_usertype, w_args, w_kwds) try: init = space.getattr(newobj, space.wrap('__init__')) except OperationError, err: From mwh at codespeak.net Sat Jun 7 20:07:21 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:07:21 +0200 (MEST) Subject: [pypy-svn] rev 776 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030607180721.EA1D85ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:07:21 2003 New Revision: 776 Removed: pypy/trunk/src/pypy/interpreter/test/support.py Log: this file is dead Deleted: pypy/trunk/src/pypy/interpreter/test/support.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/support.py Sat Jun 7 20:07:21 2003 +++ (empty file) @@ -1,9 +0,0 @@ -import sys, os - -opd = os.path.dirname - -testdir = opd(os.path.abspath(__file__)) -parentdir = opd(testdir) -rootdir = opd(parentdir) - -sys.path.insert(0, opd(rootdir)) From mwh at codespeak.net Sat Jun 7 20:24:30 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:24:30 +0200 (MEST) Subject: [pypy-svn] rev 777 - in pypy/trunk/src/pypy: . appspace/test interpreterinterpreter/test module/test objspace/std/test Message-ID: <20030607182430.6D9E45ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:24:29 2003 New Revision: 777 Modified: pypy/trunk/src/pypy/appspace/test/testsupport.py pypy/trunk/src/pypy/interpreter/test/testsupport.py pypy/trunk/src/pypy/interpreter/testsupport.py pypy/trunk/src/pypy/interpreter/testtools.py pypy/trunk/src/pypy/module/test/testsupport.py pypy/trunk/src/pypy/objspace/std/test/testsupport.py pypy/trunk/src/pypy/testsupport.py Log: testsupport tweaks notable changes: - this doesn't bother to interpret the contents of $OBJSPACE as much as before, it just assumes that if it's present and contains a dot you want the standard object space. - we now use the same objspace object for each test Modified: pypy/trunk/src/pypy/appspace/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/testsupport.py (original) +++ pypy/trunk/src/pypy/appspace/test/testsupport.py Sat Jun 7 20:24:29 2003 @@ -21,7 +21,9 @@ When run as a script, runs all tests found in files called 'test_*.py' in the same directory. """ -import sys, os +import sys +import os +import unittest try: head = this_path = os.path.abspath(__file__) @@ -39,26 +41,11 @@ break import pypy.interpreter.unittest_w +from pypy.interpreter.testtools import * + TestCase = pypy.interpreter.unittest_w.TestCase_w -import unittest main = unittest.main -from pypy.interpreter import testtools - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - import pypy.objspace.trivial - return pypy.objspace.trivial.TrivialObjSpace() - else: - objspace_pieces = objspace_path.split('.') - objspace_path = '.'.join(objspace_pieces[:-1]) - objspace_module = __import__(objspace_path) - for piece in objspace_pieces[1:-1]: - objspace_module = getattr(objspace_module, piece) - objspace_classname = objspace_pieces[-1] - return getattr(objspace_module, objspace_classname)() - if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(testtools.get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) Modified: pypy/trunk/src/pypy/interpreter/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/testsupport.py (original) +++ pypy/trunk/src/pypy/interpreter/test/testsupport.py Sat Jun 7 20:24:29 2003 @@ -21,7 +21,9 @@ When run as a script, runs all tests found in files called 'test_*.py' in the same directory. """ -import sys, os +import sys +import os +import unittest try: head = this_path = os.path.abspath(__file__) @@ -39,26 +41,11 @@ break import pypy.interpreter.unittest_w +from pypy.interpreter.testtools import * + TestCase = pypy.interpreter.unittest_w.TestCase_w -import unittest main = unittest.main -from pypy.interpreter import testtools - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - import pypy.objspace.trivial - return pypy.objspace.trivial.TrivialObjSpace() - else: - objspace_pieces = objspace_path.split('.') - objspace_path = '.'.join(objspace_pieces[:-1]) - objspace_module = __import__(objspace_path) - for piece in objspace_pieces[1:-1]: - objspace_module = getattr(objspace_module, piece) - objspace_classname = objspace_pieces[-1] - return getattr(objspace_module, objspace_classname)() - if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(testtools.get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) Modified: pypy/trunk/src/pypy/interpreter/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/testsupport.py (original) +++ pypy/trunk/src/pypy/interpreter/testsupport.py Sat Jun 7 20:24:29 2003 @@ -21,7 +21,9 @@ When run as a script, runs all tests found in files called 'test_*.py' in the same directory. """ -import sys, os +import sys +import os +import unittest try: head = this_path = os.path.abspath(__file__) @@ -39,26 +41,11 @@ break import pypy.interpreter.unittest_w +from pypy.interpreter.testtools import * + TestCase = pypy.interpreter.unittest_w.TestCase_w -import unittest main = unittest.main -from pypy.interpreter import testtools - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - import pypy.objspace.trivial - return pypy.objspace.trivial.TrivialObjSpace() - else: - objspace_pieces = objspace_path.split('.') - objspace_path = '.'.join(objspace_pieces[:-1]) - objspace_module = __import__(objspace_path) - for piece in objspace_pieces[1:-1]: - objspace_module = getattr(objspace_module, piece) - objspace_classname = objspace_pieces[-1] - return getattr(objspace_module, objspace_classname)() - if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(testtools.get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) Modified: pypy/trunk/src/pypy/interpreter/testtools.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/testtools.py (original) +++ pypy/trunk/src/pypy/interpreter/testtools.py Sat Jun 7 20:24:29 2003 @@ -3,7 +3,8 @@ def get_tests_for_dir(directory): files = os.listdir(directory) - testfiles = [f[:-3] for f in files if f.startswith('test_') and f.endswith('.py')] + testfiles = [f[:-3] for f in files + if f.startswith('test_') and f.endswith('.py')] ts = unittest.TestSuite() @@ -14,5 +15,30 @@ ts.addTest(tl.loadTestsFromModule(mod)) return ts - - + +def objspace(): + objspace_path = os.environ.get('OBJSPACE') + if not objspace_path or '.' not in objspace_path: + return trivobjspace() + else: + return stdobjspace() + +_trivobjspace = None + +def trivobjspace(): + global _trivobjspace + if _trivobjspace: + return _trivobjspace + from pypy.objspace.trivial import TrivialObjSpace + _trivobjspace = TrivialObjSpace() + return _trivobjspace + +_stdobjspace = None + +def stdobjspace(): + global _stdobjspace + if _stdobjspace: + return _stdobjspace + from pypy.objspace.std import StdObjSpace + _stdobjspace = StdObjSpace() + return _stdobjspace Modified: pypy/trunk/src/pypy/module/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/module/test/testsupport.py (original) +++ pypy/trunk/src/pypy/module/test/testsupport.py Sat Jun 7 20:24:29 2003 @@ -21,7 +21,9 @@ When run as a script, runs all tests found in files called 'test_*.py' in the same directory. """ -import sys, os +import sys +import os +import unittest try: head = this_path = os.path.abspath(__file__) @@ -39,26 +41,11 @@ break import pypy.interpreter.unittest_w +from pypy.interpreter.testtools import * + TestCase = pypy.interpreter.unittest_w.TestCase_w -import unittest main = unittest.main -from pypy.interpreter import testtools - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - import pypy.objspace.trivial - return pypy.objspace.trivial.TrivialObjSpace() - else: - objspace_pieces = objspace_path.split('.') - objspace_path = '.'.join(objspace_pieces[:-1]) - objspace_module = __import__(objspace_path) - for piece in objspace_pieces[1:-1]: - objspace_module = getattr(objspace_module, piece) - objspace_classname = objspace_pieces[-1] - return getattr(objspace_module, objspace_classname)() - if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(testtools.get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) Modified: pypy/trunk/src/pypy/objspace/std/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/testsupport.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/testsupport.py Sat Jun 7 20:24:29 2003 @@ -21,7 +21,9 @@ When run as a script, runs all tests found in files called 'test_*.py' in the same directory. """ -import sys, os +import sys +import os +import unittest try: head = this_path = os.path.abspath(__file__) @@ -39,26 +41,11 @@ break import pypy.interpreter.unittest_w +from pypy.interpreter.testtools import * + TestCase = pypy.interpreter.unittest_w.TestCase_w -import unittest main = unittest.main -from pypy.interpreter import testtools - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - import pypy.objspace.trivial - return pypy.objspace.trivial.TrivialObjSpace() - else: - objspace_pieces = objspace_path.split('.') - objspace_path = '.'.join(objspace_pieces[:-1]) - objspace_module = __import__(objspace_path) - for piece in objspace_pieces[1:-1]: - objspace_module = getattr(objspace_module, piece) - objspace_classname = objspace_pieces[-1] - return getattr(objspace_module, objspace_classname)() - if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(testtools.get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) Modified: pypy/trunk/src/pypy/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/testsupport.py (original) +++ pypy/trunk/src/pypy/testsupport.py Sat Jun 7 20:24:29 2003 @@ -21,7 +21,9 @@ When run as a script, runs all tests found in files called 'test_*.py' in the same directory. """ -import sys, os +import sys +import os +import unittest try: head = this_path = os.path.abspath(__file__) @@ -39,26 +41,11 @@ break import pypy.interpreter.unittest_w +from pypy.interpreter.testtools import * + TestCase = pypy.interpreter.unittest_w.TestCase_w -import unittest main = unittest.main -from pypy.interpreter import testtools - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - import pypy.objspace.trivial - return pypy.objspace.trivial.TrivialObjSpace() - else: - objspace_pieces = objspace_path.split('.') - objspace_path = '.'.join(objspace_pieces[:-1]) - objspace_module = __import__(objspace_path) - for piece in objspace_pieces[1:-1]: - objspace_module = getattr(objspace_module, piece) - objspace_classname = objspace_pieces[-1] - return getattr(objspace_module, objspace_classname)() - if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(testtools.get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) From mwh at codespeak.net Sat Jun 7 20:26:04 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:26:04 +0200 (MEST) Subject: [pypy-svn] rev 778 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030607182604.C18255ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:26:03 2003 New Revision: 778 Modified: pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py pypy/trunk/src/pypy/objspace/std/test/test_intobject.py pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py pypy/trunk/src/pypy/objspace/std/test/test_listobject.py pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Log: considerable, but largely cosmetic, test gardening hope I didn't cause too many conflicts for you! Modified: pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py Sat Jun 7 20:26:03 2003 @@ -1,13 +1,13 @@ import unittest, sys, array import testsupport from pypy.objspace.std import cpythonobject -from pypy.objspace.std.objspace import * +from pypy.objspace.std.objspace import OperationError -class TestW_CPythonObject(unittest.TestCase): +class TestW_CPythonObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() # arbitrary always-wrapped object self.stuff = array.array('b', [5,-2,77]) @@ -63,6 +63,7 @@ self.assertEquals(self.space.unwrap(w_result), expected) def test_hash(self): + # i don't understand this test -- mwh w1 = self.space.wrap(self.stuff) try: self.space.hash(w1) @@ -76,4 +77,4 @@ self.assertEquals(self.space.unwrap(w_result), 11) if __name__ == '__main__': - unittest.main() + testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Sat Jun 7 20:26:03 2003 @@ -1,26 +1,24 @@ -import sys import testsupport -from pypy.objspace.std import dictobject as dobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.dictobject import W_DictObject class TestW_DictObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass def test_empty(self): space = self.space - d = dobj.W_DictObject(space, []) + d = W_DictObject(space, []) self.failIf_w(d) def test_nonempty(self): space = self.space wNone = space.w_None - d = dobj.W_DictObject(space, [(wNone, wNone)]) + d = W_DictObject(space, [(wNone, wNone)]) self.failUnless(space.is_true(d)) i = space.getitem(d, wNone) equal = space.eq(i, wNone) @@ -30,7 +28,7 @@ space = self.space wk1 = space.wrap('key') wone = space.wrap(1) - d = dobj.W_DictObject(space, [(space.wrap('zero'),space.wrap(0))]) + d = W_DictObject(space, [(space.wrap('zero'),space.wrap(0))]) space.setitem(d,wk1,wone) wback = space.getitem(d,wk1) self.assertEqual_w(wback,wone) @@ -38,19 +36,20 @@ def test_delitem(self): space = self.space wk1 = space.wrap('key') - d = dobj.W_DictObject(space, + d = W_DictObject(space, [(space.wrap('zero'),space.wrap(0)), (space.wrap('one'),space.wrap(1)), (space.wrap('two'),space.wrap(2))]) space.delitem(d,space.wrap('one')) self.assertEqual_w(space.getitem(d,space.wrap('zero')),space.wrap(0)) self.assertEqual_w(space.getitem(d,space.wrap('two')),space.wrap(2)) - self.failUnlessRaises(OperationError,space.getitem,d,space.wrap('one')) + self.assertRaises_w(self.space.w_KeyError, + space.getitem,d,space.wrap('one')) def test_cell(self): space = self.space wk1 = space.wrap('key') - d = dobj.W_DictObject(space, []) + d = W_DictObject(space, []) w_cell = d.cell(space,wk1) cell = space.unwrap(w_cell) self.failUnless(cell.is_empty()) @@ -63,7 +62,7 @@ def test_wrap_dict(self): - self.assert_(isinstance(self.space.wrap({}), dobj.W_DictObject)) + self.assert_(isinstance(self.space.wrap({}), W_DictObject)) def test_dict_compare(self): Modified: pypy/trunk/src/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_intobject.py Sat Jun 7 20:26:03 2003 @@ -1,14 +1,12 @@ -import unittest, sys +import sys import testsupport -from pypy.interpreter import unittest_w from pypy.objspace.std import intobject as iobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.objspace import FailedToImplement - -class TestW_IntObject(unittest_w.TestCase_w): +class TestW_IntObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass @@ -32,14 +30,6 @@ except FailedToImplement, arg: return arg[0] - def _unwrap_except(self, func, *args, **kwds): - """ make sure that the expected exception occours, and unwrap it """ - try: - res = func(*args, **kwds) - raise Exception, "should have failed but returned '%s'!" %repr(res) - except OperationError, e: - return e.w_type - def test_repr(self): x = 1 f1 = iobj.W_IntObject(self.space, x) @@ -163,11 +153,13 @@ v = iobj.int_int_int_pow(self.space, f1, f2, f3) self.assertEquals(v.intval, pow(x, y, z)) f1, f2, f3 = [iobj.W_IntObject(self.space, i) for i in (10, -1, 42)] - self.assertEquals(self.space.w_TypeError, - self._unwrap_except(iobj.int_int_int_pow, self.space, f1, f2, f3)) + self.assertRaises_w(self.space.w_TypeError, + iobj.int_int_int_pow, + self.space, f1, f2, f3) f1, f2, f3 = [iobj.W_IntObject(self.space, i) for i in (10, 5, 0)] - self.assertEquals(self.space.w_ValueError, - self._unwrap_except(iobj.int_int_int_pow, self.space, f1, f2, f3)) + self.assertRaises_w(self.space.w_ValueError, + iobj.int_int_int_pow, + self.space, f1, f2, f3) def test_pow_iin(self): x = 10 @@ -294,4 +286,4 @@ self.assertEquals(self.space.unwrap(result), hex(x)) if __name__ == '__main__': - unittest.main() + testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py Sat Jun 7 20:26:03 2003 @@ -1,14 +1,11 @@ -import unittest, sys import testsupport -from pypy.interpreter import unittest_w -from pypy.objspace.std import iterobject as iobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.iterobject import W_SeqIterObject +from pypy.objspace.std.objspace import NoValue - -class TestW_IterObject(unittest_w.TestCase_w): +class TestW_IterObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass @@ -16,7 +13,7 @@ def test_iter(self): w = self.space.wrap w_tuple = self.space.newtuple([w(5), w(3), w(99)]) - w_iter = iobj.W_SeqIterObject(self.space, w_tuple) + w_iter = W_SeqIterObject(self.space, w_tuple) self.assertEqual_w(self.space.next(w_iter), w(5)) self.assertEqual_w(self.space.next(w_iter), w(3)) self.assertEqual_w(self.space.next(w_iter), w(99)) @@ -25,9 +22,9 @@ def test_emptyiter(self): w_list = self.space.newlist([]) - w_iter = iobj.W_SeqIterObject(self.space, w_list) + w_iter = W_SeqIterObject(self.space, w_list) self.assertRaises(NoValue, self.space.next, w_iter) self.assertRaises(NoValue, self.space.next, w_iter) if __name__ == '__main__': - unittest.main() + testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_listobject.py Sat Jun 7 20:26:03 2003 @@ -1,35 +1,33 @@ -from __future__ import nested_scopes -import unittest, sys +#from __future__ import nested_scopes import testsupport -from pypy.interpreter import unittest_w -from pypy.objspace.std import listobject as lobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.listobject import W_ListObject +from pypy.objspace.std.objspace import NoValue -class TestW_ListObject(unittest_w.TestCase_w): +class TestW_ListObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass def test_is_true(self): w = self.space.wrap - w_list = lobj.W_ListObject(self.space, []) + w_list = W_ListObject(self.space, []) self.assertEqual(self.space.is_true(w_list), False) - w_list = lobj.W_ListObject(self.space, [w(5)]) + w_list = W_ListObject(self.space, [w(5)]) self.assertEqual(self.space.is_true(w_list), True) - w_list = lobj.W_ListObject(self.space, [w(5), w(3)]) + w_list = W_ListObject(self.space, [w(5), w(3)]) self.assertEqual(self.space.is_true(w_list), True) def test_len(self): w = self.space.wrap - w_list = lobj.W_ListObject(self.space, []) + w_list = W_ListObject(self.space, []) self.assertEqual_w(self.space.len(w_list), w(0)) - w_list = lobj.W_ListObject(self.space, [w(5)]) + w_list = W_ListObject(self.space, [w(5)]) self.assertEqual_w(self.space.len(w_list), w(1)) - w_list = lobj.W_ListObject(self.space, [w(5), w(3), w(99)]*111) + w_list = W_ListObject(self.space, [w(5), w(3), w(99)]*111) self.assertEqual_w(self.space.len(w_list), w(333)) def test_mul(self): @@ -37,8 +35,8 @@ w = self.space.wrap arg = w(2) n = 3 - w_lis = lobj.W_ListObject(self.space, [arg]) - w_lis3 = lobj.W_ListObject(self.space, [arg]*n) + w_lis = W_ListObject(self.space, [arg]) + w_lis3 = W_ListObject(self.space, [arg]*n) w_res = self.space.mul(w_lis, w(n)) self.assertEqual_w(w_lis3, w_res) # commute @@ -47,7 +45,7 @@ def test_getitem(self): w = self.space.wrap - w_list = lobj.W_ListObject(self.space, [w(5), w(3)]) + w_list = W_ListObject(self.space, [w(5), w(3)]) self.assertEqual_w(self.space.getitem(w_list, w(0)), w(5)) self.assertEqual_w(self.space.getitem(w_list, w(1)), w(3)) self.assertEqual_w(self.space.getitem(w_list, w(-2)), w(5)) @@ -61,7 +59,7 @@ def test_iter(self): w = self.space.wrap - w_list = lobj.W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list = W_ListObject(self.space, [w(5), w(3), w(99)]) w_iter = self.space.iter(w_list) self.assertEqual_w(self.space.next(w_iter), w(5)) self.assertEqual_w(self.space.next(w_iter), w(3)) @@ -71,24 +69,25 @@ def test_add(self): w = self.space.wrap - w_list0 = lobj.W_ListObject(self.space, []) - w_list1 = lobj.W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = lobj.W_ListObject(self.space, [w(-7)] * 111) + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(-7)] * 111) self.assertEqual_w(self.space.add(w_list1, w_list1), - lobj.W_ListObject(self.space, [w(5), w(3), w(99), + W_ListObject(self.space, [w(5), w(3), w(99), w(5), w(3), w(99)])) self.assertEqual_w(self.space.add(w_list1, w_list2), - lobj.W_ListObject(self.space, [w(5), w(3), w(99)] + + W_ListObject(self.space, [w(5), w(3), w(99)] + [w(-7)] * 111)) self.assertEqual_w(self.space.add(w_list1, w_list0), w_list1) self.assertEqual_w(self.space.add(w_list0, w_list2), w_list2) def test_getslice(self): + # this takes aaagggeeesss!!! w = self.space.wrap def test1(testlist, start, stop, step, expected): w_slice = self.space.newslice(w(start), w(stop), w(step)) - w_list = lobj.W_ListObject(self.space, [w(i) for i in testlist]) + w_list = W_ListObject(self.space, [w(i) for i in testlist]) w_result = self.space.getitem(w_list, w_slice) self.assertEqual(self.space.unwrap(w_result), expected) @@ -106,9 +105,9 @@ def test_setitem(self): w = self.space.wrap - w_list = lobj.W_ListObject(self.space, [w(5), w(3)]) - w_exp1 = lobj.W_ListObject(self.space, [w(5), w(7)]) - w_exp2 = lobj.W_ListObject(self.space, [w(8), w(7)]) + w_list = W_ListObject(self.space, [w(5), w(3)]) + w_exp1 = W_ListObject(self.space, [w(5), w(7)]) + w_exp2 = W_ListObject(self.space, [w(8), w(7)]) self.space.setitem(w_list, w(1), w(7)) self.assertEqual_w(w_exp1, w_list) self.space.setitem(w_list, w(-2), w(8)) @@ -120,4 +119,4 @@ if __name__ == '__main__': - unittest.main() + testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py Sat Jun 7 20:26:03 2003 @@ -1,21 +1,18 @@ -import unittest, sys import testsupport -from pypy.interpreter import unittest_w -from pypy.objspace.std import moduleobject as mobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.moduleobject import W_ModuleObject -class TestW_ModuleObject(unittest_w.TestCase_w): +class TestW_ModuleObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass def test_name(self): space = self.space - w_m = mobj.W_ModuleObject(space, space.wrap('somename')) + w_m = W_ModuleObject(space, space.wrap('somename')) self.assertEqual_w(space.getattr(w_m, space.wrap('__name__')), space.wrap('somename')) @@ -23,7 +20,7 @@ space = self.space w_x = space.wrap(123) w_yy = space.w_True - w_m = mobj.W_ModuleObject(space, space.wrap('somename')) + w_m = W_ModuleObject(space, space.wrap('somename')) space.setattr(w_m, space.wrap('x'), w_x) space.setattr(w_m, space.wrap('yy'), w_yy) self.assertEqual_w(space.getattr(w_m, space.wrap('x')), w_x) @@ -34,4 +31,4 @@ self.assertEqual_w(space.getattr(w_m, space.wrap('yy')), w_yy) if __name__ == '__main__': - unittest.main() + testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py Sat Jun 7 20:26:03 2003 @@ -1,11 +1,10 @@ import testsupport -from pypy.objspace.std.objspace import StdObjSpace class TestW_NoneObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass Modified: pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py Sat Jun 7 20:26:03 2003 @@ -1,4 +1,4 @@ -import unittest, sys +import unittest import testsupport from pypy.objspace.std.restricted_int import * Modified: pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py Sat Jun 7 20:26:03 2003 @@ -1,10 +1,9 @@ import testsupport -from pypy.objspace.std import StdObjSpace class TestW_SliceObject(testsupport.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = testsupport.stdobjspace() def tearDown(self): pass @@ -24,13 +23,11 @@ w_slice = space.newslice(w_None, w_None, w(-1)) self.equal_indices(w_slice.indices(w(6)), (5, -1, -1, 6)) - def XXXtest_indices_fail(self): - """ usual exception problems """ + def test_indices_fail(self): space = self.space w = space.wrap w_None = space.w_None w_slice = space.newslice(w_None, w_None, w(0)) - self.equal_indices(w_slice.indices(w(6)), (5, -1, -1, 6)) self.assertRaises_w(space.w_ValueError, w_slice.indices, w(10)) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py Sat Jun 7 20:26:03 2003 @@ -1,11 +1,9 @@ import testsupport -from pypy.objspace.std import StdObjSpace - class TestW_StdObjSpace(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass @@ -15,6 +13,10 @@ self.space.wrap, self.space.wrap(0)) + def hopeful_test_exceptions(self): + self.apptest("self.failUnless(issubclass(ArithmeticError, Exception))") + self.apptest("self.failIf(issubclass(ArithmeticError, KeyError))") + if __name__ == '__main__': testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sat Jun 7 20:26:03 2003 @@ -1,8 +1,8 @@ import testsupport -import pypy.objspace.std.stringobject as so +from pypy.objspace.std import stringobject -from pypy.objspace.std.stringobject import string_richcompare, W_StringObject, EQ, LT, GT, NE, LE, GE -from pypy.objspace.std.objspace import StdObjSpace +from pypy.objspace.std.stringobject import \ + string_richcompare, W_StringObject, EQ, LT, GT, NE, LE, GE class TestW_StringObject(testsupport.TestCase): @@ -23,16 +23,23 @@ while strs[1:]: str1 = strs.pop() for op in ops: - orf = getattr(str1, '__%s__' % op.lower()) #original python function - pypyconst = getattr(so, op) + #original python function + orf = getattr(str1, '__%s__' % op.lower()) + pypyconst = getattr(stringobject, op) for str2 in strs: if orf(str2): - self.failUnless_w(string_richcompare(space, w(str1), w(str2), pypyconst)) + self.failUnless_w( + string_richcompare(space, + w(str1), + w(str2), + pypyconst)) else: - self.failIf_w(string_richcompare(space, w(str1), w(str2), pypyconst)) + self.failIf_w( + string_richcompare(space, + w(str1), + w(str2), + pypyconst)) - - def test_equality(self): w = self.space.wrap self.assertEqual_w(w('abc'), w('abc')) @@ -103,7 +110,5 @@ w_slice = space.newslice(w(1), w_None, w(2)) self.assertEqual_w(space.getitem(w_str, w_slice), w('el')) - - if __name__ == '__main__': testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py Sat Jun 7 20:26:03 2003 @@ -1,40 +1,38 @@ -from __future__ import nested_scopes -import unittest, sys +#from __future__ import nested_scopes import testsupport -from pypy.interpreter import unittest_w -from pypy.objspace.std import tupleobject as tobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.tupleobject import W_TupleObject +from pypy.objspace.std.objspace import NoValue -class TestW_TupleObject(unittest_w.TestCase_w): +class TestW_TupleObject(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass def test_is_true(self): w = self.space.wrap - w_tuple = tobj.W_TupleObject(self.space, []) + w_tuple = W_TupleObject(self.space, []) self.assertEqual(self.space.is_true(w_tuple), False) - w_tuple = tobj.W_TupleObject(self.space, [w(5)]) + w_tuple = W_TupleObject(self.space, [w(5)]) self.assertEqual(self.space.is_true(w_tuple), True) - w_tuple = tobj.W_TupleObject(self.space, [w(5), w(3)]) + w_tuple = W_TupleObject(self.space, [w(5), w(3)]) self.assertEqual(self.space.is_true(w_tuple), True) def test_len(self): w = self.space.wrap - w_tuple = tobj.W_TupleObject(self.space, []) + w_tuple = W_TupleObject(self.space, []) self.assertEqual_w(self.space.len(w_tuple), w(0)) - w_tuple = tobj.W_TupleObject(self.space, [w(5)]) + w_tuple = W_TupleObject(self.space, [w(5)]) self.assertEqual_w(self.space.len(w_tuple), w(1)) - w_tuple = tobj.W_TupleObject(self.space, [w(5), w(3), w(99)]*111) + w_tuple = W_TupleObject(self.space, [w(5), w(3), w(99)]*111) self.assertEqual_w(self.space.len(w_tuple), w(333)) def test_getitem(self): w = self.space.wrap - w_tuple = tobj.W_TupleObject(self.space, [w(5), w(3)]) + w_tuple = W_TupleObject(self.space, [w(5), w(3)]) self.assertEqual_w(self.space.getitem(w_tuple, w(0)), w(5)) self.assertEqual_w(self.space.getitem(w_tuple, w(1)), w(3)) self.assertEqual_w(self.space.getitem(w_tuple, w(-2)), w(5)) @@ -48,7 +46,7 @@ def test_iter(self): w = self.space.wrap - w_tuple = tobj.W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple = W_TupleObject(self.space, [w(5), w(3), w(99)]) w_iter = self.space.iter(w_tuple) self.assertEqual_w(self.space.next(w_iter), w(5)) self.assertEqual_w(self.space.next(w_iter), w(3)) @@ -58,7 +56,7 @@ def test_contains(self): w = self.space.wrap - w_tuple = tobj.W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple = W_TupleObject(self.space, [w(5), w(3), w(99)]) self.assertEqual_w(self.space.contains(w_tuple, w(5)), self.space.w_True) self.assertEqual_w(self.space.contains(w_tuple, w(99)), @@ -70,15 +68,15 @@ def test_add(self): w = self.space.wrap - w_tuple0 = tobj.W_TupleObject(self.space, []) - w_tuple1 = tobj.W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = tobj.W_TupleObject(self.space, [w(-7)] * 111) + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(-7)] * 111) self.assertEqual_w(self.space.add(w_tuple1, w_tuple1), - tobj.W_TupleObject(self.space, [w(5), w(3), w(99), - w(5), w(3), w(99)])) + W_TupleObject(self.space, [w(5), w(3), w(99), + w(5), w(3), w(99)])) self.assertEqual_w(self.space.add(w_tuple1, w_tuple2), - tobj.W_TupleObject(self.space, [w(5), w(3), w(99)] + - [w(-7)] * 111)) + W_TupleObject(self.space, + [w(5), w(3), w(99)] + [w(-7)] * 111)) self.assertEqual_w(self.space.add(w_tuple1, w_tuple0), w_tuple1) self.assertEqual_w(self.space.add(w_tuple0, w_tuple2), w_tuple2) @@ -87,8 +85,8 @@ w = self.space.wrap arg = w(2) n = 3 - w_tup = tobj.W_TupleObject(self.space, [arg]) - w_tup3 = tobj.W_TupleObject(self.space, [arg]*n) + w_tup = W_TupleObject(self.space, [arg]) + w_tup3 = W_TupleObject(self.space, [arg]*n) w_res = self.space.mul(w_tup, w(n)) self.assertEqual_w(w_tup3, w_res) # commute @@ -100,7 +98,7 @@ def test1(testtuple, start, stop, step, expected): w_slice = self.space.newslice(w(start), w(stop), w(step)) - w_tuple = tobj.W_TupleObject(self.space, [w(i) for i in testtuple]) + w_tuple = W_TupleObject(self.space, [w(i) for i in testtuple]) w_result = self.space.getitem(w_tuple, w_slice) self.assertEqual(self.space.unwrap(w_result), expected) @@ -117,4 +115,4 @@ test1((5,7,1,4), -5, 11, 2, (5, 1)) if __name__ == '__main__': - unittest.main() + testsupport.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Sat Jun 7 20:26:03 2003 @@ -1,14 +1,10 @@ -import unittest, sys import testsupport -from pypy.interpreter import unittest_w -from pypy.objspace.std import typeobject as tobj -from pypy.objspace.std.objspace import * +from pypy.objspace.std.typeobject import PyMultimethodCode - -class TestPyMultimethodCode(unittest_w.TestCase_w): +class TestPyMultimethodCode(testsupport.TestCase): def setUp(self): - self.space = StdObjSpace() + self.space = testsupport.stdobjspace() def tearDown(self): pass @@ -16,8 +12,8 @@ def test_int_sub(self): w = self.space.wrap for i in range(2): - meth = tobj.PyMultimethodCode(self.space.sub.multimethod, - i, self.space.w_int) + meth = PyMultimethodCode(self.space.sub.multimethod, + i, self.space.w_int) self.assertEqual(meth.slice().is_empty(), False) # test int.__sub__ and int.__rsub__ self.assertEqual_w(meth.eval_code(self.space, None, @@ -32,16 +28,16 @@ def test_empty_inplace_add(self): for i in range(2): - meth = tobj.PyMultimethodCode(self.space.inplace_add.multimethod, - i, self.space.w_int) + meth = PyMultimethodCode(self.space.inplace_add.multimethod, + i, self.space.w_int) self.assertEqual(meth.slice().is_empty(), True) def test_float_sub(self): w = self.space.wrap w(1.5) # force floatobject imported for i in range(2): - meth = tobj.PyMultimethodCode(self.space.sub.multimethod, - i, self.space.w_float) + meth = PyMultimethodCode(self.space.sub.multimethod, + i, self.space.w_float) self.assertEqual(meth.slice().is_empty(), False) # test float.__sub__ and float.__rsub__ @@ -59,4 +55,4 @@ if __name__ == '__main__': - unittest.main() + testsupport.main() From mwh at codespeak.net Sat Jun 7 20:30:35 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:30:35 +0200 (MEST) Subject: [pypy-svn] rev 779 - pypy/trunk/src/pypy/interpreter Message-ID: <20030607183035.9140B5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:30:35 2003 New Revision: 779 Modified: pypy/trunk/src/pypy/interpreter/opcode.py Log: it's called import_all_from in opcode_app.py, not import_star... Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Sat Jun 7 20:30:35 2003 @@ -552,7 +552,7 @@ def IMPORT_STAR(f): w_module = f.valuestack.pop() - f.space.gethelper(appfile).call("import_star", [w_module, f.w_locals]) + f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals]) def IMPORT_FROM(f, nameindex): name = f.getname(nameindex) From mwh at codespeak.net Sat Jun 7 20:31:24 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:31:24 +0200 (MEST) Subject: [pypy-svn] rev 780 - pypy/trunk/src/pypy/interpreter Message-ID: <20030607183124.7F5BE5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:31:24 2003 New Revision: 780 Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py Log: remove need for types from opcode_app.prepare_raise Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode_app.py Sat Jun 7 20:31:24 2003 @@ -3,24 +3,24 @@ return sys.exc_info() def prepare_raise(etype, value, traceback): - import types +# import types # XXX we get an infinite loop if this import fails: # import types -> IMPORT_NAME -> import_name -> raise ImportError # -> RAISE_VARARGS -> prepare_raise -> import types ... - if not isinstance(traceback, (types.NoneType, types.TracebackType)): - raise TypeError, "raise: arg 3 must be traceback or None" +# if not isinstance(traceback, (types.NoneType, types.TracebackType)): +# raise TypeError, "raise: arg 3 must be traceback or None" while isinstance(etype, tuple): etype = etype[0] if type(etype) is str: # warn pass - elif isinstance(etype, types.ClassType): + elif isinstance(etype, type) and issubclass(etype, Exception): if value is None: value = () elif not isinstance(value, tuple): value = (value,) value = etype(*value) - elif isinstance(etype, types.InstanceType): + elif isinstance(etype, Exception): if value is not None: raise TypeError, "instance exception may not have a separate value" value = etype From mwh at codespeak.net Sat Jun 7 20:53:40 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:53:40 +0200 (MEST) Subject: [pypy-svn] rev 781 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607185340.0698F5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:53:39 2003 New Revision: 781 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: add Exception.__str__, too (this is getting tedious) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sat Jun 7 20:53:39 2003 @@ -71,7 +71,19 @@ code._from_code(__init__.func_code) w_init = W_FuncObject(self, code, self.newdict([]), self.newtuple([]), None) -# w_init = w(__init__) # should this work? --mwh +## w_init = w(__init__) # should this work? --mwh + def __str__(self): + l = len(self.args) + if l == 0: + return '' + elif l == 1: + return str(self.args[0]) + else: + return str(self.args) + code = PyByteCode() + code._from_code(__str__.func_code) + w_str = W_FuncObject(self, code, + self.newdict([]), self.newtuple([]), None) import exceptions # to create types, we should call the standard type object; @@ -82,7 +94,8 @@ self, w('Exception'), self.newtuple([]), - self.newdict([(w('__init__'), w_init)])) + self.newdict([(w('__init__'), w_init), + (w('__str__'), w_str)])) self.w_IndexError = self.w_Exception done = {'Exception': self.w_Exception} From mwh at codespeak.net Sat Jun 7 20:55:19 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:55:19 +0200 (MEST) Subject: [pypy-svn] rev 782 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607185519.66E3C5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:55:19 2003 New Revision: 782 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py Log: some bogus implementations of things that await proper implementation Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sat Jun 7 20:55:19 2003 @@ -5,6 +5,7 @@ from listobject import W_ListObject from instmethobject import W_InstMethObject from noneobject import W_NoneObject +from tupleobject import W_TupleObject from pypy.interpreter.extmodule import make_builtin_func from rarray import CharArrayFromStr, CharArraySize @@ -293,8 +294,8 @@ W_StringObject, W_IntObject) def getitem_str_slice(space, w_str, w_slice): -# return space.gethelper(applicationfile).call( -# "getitem_string_slice", [w_str, w_slice]) + return space.gethelper(applicationfile).call( + "getitem_string_slice", [w_str, w_slice]) w = space.wrap u = space.unwrap w_start, w_stop, w_step, w_sl = w_slice.indices(w(w_str._value.len)) @@ -338,8 +339,24 @@ def str_repr(space, w_str): # XXX this is bogus -- mwh + return space.wrap(repr(space.unwrap(w_str))) a = space.add q = space.wrap("'") return a(a(q, w_str), q) StdObjSpace.repr.register(str_repr, W_StringObject) + +def str_ord(space, w_str): + return space.wrap(ord(space.unwrap(w_str))) + +StdObjSpace.ord.register(str_ord, W_StringObject) + +def str_mod_any(space, w_str, w_item): + return str_mod_tuple(space, w_str, space.newtuple([w_item])) + +StdObjSpace.mod.register(str_mod_any, W_StringObject, W_ANY) + +def str_mod_tuple(space, w_str, w_tuple): + return space.wrap(space.unwrap(w_str)%space.unwrap(w_tuple)) + +StdObjSpace.mod.register(str_mod_tuple, W_StringObject, W_TupleObject) From mwh at codespeak.net Sat Jun 7 20:56:01 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:56:01 +0200 (MEST) Subject: [pypy-svn] rev 783 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607185601.E12FA5ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:56:01 2003 New Revision: 783 Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py Log: support __name__ (needed to get an exception test to work). Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sat Jun 7 20:56:01 2003 @@ -161,7 +161,6 @@ StdObjSpace.call.register(type_call, W_TypeObject, W_ANY, W_ANY) - def type_issubtype(space, w_type1, w_type2): return space.newbool(w_type2 in w_type1.getmro()) @@ -171,3 +170,11 @@ return space.wrap("" % w_obj.typename) StdObjSpace.repr.register(type_repr, W_TypeObject) + +def type_getattr(space, w_type, w_attr): + # XXX mwh doubts this is the Right Way to do this... + if space.is_true(space.eq(w_attr, space.wrap('__name__'))): + return w_type.w_tpname + raise FailedToImplement + +StdObjSpace.getattr.register(type_getattr, W_TypeObject, W_ANY) From mwh at codespeak.net Sat Jun 7 20:56:36 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:56:36 +0200 (MEST) Subject: [pypy-svn] rev 784 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607185636.786615ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:56:36 2003 New Revision: 784 Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py Log: expose .func_code on function objects Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Sat Jun 7 20:56:36 2003 @@ -48,3 +48,11 @@ return W_InstMethObject(space, w_instance, w_function) StdObjSpace.get.register(func_get, W_FuncObject, W_ANY, W_ANY) + +def func_getattr(space, w_function, w_attr): + if space.is_true(space.eq(w_attr, space.wrap('func_code'))): + return space.wrap(w_function.code) + else: + raise FailedToImplement + +StdObjSpace.getattr.register(func_getattr, W_FuncObject, W_ANY) From mwh at codespeak.net Sat Jun 7 20:57:04 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 7 Jun 2003 20:57:04 +0200 (MEST) Subject: [pypy-svn] rev 785 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030607185704.18CE75ACA3@thoth.codespeak.net> Author: mwh Date: Sat Jun 7 20:57:03 2003 New Revision: 785 Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py Log: slimy tuple.__repr__ Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Sat Jun 7 20:57:03 2003 @@ -100,3 +100,9 @@ return space.w_True StdObjSpace.eq.register(tuple_eq, W_TupleObject, W_TupleObject) + +def tuple_repr(space, w_tuple): + # XXX slimy! --mwh + return space.wrap(repr(space.unwrap(w_tuple))) + +StdObjSpace.repr.register(tuple_repr, W_TupleObject) From mwh at codespeak.net Mon Jun 9 14:00:34 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:00:34 +0200 (MEST) Subject: [pypy-svn] rev 788 - pypy/trunk/src/pypy/interpreter Message-ID: <20030609120034.47B905BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:00:33 2003 New Revision: 788 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py Log: Exceptions now know how to print themselves. Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Mon Jun 9 14:00:33 2003 @@ -72,9 +72,10 @@ def errorstr(self, space): "The exception class and value, as a string." - exc_type = space.unwrap(self.w_type) - exc_value = space.unwrap(self.w_value) - return '%s: %s' % (exc_type.__name__, exc_value) + exc_type = space.unwrap( + space.getattr(self.w_type, space.wrap('__name__'))) + exc_value = space.unwrap(space.str(self.w_value)) + return '%s: %s' % (exc_type, exc_value) def getframe(self): "The frame this exception was raised in, or None." @@ -136,8 +137,9 @@ exc_typename = str(self.w_type) exc_value = self.w_value else: - exc_typename = space.unwrap(self.w_type).__name__ - exc_value = space.unwrap(self.w_value) + w = space.wrap + exc_typename = space.getattr(self.w_type, w('__name__')) + exc_value = space.unwrap(space.str(self.w_value)) print >> file, '(application-level)', if exc_value is None: print >> file, exc_typename From mwh at codespeak.net Mon Jun 9 14:01:01 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:01:01 +0200 (MEST) Subject: [pypy-svn] rev 789 - pypy/trunk/src/pypy/interpreter Message-ID: <20030609120101.2B7F95BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:01:00 2003 New Revision: 789 Modified: pypy/trunk/src/pypy/interpreter/extmodule.py Log: Wrap long line. Modified: pypy/trunk/src/pypy/interpreter/extmodule.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/extmodule.py (original) +++ pypy/trunk/src/pypy/interpreter/extmodule.py Mon Jun 9 14:01:00 2003 @@ -72,7 +72,9 @@ w_module = space.newmodule(space.wrap(modulename)) for key, value in self.__class__.__dict__.items() + self.__dict__.items(): if isinstance(value, appmethod): - w_function = make_builtin_func(space,value.func.__get__(self),boundmethod=True) + w_function = make_builtin_func(space, + value.func.__get__(self), + boundmethod=True) space.setattr(w_module, space.wrap(key), w_function) elif isinstance(value, appdata): w_data = space.wrap(value.data) From mwh at codespeak.net Mon Jun 9 14:01:52 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:01:52 +0200 (MEST) Subject: [pypy-svn] rev 790 - pypy/trunk/src/pypy/interpreter Message-ID: <20030609120152.766115BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:01:52 2003 New Revision: 790 Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py Log: Do not rely on being able to catch exceptions in decode_code_arguments. Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode_app.py Mon Jun 9 14:01:52 2003 @@ -1,7 +1,17 @@ # replacement for decode_frame_arguments -# ===== ATTENTION ===== ! All calls here must be "easy", i.e. not involve -# default or keyword arguments !! For example, all range() calls -# need three arguments. +# +# ===== ATTENTION ===== +# +# This code is pretty fundamental to pypy and great care must be taken +# to avoid infinite recursion. In particular: +# +# - All calls here must be "easy", i.e. not involve default or keyword +# arguments. For example, all range() calls need three arguments. +# +# - You cannot *catch* any exceptions (raising is fine). +# +# (I wonder if the pain of writing this at interpreter level might be +# worth it...) def decode_code_arguments(args, kws, defs, closure, codeobject): """ @@ -21,9 +31,9 @@ # Normal arguments for i in range(0, len(args), 1): # see comment above for ", 1" - try: + if 0 <= i < len(parameter_names): # try argdict[parameter_names[i]] = args[i] - except IndexError: + else: # except IndexError: # If varargs, put in tuple, else throw error if varargs: varargs_tuple = args[i:] From mwh at codespeak.net Mon Jun 9 14:03:08 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:03:08 +0200 (MEST) Subject: [pypy-svn] rev 791 - pypy/trunk/src/pypy/interpreter Message-ID: <20030609120308.74C795BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:03:08 2003 New Revision: 791 Modified: pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/interpreter/pyframe_app.py Log: Normalize exceptions before pushing onto stack. Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Mon Jun 9 14:03:08 2003 @@ -186,8 +186,19 @@ # instead of the traceback, we store the unroller object, # wrapped. frame.valuestack.push(frame.space.wrap(unroller)) - frame.valuestack.push(operationerr.w_value) - frame.valuestack.push(operationerr.w_type) + + s = frame.space + w_value = operationerr.w_value + w_type = operationerr.w_type +## import pdb +## pdb.set_trace() +## print w_type, `w_value`, frame.bytecode.co_name + w_res = s.gethelper(appfile).call( + "normalize_exception", [w_type, w_value]) + w_value = s.getitem(w_res, s.wrap(1)) + + frame.valuestack.push(w_value) + frame.valuestack.push(w_type) frame.next_instr = self.handlerposition # jump to the handler raise StopUnrolling Modified: pypy/trunk/src/pypy/interpreter/pyframe_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe_app.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe_app.py Mon Jun 9 14:03:08 2003 @@ -81,3 +81,19 @@ if varkeywords: a.append(newkw) return tuple(a) + +def normalize_exception(etype, evalue): + # mistakes here usually show up as infinite recursion, which is + # fun. + if isinstance(evalue, etype): + return etype, evalue + if isinstance(etype, type) and issubclass(etype, Exception): + if evalue is None: + evalue = () + elif not isinstance(evalue, tuple): + evalue = (evalue,) + evalue = etype(*evalue) + else: + raise Exception, "?!" + return etype, evalue + From mwh at codespeak.net Mon Jun 9 14:04:36 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:04:36 +0200 (MEST) Subject: [pypy-svn] rev 792 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030609120436.9F9C35BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:04:36 2003 New Revision: 792 Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Log: Reduce noise. Enable some exception tests that now pass. Tweak a test to fail instead of erroring out. Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Mon Jun 9 14:04:36 2003 @@ -27,7 +27,7 @@ try: w_output = space.call(wrappedfunc, wrappedargs, wrappedkwds) except baseobjspace.OperationError, e: - e.print_detailed_traceback(space) + #e.print_detailed_traceback(space) return '<<<%s>>>' % e.errorstr(space) else: return space.unwrap(w_output) @@ -73,8 +73,7 @@ ''', 'f', []) self.assertEquals(x, 1) - def XXXtest_exception(self): - """ exception raising currently semi-broken """ + def test_exception(self): x = self.codetest(''' def f(): try: @@ -97,16 +96,14 @@ self.assertEquals(self.codetest(code, 'f', [0]), -12) self.assertEquals(self.codetest(code, 'f', [1]), 1) - def XXXtest_raise(self): - """ depends on being able to import types """ + def test_raise(self): x = self.codetest(''' def f(): raise 1 ''', 'f', []) self.assertEquals(x, '<<>>') - def XXXtest_except2(self): - """ depends on being able to import types """ + def test_except2(self): x = self.codetest(''' def f(): try: @@ -135,7 +132,7 @@ self.assertEquals(self.codetest(code, 'f', [0]), "infinite result") ess = "TypeError: unsupported operand type" res = self.codetest(code, 'f', ['x']) - self.failUnless(res.index(ess) >= 0) + self.failUnless(res.find(ess) >= 0) # the following (original) test was a bit too strict...: # self.assertEquals(self.codetest(code, 'f', ['x']), "<<>>") From mwh at codespeak.net Mon Jun 9 14:05:56 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:05:56 +0200 (MEST) Subject: [pypy-svn] rev 793 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030609120556.AF2FA5BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:05:56 2003 New Revision: 793 Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py Log: Reduce noise. Add (hacky) support for .__name__ which is needed to make some of the things I've already checked in today work. Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Mon Jun 9 14:05:56 2003 @@ -116,9 +116,9 @@ def slice(self): if self.slicedmultimethod is None: multimethod = self.basemultimethod - print "pypy: slicing %r for a %r argument at position %d" % ( - multimethod.operatorsymbol, - self.w_type.typename, self.bound_position) + #print "pypy: slicing %r for a %r argument at position %d" % ( + # multimethod.operatorsymbol, + # self.w_type.typename, self.bound_position) # slice the multimethod and cache the result sliced = multimethod.slicetable(self.bound_position, self.w_type) if sliced.is_empty(): From mwh at codespeak.net Mon Jun 9 14:11:56 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 9 Jun 2003 14:11:56 +0200 (MEST) Subject: [pypy-svn] rev 794 - pypy/trunk/src/pypy/objspace Message-ID: <20030609121156.AD2CB5BFF5@thoth.codespeak.net> Author: mwh Date: Mon Jun 9 14:11:56 2003 New Revision: 794 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: Bunch of changes to get the trivial object space working again. The deepest: our builtins know nothing of old style classes. Unfortunately, the trivial object space exported the Exceptions from the underlying interpreter, which were old style classes. So, like the std object space, clone the interpreters exception heirachy as new-style classes. This means we need to convert the exceptions raised by the wrapped operations into our exceptions -- this is the point of the 'reraise' function. Also, add __get__ to nufun, add a few object space methods that have appeared recently and a check that we get them all and a few cosmetic bits. With these changes, the only failure in the test suite is due to 2.2.X not supporting extended slices. Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 9 14:11:56 2003 @@ -11,6 +11,57 @@ class TrivialObjSpace(ObjSpace): + def clone_exception_heirachy(self): + from pypy.interpreter.pycode import PyByteCode + def __init__(self, *args): + self.args = args + def __str__(self): + l = len(self.args) + if l == 0: + return '' + elif l == 1: + return str(self.args[0]) + else: + return str(self.args) + import exceptions + + # to create types, we should call the standard type object; + # but being able to do that depends on the existence of some + # of the exceptions... + + self.w_Exception = type('Exception', (), + {'__init__':__init__, '__str__': __str__}) + + done = {'Exception': self.w_Exception} + + # some of the complexity of the following is due to the fact + # that we need to create the tree root first, but the only + # connections we have go in the inconvenient direction... + + for k in dir(exceptions): + if k not in done: + v = getattr(exceptions, k) + if isinstance(v, str): + continue + stack = [k] + while stack: + next = stack[-1] + if next not in done: + v = getattr(exceptions, next) + b = v.__bases__[0] + if b.__name__ not in done: + stack.append(b.__name__) + continue + else: + base = done[b.__name__] + newtype = type(k, (base,), {}) + setattr(self, 'w_' + next, newtype) + done[next] = newtype + stack.pop() + else: + stack.pop() + return done + def initialize(self): self.w_None = None self.w_True = True @@ -21,11 +72,10 @@ "None" : self.w_None, } for n, c in __builtin__.__dict__.iteritems(): - if ((isinstance(c, types.ClassType) and issubclass(c, Exception)) or - isinstance(c, types.TypeType)): - w_c = c - setattr(self, 'w_' + c.__name__, w_c) - newstuff[c.__name__] = w_c + if isinstance(c, types.TypeType): + setattr(self, 'w_' + c.__name__, c) + newstuff[c.__name__] = c + newstuff.update(self.clone_exception_heirachy()) self.make_builtins() self.make_sys() # insert these into the newly-made builtins @@ -39,6 +89,23 @@ def unwrap(self, w): return w + def reraise(self): + etype, evalue = sys.exc_info()[:2] + name = etype.__name__ + if hasattr(self, 'w_' + name): + nt = getattr(self, 'w_' + name) + nv = object.__new__(nt) + if isinstance(evalue, etype): + nv.args = evalue.args + else: + print [etype, evalue, nt, nv], + print '!!!!!!!!' + nv.args = (evalue,) + else: + nt = etype + nv = evalue + raise OperationError(nt, nv) + # from the built-ins id = id type = type @@ -66,18 +133,18 @@ try: return getattr(obj, name) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() for _name in ('pos', 'neg', 'not_', 'abs', 'invert', - 'mul', 'truediv', 'floordiv', 'div', 'mod', - 'add', 'sub', 'lshift', 'rshift', 'and_', 'xor', 'or_', + 'mul', 'truediv', 'floordiv', 'div', 'mod', + 'add', 'sub', 'lshift', 'rshift', 'and_', 'xor', 'or_', 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'contains'): exec """ def %(_name)s(self, *args): try: return operator.%(_name)s(*args) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() """ % locals() # in-place operators @@ -146,7 +213,7 @@ else: return operator.getslice(obj, sindex[0], sindex[1]) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() def setitem(self, w_obj, w_index, w_value): obj = self.unwrap(w_obj) @@ -159,7 +226,7 @@ else: return operator.setslice(obj, sindex[0], sindex[1], value) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() def delitem(self, w_obj, w_index): obj = self.unwrap(w_obj) @@ -171,7 +238,7 @@ else: operator.delslice(obj, sindex[0], sindex[1]) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() # misc def next(self, w): @@ -197,13 +264,16 @@ w_defaults = self.defaultarguments, w_closure = self.closure) return self.code.eval_code(self.space, self.globals, locals) + def __get__(self, ob, cls=None): + import new + return new.instancemethod(self, ob, cls) return nufun(self, code, globals, defaultarguments, closure) def newstring(self, asciilist): try: return ''.join([chr(ascii) for ascii in asciilist]) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() def call(self, callable, args, kwds): if isinstance(callable, types.ClassType): @@ -211,7 +281,7 @@ try: r = new.instance(callable) except: - raise OperationError(*sys.exc_info()[:2]) + self.reraise() if hasattr(r, '__init__'): self.call(r.__init__, args, kwds) return r @@ -232,3 +302,38 @@ return ec.eval_frame(frame) else: return apply(callable, args, kwds or {}) + + def hex(self, ob): + try: + return hex(ob) + except: + self.reraise() + + def oct(self, ob): + try: + return oct(ob) + except: + self.reraise() + + def ord(self, ob): + try: + return ord(ob) + except: + self.reraise() + + def get(self, descr, ob, cls): + try: + return descr.__get__(ob, cls) + except: + self.reraise() + + def new(self, type, args, kw): + return type(args, kw) + + def init(self, type, args, kw): + pass + + +for m in ObjSpace.MethodTable: + if not hasattr(TrivialObjSpace, m[0]): + print m[0] From arigo at codespeak.net Fri Jun 13 13:15:23 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Jun 2003 13:15:23 +0200 (MEST) Subject: [pypy-svn] rev 795 - pypy/trunk/src/pypy/interpreter Message-ID: <20030613111523.D55CD5A47A@thoth.codespeak.net> Author: arigo Date: Fri Jun 13 13:15:22 2003 New Revision: 795 Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py Log: 'raise' now checks isinstance(Exception) before issubclass(Exception), following Guido's answer Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode_app.py Fri Jun 13 13:15:22 2003 @@ -14,20 +14,21 @@ if type(etype) is str: # warn pass + elif isinstance(etype, Exception): + if value is not None: + raise TypeError, "instance exception may not have a separate value" + value = etype + etype = value.__class__ elif isinstance(etype, type) and issubclass(etype, Exception): if value is None: value = () elif not isinstance(value, tuple): value = (value,) value = etype(*value) - elif isinstance(etype, Exception): - if value is not None: - raise TypeError, "instance exception may not have a separate value" - value = etype - etype = value.__class__ else: - raise TypeError, "exceptions must be classes, instances, or " \ - "strings (deprecated), not %s"%(type(etype).__name__,) + raise TypeError, ("exceptions must be instances or subclasses of " + "Exception or strings (deprecated), not %s" % + (type(etype).__name__,)) return etype, value, traceback def print_expr(x): From mwh at codespeak.net Fri Jun 13 14:27:18 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 14:27:18 +0200 (MEST) Subject: [pypy-svn] rev 796 - pypy/trunk/src/pypy/interpreter Message-ID: <20030613122718.538215A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 14:27:18 2003 New Revision: 796 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py Log: fix for printing exceptions Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Fri Jun 13 14:27:18 2003 @@ -138,7 +138,8 @@ exc_value = self.w_value else: w = space.wrap - exc_typename = space.getattr(self.w_type, w('__name__')) + exc_typename = space.unwrap( + space.getattr(self.w_type, w('__name__'))) exc_value = space.unwrap(space.str(self.w_value)) print >> file, '(application-level)', if exc_value is None: From mwh at codespeak.net Fri Jun 13 14:28:17 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 14:28:17 +0200 (MEST) Subject: [pypy-svn] rev 797 - pypy/trunk/src/pypy/module Message-ID: <20030613122817.21F4D5A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 14:28:16 2003 New Revision: 797 Modified: pypy/trunk/src/pypy/module/builtin_app.py Log: hasattr Modified: pypy/trunk/src/pypy/module/builtin_app.py ============================================================================== --- pypy/trunk/src/pypy/module/builtin_app.py (original) +++ pypy/trunk/src/pypy/module/builtin_app.py Fri Jun 13 14:28:16 2003 @@ -223,3 +223,11 @@ return obj[0].__dict__ except AttributeError: raise TypeError, "vars() argument must have __dict__ attribute" + +def hasattr(ob, attr): + try: + getattr(ob, attr) + return True + except AttributeError: + return False + From mwh at codespeak.net Fri Jun 13 14:46:54 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 14:46:54 +0200 (MEST) Subject: [pypy-svn] rev 798 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613124654.DD6745A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 14:46:54 2003 New Revision: 798 Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py Log: teach None to print itself Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/noneobject.py Fri Jun 13 14:46:54 2003 @@ -18,3 +18,10 @@ return False StdObjSpace.is_true.register(none_is_true, W_NoneObject) + +def none_repr(space, w_none): + return space.wrap('None') + +StdObjSpace.repr.register(none_repr, W_NoneObject) + + From arigo at codespeak.net Fri Jun 13 14:48:00 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Jun 2003 14:48:00 +0200 (MEST) Subject: [pypy-svn] rev 799 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613124800.704385A47A@thoth.codespeak.net> Author: arigo Date: Fri Jun 13 14:48:00 2003 New Revision: 799 Modified: pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/listtype.py Log: list.sort(), simple incomplete version; code by Magnus Lie Hetland Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Fri Jun 13 14:48:00 2003 @@ -386,6 +386,58 @@ _reverse_slice(w_list.ob_item, 0, w_list.ob_size) return space.w_None + + +# Python Quicksort Written by Magnus Lie Hetland +# http://www.hetland.org/python/quicksort.html +def _partition(space, list, start, end): + pivot = list[end] # Partition around the last value + bottom = start-1 # Start outside the area to be partitioned + top = end # Ditto + + done = 0 + while not done: # Until all elements are partitioned... + + while not done: # Until we find an out of place element... + bottom = bottom+1 # ... move the bottom up. + + if bottom == top: # If we hit the top... + done = 1 # ... we are done. + break + + if space.is_true(space.gt(list[bottom], pivot)): # Is the bottom out of place? + list[top] = list[bottom] # Then put it at the top... + break # ... and start searching from the top. + + while not done: # Until we find an out of place element... + top = top-1 # ... move the top down. + + if top == bottom: # If we hit the bottom... + done = 1 # ... we are done. + break + + if space.is_true(space.lt(list[top], pivot)): # Is the top out of place? + list[bottom] = list[top] # Then put it at the bottom... + break # ...and start searching from the bottom. + + list[top] = pivot # Put the pivot in its place. + return top # Return the split point + + +def _quicksort(space, list, start, end): + if start < end: # If there are two or more elements... + split = _partition(space, list, start, end) # ... partition the sublist... + _quicksort(space, list, start, split-1) # ... and sort both halves. + _quicksort(space, list, split+1, end) + +def list_sort(space, w_list): + # XXX Basic quicksort implementation + # XXX this is not stable !! + # XXX no optional argument yet ! + _quicksort(space, w_list.ob_item, 0, w_list.ob_size-1) + return space.w_None + + W_ListType.list_append .register(list_append, W_ListObject, W_ANY) W_ListType.list_insert .register(list_insert, W_ListObject, W_IntObject, W_ANY) W_ListType.list_extend .register(list_extend, W_ListObject, W_ANY) @@ -394,6 +446,7 @@ W_ListType.list_index .register(list_index, W_ListObject, W_ANY) W_ListType.list_count .register(list_count, W_ListObject, W_ANY) W_ListType.list_reverse.register(list_reverse,W_ListObject) +W_ListType.list_sort .register(list_sort, W_ListObject) """ static PyMethodDef list_methods[] = { Modified: pypy/trunk/src/pypy/objspace/std/listtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/listtype.py Fri Jun 13 14:48:00 2003 @@ -14,6 +14,7 @@ list_index = MultiMethod('index', 2) list_count = MultiMethod('count', 2) list_reverse= MultiMethod('reverse',1) + list_sort = MultiMethod('sort', 1) # XXX right now, this is responsible for building a whole new list From mwh at codespeak.net Fri Jun 13 14:56:25 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 14:56:25 +0200 (MEST) Subject: [pypy-svn] rev 800 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613125625.67C495A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 14:56:24 2003 New Revision: 800 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py Log: nasty implementations of str_ljust & str_rjust (needed for dis-goal.py) Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Fri Jun 13 14:56:24 2003 @@ -169,6 +169,21 @@ W_StringType.str_join.register(str_join, W_StringObject, W_ANY) +def str_ljust(space, w_str, w_arg): + # XXX look away for three lines, please :-) -- mwh + u = space.unwrap + w = space.wrap + return w(u(w_str).ljust(u(w_arg))) + +W_StringType.str_ljust.register(str_ljust, W_StringObject, W_ANY) + +def str_rjust(space, w_str, w_arg): + # XXX and another three -- mwh + u = space.unwrap + w = space.wrap + return w(u(w_str).rjust(u(w_arg))) + +W_StringType.str_rjust.register(str_rjust, W_StringObject, W_ANY) def str_unwrap(space, w_str): return w_str._value.value() Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Fri Jun 13 14:56:24 2003 @@ -16,6 +16,8 @@ str_islower = MultiMethod('islower', 1) str_istitle = MultiMethod('istitle', 1) str_isalnum = MultiMethod('isalnum', 1) + str_ljust = MultiMethod('ljust', 2) + str_rjust = MultiMethod('rjust', 2) # XXX we'll worry about the __new__/__init__ distinction later def stringtype_new(space, w_stringtype, w_args, w_kwds): From arigo at codespeak.net Fri Jun 13 15:05:15 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Jun 2003 15:05:15 +0200 (MEST) Subject: [pypy-svn] rev 801 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613130515.202475A47A@thoth.codespeak.net> Author: arigo Date: Fri Jun 13 15:05:14 2003 New Revision: 801 Modified: pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/tupleobject.py Log: fixed list comparison, added tuple comparison Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Fri Jun 13 15:05:14 2003 @@ -147,18 +147,16 @@ return b def list_lt(space, w_list1, w_list2): + # XXX list_le, list_gt, list_ge, list_ne must also be explicitely done items1 = w_list1.ob_item items2 = w_list2.ob_item ncmp = _min(w_list1.ob_size, w_list2.ob_size) # Search for the first index where items are different - p = 0 - while p < ncmp: + for p in range(ncmp): if not space.is_true(space.eq(items1[p], items2[p])): - break - if p >= ncmp: - # No more items to compare -- compare sizes - return space.newbool(vs < ws) - return space.lt(items1[p], items2[p]) + return space.lt(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(w_list1.ob_size < w_list2.ob_size) StdObjSpace.lt.register(list_lt, W_ListObject, W_ListObject) Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Fri Jun 13 15:05:14 2003 @@ -101,6 +101,25 @@ StdObjSpace.eq.register(tuple_eq, W_TupleObject, W_TupleObject) +def _min(a, b): + if a < b: + return a + return b + +def tuple_lt(space, w_tuple1, w_tuple2): + # XXX tuple_le, tuple_gt, tuple_ge, tuple_ne must also be explicitely done + items1 = w_tuple1.wrappeditems + items2 = w_tuple2.wrappeditems + ncmp = _min(len(items1), len(items2)) + # Search for the first index where items are different + for p in range(ncmp): + if not space.is_true(space.eq(items1[p], items2[p])): + return space.lt(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(len(items1) < len(items2)) + +StdObjSpace.lt.register(tuple_lt, W_TupleObject, W_TupleObject) + def tuple_repr(space, w_tuple): # XXX slimy! --mwh return space.wrap(repr(space.unwrap(w_tuple))) From mwh at codespeak.net Fri Jun 13 15:31:06 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 15:31:06 +0200 (MEST) Subject: [pypy-svn] rev 802 - pypy/trunk/src/pypy/module Message-ID: <20030613133106.B3C5C5A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 15:31:06 2003 New Revision: 802 Modified: pypy/trunk/src/pypy/module/sysmodule.py Log: prepend the 'appspace' dir to sys.path Modified: pypy/trunk/src/pypy/module/sysmodule.py ============================================================================== --- pypy/trunk/src/pypy/module/sysmodule.py (original) +++ pypy/trunk/src/pypy/module/sysmodule.py Fri Jun 13 15:31:06 2003 @@ -14,8 +14,10 @@ opd = os.path.dirname pypydir = opd(opd(os.path.abspath(pypy.__file__))) + + appdir = os.path.join(pypydir, 'pypy', 'appspace') - self.path = appdata([p for p in sys.path if p != pypydir]) + self.path = appdata([appdir] + [p for p in sys.path if p != pypydir]) stdout = appdata(sys.stdout) From mwh at codespeak.net Fri Jun 13 15:31:27 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 15:31:27 +0200 (MEST) Subject: [pypy-svn] rev 803 - pypy/trunk/src/pypy/appspace Message-ID: <20030613133127.B2ACE5A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 15:31:27 2003 New Revision: 803 Added: pypy/trunk/src/pypy/appspace/types.py Log: a neutered types.py that we can import Added: pypy/trunk/src/pypy/appspace/types.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/appspace/types.py Fri Jun 13 15:31:27 2003 @@ -0,0 +1,98 @@ +"""Define names for all type symbols known in the standard interpreter. + +Types that are part of optional modules (e.g. array) are not listed. +""" +from __future__ import generators + +import sys + +# Iterators in Python aren't a matter of type but of protocol. A large +# and changing number of builtin types implement *some* flavor of +# iterator. Don't check the type! Use hasattr to check for both +# "__iter__" and "next" attributes instead. + +NoneType = type(None) +TypeType = type +ObjectType = object + +IntType = int +try: + LongType = long +except NameError: + pass +FloatType = float +try: + ComplexType = complex +except NameError: + pass + +StringType = str +try: + UnicodeType = unicode + StringTypes = (StringType, UnicodeType) +except NameError: + StringTypes = (StringType,) + +try: + BufferType = type(buffer('')) +except NameError: + pass + +TupleType = tuple +ListType = list +DictType = DictionaryType = dict + +def _f(): pass +FunctionType = type(_f) +LambdaType = type(lambda: None) # Same as FunctionType +try: + CodeType = type(_f.func_code) +except RuntimeError: + # Execution in restricted environment + pass + +def g(): + yield 1 +GeneratorType = type(g()) +del g + +class _C: + def _m(self): pass +ClassType = type(_C) +try: + UnboundMethodType = type(_C._m) # Same as MethodType +except AttributeError: + pass +_x = _C() +InstanceType = type(_x) +MethodType = type(_x._m) + +BuiltinFunctionType = type(len) +BuiltinMethodType = type([].append) # Same as BuiltinFunctionType + +ModuleType = type(sys) +try: + FileType = file + XRangeType = type(xrange(0)) +except NameError: + pass + +try: + raise TypeError +except TypeError: + try: + tb = sys.exc_info()[2] + TracebackType = type(tb) + FrameType = type(tb.tb_frame) + except AttributeError: + # In the restricted environment, exc_info returns (None, None, + # None) Then, tb.tb_frame gives an attribute error + pass + tb = None; del tb + +SliceType = type(slice(0)) +EllipsisType = type(Ellipsis) + +#DictProxyType = type(TypeType.__dict__) + +del sys, _f, _C, _x, generators # Not for export From mwh at codespeak.net Fri Jun 13 15:38:16 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 15:38:16 +0200 (MEST) Subject: [pypy-svn] rev 804 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613133816.267805A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 15:38:15 2003 New Revision: 804 Modified: pypy/trunk/src/pypy/objspace/std/slicetype.py Log: slice_new Modified: pypy/trunk/src/pypy/objspace/std/slicetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/slicetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/slicetype.py Fri Jun 13 15:38:15 2003 @@ -5,3 +5,24 @@ class W_SliceType(W_TypeObject): typename = 'slice' + +def slicetype_new(space, w_slicetype, w_args, w_kwds): + if space.is_true(w_kwds): + raise OperationError(space.w_TypeError, + space.wrap("no keyword arguments expected")) + args = space.unpackiterable(w_args) + start = space.w_None + stop = space.w_None + step = space.w_None + if len(args) == 1: + stop, = args + elif len(args) == 2: + start, stop = args + elif len(args) == 3: + start, stop, step = args + else: + raise OperationError(space.w_TypeError, + space.wrap("slice() takes at least 1 argument")) + return space.newslice(start, stop, step) + +StdObjSpace.new.register(slicetype_new, W_SliceType, W_ANY, W_ANY) From mwh at codespeak.net Fri Jun 13 15:41:53 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 15:41:53 +0200 (MEST) Subject: [pypy-svn] rev 805 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613134153.E0C4A5A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 15:41:53 2003 New Revision: 805 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: Ellipsis Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Fri Jun 13 15:41:53 2003 @@ -144,11 +144,13 @@ self.w_False = W_BoolObject(self, False) self.w_True = W_BoolObject(self, True) self.w_NotImplemented = self.wrap(NotImplemented) # XXX do me + self.w_Ellipsis = self.wrap(Ellipsis) # XXX do me too for_builtins = {"False": self.w_False, "True" : self.w_True, "None" : self.w_None, "NotImplemented": self.w_NotImplemented, + "Ellipsis": self.w_Ellipsis, } # types From arigo at codespeak.net Fri Jun 13 15:46:02 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Jun 2003 15:46:02 +0200 (MEST) Subject: [pypy-svn] rev 806 - pypy/trunk/src/goals Message-ID: <20030613134602.71A335A47A@thoth.codespeak.net> Author: arigo Date: Fri Jun 13 15:46:02 2003 New Revision: 806 Added: pypy/trunk/src/goals/dis-pregoal.py Log: this is what works right now. There are more type-checking tricks in dis.dis() not really supported yet. Added: pypy/trunk/src/goals/dis-pregoal.py ============================================================================== --- (empty file) +++ pypy/trunk/src/goals/dis-pregoal.py Fri Jun 13 15:46:02 2003 @@ -0,0 +1,2 @@ +import dis +dis.disassemble(dis.dis.func_code) From mwh at codespeak.net Fri Jun 13 16:12:56 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 13 Jun 2003 16:12:56 +0200 (MEST) Subject: [pypy-svn] rev 807 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030613141256.863C85A47A@thoth.codespeak.net> Author: mwh Date: Fri Jun 13 16:12:56 2003 New Revision: 807 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: add a version of StdObjSpace.is_ that speeds up running dis-pregoal.py by 40% or so :-) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Fri Jun 13 16:12:56 2003 @@ -257,6 +257,17 @@ getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute + def is_(self, w_one, w_two): + # XXX this is a hopefully temporary speed hack: + from cpythonobject import W_CPythonObject + if isinstance(w_one, W_CPythonObject): + if isinstance(w_two, W_CPythonObject): + return self.newbool(w_one.cpyobj is w_two.cpyobj) + else: + return self.newbool(0) + else: + return self.newbool(w_one is w_two) + # add all regular multimethods to StdObjSpace for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: From arigo at codespeak.net Fri Jun 13 16:31:02 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Jun 2003 16:31:02 +0200 (MEST) Subject: [pypy-svn] rev 808 - in pypy/trunk/src/pypy: appspace interpreter Message-ID: <20030613143102.B122F5A47A@thoth.codespeak.net> Author: arigo Date: Fri Jun 13 16:31:02 2003 New Revision: 808 Modified: pypy/trunk/src/pypy/appspace/types.py pypy/trunk/src/pypy/interpreter/pyframe.py Log: clear error message saying that generators aren't ready Modified: pypy/trunk/src/pypy/appspace/types.py ============================================================================== --- pypy/trunk/src/pypy/appspace/types.py (original) +++ pypy/trunk/src/pypy/appspace/types.py Fri Jun 13 16:31:02 2003 @@ -53,7 +53,11 @@ def g(): yield 1 -GeneratorType = type(g()) +try: + GeneratorType = type(g()) +except: + # Refusing generators + pass del g class _C: Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Fri Jun 13 16:31:02 2003 @@ -289,8 +289,9 @@ """Signals a 'yield' statement. Argument is the wrapped object to return.""" def unrollstack(self, frame): - w_yieldedvalue = self.args[0] - raise ExitFrame(w_yieldedvalue) + # XXX generators + raise OperationError(frame.space.w_Exception, + frame.space.wrap("generators are not ready yet")) class StopUnrolling(Exception): "Signals the end of the block stack unrolling." From hpk at codespeak.net Sat Jun 14 19:15:18 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 14 Jun 2003 19:15:18 +0200 (MEST) Subject: [pypy-svn] rev 809 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030614171518.496895A415@thoth.codespeak.net> Author: hpk Date: Sat Jun 14 19:15:16 2003 New Revision: 809 Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py pypy/trunk/src/pypy/objspace/std/cpythonobject.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/floatobject.py pypy/trunk/src/pypy/objspace/std/funcobject.py pypy/trunk/src/pypy/objspace/std/instmethobject.py pypy/trunk/src/pypy/objspace/std/iterobject.py pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/longobject.py pypy/trunk/src/pypy/objspace/std/noneobject.py pypy/trunk/src/pypy/objspace/std/objectobject.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/sliceobject.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/tupleobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/userobject.py Log: revised multimethod registration machinery - now functions whose name is of the form "X__Y1_Y2_..." are registered on the multimethod "X" on StdObjSpace or (if that doesn't exist) on an alternatively provided namespace's multimethod. The Y1, Y2, ... specify the "multimethod implementation signature" and must match the number of arguments the function takes. Otherwise a value Error is raised. For a given Y first "W_Y" is looked up and if that doesn't exist "W_YObject" to allow for short names in signature specs. - to invoke this automatic you call pypy.objspace.std.objspace.register_all(module_dict, alt_ns) - example: def lt__ANY_ANY(space, w_a, w_b): ... will result in a call to StdObjSpace.lt.register(lt__ANY_ANY, W_ANY, W_ANY) - fixed some errors while walking through the source - you don't have to use the register_all machinery i.e. you can still use the direct StdObjSpace.NAME.register - remaining is "intobject.py" because test/test_intobject.py uses the intobject.* names directly instead of going through the StdObjSpace. Actually, at first i also changed intobject and test_intobject but i didn't understand the "OverflowError" handling so i reverted my changes to not destroy anything could someone explain the r_int / int / long / overflow business on pypy-dev? Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Sat Jun 14 19:15:16 2003 @@ -13,7 +13,6 @@ def __nonzero__(w_self): raise Exception, "you cannot do that, you must use space.is_true()" - registerimplementation(W_BoolObject) # bool-to-int delegation requires translating the .boolvar attribute @@ -24,17 +23,17 @@ W_BoolObject.delegate_once[intobject.W_IntObject] = bool_to_int -def bool_is_true(space, w_bool): +def is_true__Bool(space, w_bool): return w_bool.boolval -StdObjSpace.is_true.register(bool_is_true, W_BoolObject) -StdObjSpace.unwrap. register(bool_is_true, W_BoolObject) +def unwrap__Bool(space, w_bool): + return w_bool.boolval -def bool_repr(space, w_bool): +def repr__Bool(space, w_bool): if w_bool.boolval: return space.wrap('True') else: return space.wrap('False') -StdObjSpace.repr.register(bool_repr, W_BoolObject) - + +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py Sat Jun 14 19:15:16 2003 @@ -162,15 +162,13 @@ multimethod.register(cpython_f, *arglist) -def cpython_is_true(space, w_obj): +def is_true__CPython(space, w_obj): obj = space.unwrap(w_obj) try: return operator.truth(obj) except: wrap_exception(space) -StdObjSpace.is_true.register(cpython_is_true, W_CPythonObject) - # slicing def old_slice(index): @@ -185,7 +183,7 @@ return start, stop return None -def cpython_getitem(space, w_obj, w_index): +def getitem__CPython_ANY(space, w_obj, w_index): obj = space.unwrap(w_obj) index = space.unwrap(w_index) sindex = old_slice(index) @@ -198,7 +196,7 @@ wrap_exception(space) return space.wrap(result) -def cpython_setitem(space, w_obj, w_index, w_value): +def setitem__CPython_ANY_ANY(space, w_obj, w_index, w_value): obj = space.unwrap(w_obj) index = space.unwrap(w_index) value = space.unwrap(w_value) @@ -211,7 +209,7 @@ except: wrap_exception(space) -def cpython_delitem(space, w_obj, w_index): +def delitem__CPython_ANY(space, w_obj, w_index): obj = space.unwrap(w_obj) index = space.unwrap(w_index) sindex = old_slice(index) @@ -223,12 +221,7 @@ except: wrap_exception(space) -StdObjSpace.getitem.register(cpython_getitem, W_CPythonObject, W_ANY) -StdObjSpace.setitem.register(cpython_getitem, W_CPythonObject, W_ANY, W_ANY) -StdObjSpace.delitem.register(cpython_getitem, W_CPythonObject, W_ANY) - - -def cpython_next(space, w_obj): +def next__CPython(space, w_obj): obj = space.unwrap(w_obj) try: result = obj.next() @@ -238,10 +231,7 @@ wrap_exception(space) return space.wrap(result) -StdObjSpace.next.register(cpython_next, W_CPythonObject) - - -def cpython_call(space, w_obj, w_arguments, w_keywords): +def call__CPython_ANY_ANY(space, w_obj, w_arguments, w_keywords): # XXX temporary hack similar to objspace.trivial.call() callable = space.unwrap(w_obj) args = space.unwrap(w_arguments) @@ -253,4 +243,4 @@ wrap_exception(space) return space.wrap(result) -StdObjSpace.call.register(cpython_call, W_CPythonObject, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Sat Jun 14 19:15:16 2003 @@ -9,54 +9,36 @@ # 'eq' falls back to 'is' -def default_eq(space, w_a, w_b): +def eq__ANY_ANY(space, w_a, w_b): return space.is_(w_a, w_b) -StdObjSpace.eq.register(default_eq, W_ANY, W_ANY) - - # 'ne' -> 'eq', 'le/gt/ge' -> 'lt' -def default_ne(space, w_a, w_b): +def ne__ANY_ANY(space, w_a, w_b): return space.not_(space.eq(w_a, w_b)) -def default_le(space, w_a, w_b): +def le__ANY_ANY(space, w_a, w_b): return space.not_(space.lt(w_b, w_a)) -def default_gt(space, w_a, w_b): +def gt__ANY_ANY(space, w_a, w_b): return space.lt(w_b, w_a) -def default_ge(space, w_a, w_b): +def ge__ANY_ANY(space, w_a, w_b): return space.not_(space.lt(w_a, w_b)) -StdObjSpace.ne.register(default_ne, W_ANY, W_ANY) -StdObjSpace.le.register(default_le, W_ANY, W_ANY) -StdObjSpace.gt.register(default_gt, W_ANY, W_ANY) -StdObjSpace.ge.register(default_ge, W_ANY, W_ANY) - - # 'id' falls back to the address of the wrapper -def default_id(space, w_obj): +def id__ANY(space, w_obj): import intobject return intobject.W_IntObject(space, id(w_obj)) -StdObjSpace.id.register(default_id, W_ANY) - - # this 'not' implementation should be fine for most cases -def default_not(space, w_obj): +def not__ANY(space, w_obj): return space.newbool(not space.is_true(w_obj)) -StdObjSpace.not_.register(default_not, W_ANY) - - # everything is True unless otherwise specified -def default_is_true(space, w_obj): +def is_true__ANY(space, w_obj): return True -StdObjSpace.is_true.register(default_is_true, W_ANY) - - # in-place operators fall back to their non-in-place counterpart for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: @@ -69,7 +51,7 @@ # 'contains' falls back to iteration -def default_contains(space, w_iterable, w_lookfor): +def contains__ANY_ANY(space, w_iterable, w_lookfor): w_iter = space.iter(w_iterable) while 1: try: @@ -79,12 +61,9 @@ if space.is_true(space.eq(w_next, w_lookfor)): return space.w_True -StdObjSpace.contains.register(default_contains, W_ANY, W_ANY) - - # '__get__(descr, inst, cls)' returns 'descr' by default -def default_get(space, w_descr, w_inst, w_cls): +def get__ANY_ANY_ANY(space, w_descr, w_inst, w_cls): return w_descr -StdObjSpace.get.register(default_get, W_ANY, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Sat Jun 14 19:15:16 2003 @@ -68,35 +68,27 @@ registerimplementation(W_DictObject) -def dict_is_true(space, w_dict): +def is_true__Dict(space, w_dict): return not not w_dict.non_empties() -StdObjSpace.is_true.register(dict_is_true, W_DictObject) - -def dict_unwrap(space, w_dict): +def unwrap__Dict(space, w_dict): result = {} for w_key, cell in w_dict.non_empties(): result[space.unwrap(w_key)] = space.unwrap(cell.get()) return result -StdObjSpace.unwrap.register(dict_unwrap, W_DictObject) - -def getitem_dict_any(space, w_dict, w_lookup): +def getitem__Dict_ANY(space, w_dict, w_lookup): data = w_dict.non_empties() for w_key, cell in data: if space.is_true(space.eq(w_lookup, w_key)): return cell.get() raise OperationError(space.w_KeyError, w_lookup) -StdObjSpace.getitem.register(getitem_dict_any, W_DictObject, W_ANY) - -def setitem_dict_any_any(space, w_dict, w_newkey, w_newvalue): +def setitem__Dict_ANY_ANY(space, w_dict, w_newkey, w_newvalue): cell = w_dict._cell(space,w_newkey) cell.set(w_newvalue) -StdObjSpace.setitem.register(setitem_dict_any_any, W_DictObject, W_ANY, W_ANY) - -def delitem_dict_any(space, w_dict, w_lookup): +def delitem__Dict_ANY(space, w_dict, w_lookup): data = w_dict.non_empties() for w_key,cell in data: if space.is_true(space.eq(w_lookup, w_key)): @@ -104,22 +96,16 @@ return raise OperationError(space.w_KeyError, w_lookup) -StdObjSpace.delitem.register(delitem_dict_any, W_DictObject, W_ANY) - -def len_dict(space, w_dict): +def len__Dict(space, w_dict): return space.wrap(len(w_dict.non_empties())) -StdObjSpace.len.register(len_dict, W_DictObject) - -def contains_dict_any(space, w_dict, w_lookup): +def contains__Dict_ANY(space, w_dict, w_lookup): data = w_dict.non_empties() for w_key,cell in data: if space.is_true(space.eq(w_lookup, w_key)): return space.w_True return space.w_False -StdObjSpace.contains.register(contains_dict_any, W_DictObject, W_ANY) - ##def getattr_dict(space, w_dict, w_attr): ## if space.is_true(space.eq(w_attr, space.wrap('copy'))): ## w_builtinfn = make_builtin_func(space, W_DictObject.copy) @@ -137,7 +123,7 @@ ##StdObjSpace.getattr.register(getattr_dict, W_DictObject, W_ANY) -def eq_dict_dict(space, w_left, w_right): +def eq__Dict_Dict(space, w_left, w_right): if len(w_left.data) != len(w_right.data): return space.newbool(0) for w_k, hash, cell in w_left.data: @@ -150,29 +136,24 @@ return space.newbool(r) return space.newbool(1) -StdObjSpace.eq.register(eq_dict_dict, W_DictObject, W_DictObject) - - -def dict_copy(space, w_self): +def dict_copy__Dict(space, w_self): return W_DictObject(space, [(w_key,cell.get()) for w_key,cell in w_self.non_empties()]) -def dict_items(space, w_self): +def dict_items__Dict(space, w_self): return space.newlist([ space.newtuple([w_key,cell.get()]) for w_key,cell in w_self.non_empties()]) -def dict_keys(space, w_self): +def dict_keys__Dict(space, w_self): return space.newlist([ w_key for w_key,cell in w_self.non_empties()]) -def dict_values(space, w_self): +def dict_values__Dict(space, w_self): return space.newlist([ cell.get() for w_key,cell in w_self.non_empties()]) -W_DictType.dict_copy .register(dict_copy, W_DictObject) -W_DictType.dict_items .register(dict_items, W_DictObject) -W_DictType.dict_keys .register(dict_keys, W_DictObject) -W_DictType.dict_values.register(dict_values, W_DictObject) + +register_all(vars(), W_DictType) Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/floatobject.py Sat Jun 14 19:15:16 2003 @@ -39,69 +39,55 @@ #?StdObjSpace.float.register(float_float, W_FloatObject) -def float_unwrap(space, w_float): +def unwrap__Float(space, w_float): return w_float.floatval -StdObjSpace.unwrap.register(float_unwrap, W_FloatObject) - -def float_repr(space, w_float): +def repr__Float(space, w_float): ## %reimplement% # uses CPython "repr" builtin function return space.wrap(repr(w_float.floatval)) -StdObjSpace.repr.register(float_repr, W_FloatObject) - -def float_str(space, w_float): +def str__Float(space, w_float): ## %reimplement% # uses CPython "str" builtin function return space.wrap(str(w_float.floatval)) -StdObjSpace.str.register(float_str, W_FloatObject) - -def float_float_lt(space, w_float1, w_float2): +def lt__Float_Float(space, w_float1, w_float2): i = w_float1.floatval j = w_float2.floatval return space.newbool( i < j ) -StdObjSpace.lt.register(float_float_lt, W_FloatObject, W_FloatObject) -def float_float_le(space, w_float1, w_float2): +def le__Float_Float(space, w_float1, w_float2): i = w_float1.floatval j = w_float2.floatval return space.newbool( i <= j ) -StdObjSpace.le.register(float_float_le, W_FloatObject, W_FloatObject) -def float_float_eq(space, w_float1, w_float2): +def eq__Float_Float(space, w_float1, w_float2): i = w_float1.floatval j = w_float2.floatval return space.newbool( i == j ) -StdObjSpace.eq.register(float_float_eq, W_FloatObject, W_FloatObject) -def float_float_ne(space, w_float1, w_float2): +def ne__Float_Float(space, w_float1, w_float2): i = w_float1.floatval j = w_float2.floatval return space.newbool( i != j ) -StdObjSpace.ne.register(float_float_ne, W_FloatObject, W_FloatObject) -def float_float_gt(space, w_float1, w_float2): +def gt__Float_Float(space, w_float1, w_float2): i = w_float1.floatval j = w_float2.floatval return space.newbool( i > j ) -StdObjSpace.gt.register(float_float_gt, W_FloatObject, W_FloatObject) -def float_float_ge(space, w_float1, w_float2): +def ge__Float_Float(space, w_float1, w_float2): i = w_float1.floatval j = w_float2.floatval return space.newbool( i >= j ) -StdObjSpace.ge.register(float_float_ge, W_FloatObject, W_FloatObject) -def float_hash(space,w_value): +def hash__Float(space,w_value): ## %reimplement% # real Implementation should be taken from _Py_HashDouble in object.c return space.wrap(hash(w_value.floatval)) -StdObjSpace.hash.register(float_hash, W_FloatObject) - -def float_float_add(space, w_float1, w_float2): +def add__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval try: @@ -110,9 +96,7 @@ raise FailedToImplement(space.w_FloatingPointError, space.wrap("float addition")) return W_FloatObject(space, z) -StdObjSpace.add.register(float_float_add, W_FloatObject, W_FloatObject) - -def float_float_sub(space, w_float1, w_float2): +def sub__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval try: @@ -121,9 +105,7 @@ raise FailedToImplement(space.w_FloatingPointError, space.wrap("float substraction")) return W_FloatObject(space, z) -StdObjSpace.sub.register(float_float_sub, W_FloatObject, W_FloatObject) - -def float_float_mul(space, w_float1, w_float2): +def mul__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval try: @@ -132,9 +114,7 @@ raise FailedToImplement(space.w_FloatingPointError, space.wrap("float multiplication")) return W_FloatObject(space, z) -StdObjSpace.mul.register(float_float_mul, W_FloatObject, W_FloatObject) - -def float_float_div(space, w_float1, w_float2): +def div__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval try: @@ -144,9 +124,7 @@ # no overflow return W_FloatObject(space, z) -StdObjSpace.div.register(float_float_div, W_FloatObject, W_FloatObject) - -def float_float_mod(space, w_float1, w_float2): +def mod__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval if y == 0.0: @@ -161,9 +139,7 @@ return W_FloatObject(space, mod) -StdObjSpace.mod.register(float_float_mod, W_FloatObject, W_FloatObject) - -def float_float_divmod(space, w_float1, w_float2): +def divmod__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval if y == 0.0: @@ -193,9 +169,7 @@ return space.newtuple([W_FloatObject(space, floordiv), W_FloatObject(space, mod)]) -StdObjSpace.divmod.register(float_float_divmod, W_FloatObject, W_FloatObject) - -def float_float_pow(space, w_float1,w_float2,thirdArg=None): +def pow__Float_Float_ANY(space, w_float1,w_float2,thirdArg=None): if thirdArg is not None: raise FailedToImplement(space.w_TypeError,space.wrap("pow() 3rd argument not allowed unless all arguments are integers")) x = w_float1.floatval @@ -206,31 +180,21 @@ raise FailedToImplement(space.w_OverflowError, space.wrap("float power")) return W_FloatObject(space, z) -StdObjSpace.pow.register(float_float_pow, W_FloatObject, W_FloatObject) - -def float_neg(space, w_float1): +def neg__Float(space, w_float1): return W_FloatObject(space, w_float1.floatval) -StdObjSpace.neg.register(float_neg, W_FloatObject) - -def float_pos(space, w_float): +def pos__Float(space, w_float): if w_float.__class__ == W_FloatObject: return w_float else: return W_FloatObject(space, w_float.floatval) -StdObjSpace.pos.register(float_pos, W_FloatObject) - -def float_abs(space, w_float): +def abs__Float(space, w_float): return W_FloatObject(space, fabs(w_float.floatval)) -StdObjSpace.abs.register(float_abs, W_FloatObject) - -def float_nonzero(space, w_float): +def is_true__Float(space, w_float): return w_float.floatval != 0.0 -StdObjSpace.is_true.register(float_nonzero, W_FloatObject) - ######## coersion must be done later later = """ def float_coerce(space, w_float): @@ -241,3 +205,6 @@ StdObjSpace.coerce.register(float_coerce, W_FloatObject) """ + + +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Sat Jun 14 19:15:16 2003 @@ -19,20 +19,17 @@ registerimplementation(W_FuncObject) -def function_unwrap(space, w_function): +def unwrap__Func(space, w_function): # XXX this is probably a temporary hack def proxy_function(*args, **kw): w_arguments = space.wrap(args) w_keywords = space.wrap(kw) - w_result = func_call(space, w_function, w_arguments, w_keywords) + w_result = call__Func_ANY_ANY(space, w_function, w_arguments, w_keywords) return space.unwrap(w_result) # XXX no closure implemented return proxy_function -StdObjSpace.unwrap.register(function_unwrap, W_FuncObject) - - -def func_call(space, w_function, w_arguments, w_keywords): +def call__Func_ANY_ANY(space, w_function, w_arguments, w_keywords): somecode = w_function.code w_globals = w_function.w_globals w_locals = somecode.build_arguments(space, w_arguments, w_keywords, @@ -41,18 +38,13 @@ w_ret = somecode.eval_code(space, w_globals, w_locals) return w_ret -StdObjSpace.call.register(func_call, W_FuncObject, W_ANY, W_ANY) - - -def func_get(space, w_function, w_instance, w_cls): +def get__Func_ANY_ANY(space, w_function, w_instance, w_cls): return W_InstMethObject(space, w_instance, w_function) -StdObjSpace.get.register(func_get, W_FuncObject, W_ANY, W_ANY) - -def func_getattr(space, w_function, w_attr): +def getattr__Func_ANY(space, w_function, w_attr): if space.is_true(space.eq(w_attr, space.wrap('func_code'))): return space.wrap(w_function.code) else: raise FailedToImplement -StdObjSpace.getattr.register(func_getattr, W_FuncObject, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Sat Jun 14 19:15:16 2003 @@ -28,13 +28,12 @@ #StdObjSpace.unwrap.register(function_unwrap, W_FuncObject) -def instmeth_call(space, w_instmeth, w_arguments, w_keywords): +def call__InstMeth_ANY_ANY(space, w_instmeth, w_arguments, w_keywords): w_args = space.add(space.newtuple([w_instmeth.w_im_self]), w_arguments) w_ret = space.call(w_instmeth.w_im_func, w_args, w_keywords) return w_ret -StdObjSpace.call.register(instmeth_call, W_InstMethObject, W_ANY, W_ANY) - - # XXX do __get__ for instance methods + +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/iterobject.py Sat Jun 14 19:15:16 2003 @@ -14,12 +14,10 @@ registerimplementation(W_SeqIterObject) -def iter_seqiter(space, w_seqiter): +def iter__SeqIter(space, w_seqiter): return w_seqiter -StdObjSpace.iter.register(iter_seqiter, W_SeqIterObject) - -def next_seqiter(space, w_seqiter): +def next__SeqIter(space, w_seqiter): try: w_item = space.getitem(w_seqiter.w_seq, space.wrap(w_seqiter.index)) except OperationError, e: @@ -29,4 +27,4 @@ w_seqiter.index += 1 return w_item -StdObjSpace.next.register(next_seqiter, W_SeqIterObject) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Sat Jun 14 19:15:16 2003 @@ -32,24 +32,18 @@ registerimplementation(W_ListObject) -def list_unwrap(space, w_list): +def unwrap__List(space, w_list): items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]] return list(items) -StdObjSpace.unwrap.register(list_unwrap, W_ListObject) - -def list_is_true(space, w_list): +def is_true__List(space, w_list): return not not w_list.ob_size -StdObjSpace.is_true.register(list_is_true, W_ListObject) - -def list_len(space, w_list): +def len__List(space, w_list): result = w_list.ob_size return W_IntObject(space, result) -StdObjSpace.len.register(list_len, W_ListObject) - -def getitem_list_int(space, w_list, w_index): +def getitem__List_Int(space, w_list, w_index): items = w_list.ob_item idx = w_index.intval if idx < 0: @@ -60,9 +54,7 @@ w_item = items[idx] return w_item -StdObjSpace.getitem.register(getitem_list_int, W_ListObject, W_IntObject) - -def getitem_list_slice(space, w_list, w_slice): +def getitem__List_Slice(space, w_list, w_slice): items = w_list.ob_item w_length = space.wrap(w_list.ob_size) w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length) @@ -79,15 +71,11 @@ w_res.ob_size = slicelength return w_res -StdObjSpace.getitem.register(getitem_list_slice, W_ListObject, W_SliceObject) - -def list_iter(space, w_list): +def iter__List(space, w_list): import iterobject return iterobject.W_SeqIterObject(space, w_list) -StdObjSpace.iter.register(list_iter, W_ListObject) - -def list_add(space, w_list1, w_list2): +def add__List_List(space, w_list1, w_list2): w_res = W_ListObject(space, []) newlen = w_list1.ob_size + w_list2.ob_size _list_resize(w_res, newlen) @@ -104,9 +92,7 @@ w_res.ob_size = p return w_res -StdObjSpace.add.register(list_add, W_ListObject, W_ListObject) - -def list_int_mul(space, w_list, w_int): +def mul__List_Int(space, w_list, w_int): w_res = W_ListObject(space, []) times = w_int.intval src = w_list.ob_item @@ -122,14 +108,10 @@ w_res.ob_size = p return w_res -StdObjSpace.mul.register(list_int_mul, W_ListObject, W_IntObject) - -def int_list_mul(space, w_int, w_list): - return list_int_mul(space, w_list, w_int) +def mul__Int_List(space, w_int, w_list): + return mul__List_Int(space, w_list, w_int) -StdObjSpace.mul.register(int_list_mul, W_IntObject, W_ListObject) - -def list_eq(space, w_list1, w_list2): +def eq__List_List(space, w_list1, w_list2): items1 = w_list1.ob_item items2 = w_list2.ob_item if w_list1.ob_size != w_list2.ob_size: @@ -139,14 +121,12 @@ return space.w_False return space.w_True -StdObjSpace.eq.register(list_eq, W_ListObject, W_ListObject) - def _min(a, b): if a < b: return a return b -def list_lt(space, w_list1, w_list2): +def lt__List_List(space, w_list1, w_list2): # XXX list_le, list_gt, list_ge, list_ne must also be explicitely done items1 = w_list1.ob_item items2 = w_list2.ob_item @@ -158,12 +138,10 @@ # No more items to compare -- compare sizes return space.newbool(w_list1.ob_size < w_list2.ob_size) -StdObjSpace.lt.register(list_lt, W_ListObject, W_ListObject) - # upto here, lists are nearly identical to tuples, despite the # fact that we now support over-allocation! -def setitem_list_int(space, w_list, w_index, w_any): +def setitem__List_Int_ANY(space, w_list, w_index, w_any): items = w_list.ob_item idx = w_index.intval if idx < 0: @@ -174,10 +152,8 @@ items[idx] = w_any return space.w_None -StdObjSpace.setitem.register(setitem_list_int, W_ListObject, W_IntObject, W_ANY) - # not trivial! -def setitem_list_slice(space, w_list, w_slice, w_list2): +def setitem__List_Slice_List(space, w_list, w_slice, w_list2): items = w_list.ob_item w_length = space.wrap(w_list.ob_size) w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length) @@ -194,9 +170,7 @@ w_res.ob_size = slicelength return w_res -StdObjSpace.setitem.register(setitem_list_slice, W_ListObject, W_SliceObject, W_ListObject) - -def repr_list(space, w_list): +def repr__List(space, w_list): w = space.wrap a = space.add reprs_w = map(space.repr, space.unpackiterable(w_list)) @@ -205,8 +179,6 @@ return a(a(w('['), space.call_function(w_bm, space.newlist(reprs_w))), w(']')) return space.newstring([]) -StdObjSpace.repr.register(repr_list, W_ListObject) - # adapted C code def _roundupsize(n): nbits = r_uint(0) @@ -280,15 +252,15 @@ items[where] = w_any w_list.ob_size += 1 -def list_insert(space, w_list, w_where, w_any): +def list_insert__List_Int_ANY(space, w_list, w_where, w_any): _ins1(w_list, w_where.intval, w_any) return space.w_None -def list_append(space, w_list, w_any): +def list_append__List_ANY(space, w_list, w_any): _ins1(w_list, w_list.ob_size, w_any) return space.w_None -def list_extend(space, w_list, w_any): +def list_extend__List_List(space, w_list, w_any): lis = space.unpackiterable(w_any) newlen = w_list.ob_size + len(lis) _list_resize(w_list, newlen) @@ -322,7 +294,7 @@ w_list.ob_size -= d # note that the default value will come back wrapped!!! -def list_pop(space, w_list, w_idx=-1): +def list_pop__List_Int(space, w_list, w_idx=-1): if w_list.ob_size == 0: raise OperationError(space.w_IndexError, space.wrap("pop from empty list")) @@ -336,7 +308,7 @@ _del_slice(w_list, i, i+1) return w_res -def list_remove(space, w_list, w_any): +def list_remove__List_ANY(space, w_list, w_any): eq = space.eq items = w_list.ob_item for i in range(w_list.ob_size): @@ -347,7 +319,7 @@ raise OperationError(space.w_IndexError, space.wrap("list.remove(x): x not in list")) -def list_index(space, w_list, w_any): +def list_index__List_ANY(space, w_list, w_any): eq = space.eq items = w_list.ob_item for i in range(w_list.ob_size): @@ -357,7 +329,7 @@ raise OperationError(space.w_ValueError, space.wrap("list.index(x): x not in list")) -def list_count(space, w_list, w_any): +def list_count__List_ANY(space, w_list, w_any): eq = space.eq items = w_list.ob_item count = r_int(0) @@ -379,7 +351,7 @@ lo += 1 hi -= 1 -def list_reverse(space, w_list): +def list_reverse__List(space, w_list): if w_list.ob_size > 1: _reverse_slice(w_list.ob_item, 0, w_list.ob_size) return space.w_None @@ -428,7 +400,7 @@ _quicksort(space, list, start, split-1) # ... and sort both halves. _quicksort(space, list, split+1, end) -def list_sort(space, w_list): +def list_sort__List(space, w_list): # XXX Basic quicksort implementation # XXX this is not stable !! # XXX no optional argument yet ! @@ -436,16 +408,6 @@ return space.w_None -W_ListType.list_append .register(list_append, W_ListObject, W_ANY) -W_ListType.list_insert .register(list_insert, W_ListObject, W_IntObject, W_ANY) -W_ListType.list_extend .register(list_extend, W_ListObject, W_ANY) -W_ListType.list_pop .register(list_pop, W_ListObject, W_IntObject) -W_ListType.list_remove .register(list_remove, W_ListObject, W_ANY) -W_ListType.list_index .register(list_index, W_ListObject, W_ANY) -W_ListType.list_count .register(list_count, W_ListObject, W_ANY) -W_ListType.list_reverse.register(list_reverse,W_ListObject) -W_ListType.list_sort .register(list_sort, W_ListObject) - """ static PyMethodDef list_methods[] = { {"append", (PyCFunction)listappend, METH_O, append_doc}, @@ -460,3 +422,5 @@ {NULL, NULL} /* sentinel */ }; """ + +register_all(vars(), W_ListType) Modified: pypy/trunk/src/pypy/objspace/std/longobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/longobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/longobject.py Sat Jun 14 19:15:16 2003 @@ -15,7 +15,7 @@ def long(space,w_value): return applicationfile.call(space,"long_long",[w_value]) -def long_long_add(space, w_long1, w_long2): +def add__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -24,7 +24,7 @@ raise OperationError(OverflowError, "long addition") return W_LongObject(space, z) -def long_long_sub(space, w_long1, w_long2): +def sub__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -33,7 +33,7 @@ raise OperationError(Error, e) return W_LongObject(space, z) -def long_long_mul(space, w_long1, w_long2): +def mul__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -42,7 +42,7 @@ raise OperationError(OverflowError, "long multiplication") return W_LongObject(space, z) -def long_long_floordiv(space, w_long1, w_long2): +def floordiv__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -52,7 +52,7 @@ # no overflow return W_LongObject(space, z) -def long_long_truediv(space, w_long1, w_long2): +def truediv__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -67,7 +67,7 @@ else: long_long_div = long_long_truediv -def long_long_mod(space, w_long1, w_long2): +def mod__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -77,7 +77,7 @@ # no overflow return W_LongObject(space, z) -def long_long_divmod(space, w_long1, w_long2): +def divmod__Long_Long(space, w_long1, w_long2): x = w_long1.longval y = w_long2.longval try: @@ -89,7 +89,7 @@ return W_TupleObject(space, [W_LongObject(space, z), W_LongObject(space, m)]) -def long_long_pow(space, w_long1,w_long2): +def pow__Long_Long(space, w_long1,w_long2): x = w_long1.longval y = w_long2.longval try: @@ -98,7 +98,7 @@ raise OperationError(OverflowError, "long multiplication") return W_LongObject(space, z) -def long_long_long_pow(space, w_long1,w_long2,w_long3): +def pow__Long_Long_ANY(space, w_long1,w_long2,w_long3): x = w_long1.longval y = w_long2.longval z = w_long3.longval @@ -108,7 +108,7 @@ raise OperationError(Error(e), "long multiplication") return W_LongObject(space, z) -def long_long_lshift(space, w_long1,w_long2): +def lshift__Long_Long(space, w_long1,w_long2): x = w_long1.longval y = w_long2.longval try: @@ -117,7 +117,7 @@ raise OperationError(OverflowError, "long multiplication") return W_LongObject(space, z) -def long_long_rshift(space, w_long1,w_long2): +def rshift__Long_Long(space, w_long1,w_long2): x = w_long1.longval y = w_long2.longval try: @@ -126,7 +126,7 @@ raise OperationError(OverflowError, "long multiplication") return W_LongObject(space, z) -def long_long_and(space, w_long1,w_long2): +def and__Long_Long(space, w_long1,w_long2): x = w_long1.longval y = w_long2.longval try: @@ -135,7 +135,7 @@ raise OperationError(OverflowError, "long multiplication") return W_LongObject(space, z) -def long_long_xor(space, w_long1,w_long2): +def xor__Long_Long(space, w_long1,w_long2): x = w_long1.longval y = w_long2.longval try: @@ -144,7 +144,7 @@ raise OperationError(OverflowError, "long multiplication") return W_LongObject(space, z) -def long_long_or(space, w_long1,w_long2): +def or__Long_Long(space, w_long1,w_long2): x = w_long1.longval y = w_long2.longval try: @@ -154,20 +154,4 @@ return W_LongObject(space, z) - -StdObjSpace.add.register(long_long_add, W_LongObject, W_LongObject) -StdObjSpace.sub.register(long_long_sub, W_LongObject, W_LongObject) -StdObjSpace.mul.register(long_long_mul, W_LongObject, W_LongObject) -StdObjSpace.div.register(long_long_div, W_LongObject, W_LongObject) -StdObjSpace.floordiv.register(long_long_floordiv, W_LongObject, W_LongObject) -StdObjSpace.truediv.register(long_long_truediv, W_LongObject, W_LongObject) -StdObjSpace.mod.register(long_long_mod, W_LongObject, W_LongObject) -StdObjSpace.divmod.register(long_long_divmod, W_LongObject, W_LongObject) -StdObjSpace.pow.register(long_long_pow, W_LongObject, W_LongObject) -StdObjSpace.pow.register(long_long_long_mod, W_LongObject, W_LongObject, W_LongObject) -StdObjSpace.lshift.register(long_long_lshift, W_LongObject, W_LongObject) -StdObjSpace.rshift.register(long_long_rshift, W_LongObject, W_LongObject) -StdObjSpace.and_.register(long_long_and, W_LongObject, W_LongObject) -StdObjSpace.xor.register(long_long_xor, W_LongObject, W_LongObject) -StdObjSpace.or_.register(long_long_or, W_LongObject, W_LongObject) - +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/noneobject.py Sat Jun 14 19:15:16 2003 @@ -9,19 +9,15 @@ registerimplementation(W_NoneObject) -def none_unwrap(space, w_none): +def unwrap__None(space, w_none): return None -StdObjSpace.unwrap.register(none_unwrap, W_NoneObject) - -def none_is_true(space, w_none): +def is_true__None(space, w_none): return False -StdObjSpace.is_true.register(none_is_true, W_NoneObject) - -def none_repr(space, w_none): +def repr__None(space, w_none): return space.wrap('None') -StdObjSpace.repr.register(none_repr, W_NoneObject) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objectobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objectobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/objectobject.py Sat Jun 14 19:15:16 2003 @@ -25,7 +25,7 @@ # give objects some default attributes and a default way to complain # about missing attributes -def object_getattr(space, w_obj, w_attr): +def getattr__Object_ANY(space, w_obj, w_attr): # XXX build a nicer error message along these lines: #w_type = space.type(w_obj) #w_typename = space.getattr(w_type, space.wrap('__name__')) @@ -65,13 +65,11 @@ raise OperationError(space.w_AttributeError, w_attr) -StdObjSpace.getattr.register(object_getattr, W_ObjectObject, W_ANY) - # set attributes, complaining about read-only ones -- # a more declarative way to define attributes would be welcome -def object_setattr(space, w_obj, w_attr, w_value): +def setattr__Object_ANY_ANY(space, w_obj, w_attr, w_value): if space.is_true(space.eq(w_attr, space.wrap('__class__'))): raise OperationError(space.w_AttributeError, space.wrap("read-only attribute")) @@ -90,10 +88,8 @@ raise OperationError(space.w_AttributeError, w_attr) -StdObjSpace.setattr.register(object_setattr, W_ObjectObject, W_ANY, W_ANY) - -def object_delattr(space, w_obj, w_attr): +def delattr__Object_ANY(space, w_obj, w_attr): if space.is_true(space.eq(w_attr, space.wrap('__class__'))): raise OperationError(space.w_AttributeError, space.wrap("read-only attribute")) @@ -112,12 +108,9 @@ raise OperationError(space.w_AttributeError, w_attr) -StdObjSpace.delattr.register(object_delattr, W_ObjectObject, W_ANY) - - # static types -def object_type(space, w_obj): +def type__Object(space, w_obj): if w_obj.statictype is None: # XXX remove me, temporary return space.wrap(space.unwrap(w_obj).__class__) @@ -125,28 +118,20 @@ w_type = space.get_typeinstance(w_obj.statictype) return w_type -StdObjSpace.type.register(object_type, W_ObjectObject) - - # repr() -def object_repr(space, w_obj): +def repr__Object(space, w_obj): return space.wrap('<%s object at %s>'%( space.type(w_obj).typename, space.unwrap(space.id(w_obj)))) -StdObjSpace.repr.register(object_repr, W_ObjectObject) - - # str() defaults to repr() and hash() defaults to id(). # these should really be defined in default.py, but in CPython they # are visible in the 'object' class. -def object_str(space, w_obj): +def str__Object(space, w_obj): return space.repr(w_obj) -StdObjSpace.str.register(object_str, W_ObjectObject) - -def object_hash(space, w_obj): +def hash__Object(space, w_obj): return space.id(w_obj) -StdObjSpace.hash.register(object_hash, W_ObjectObject) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sat Jun 14 19:15:16 2003 @@ -250,7 +250,6 @@ import stringobject return stringobject.W_StringObject(self, ''.join(chars)) - # special multimethods unwrap = MultiMethod('unwrap', 1, []) # returns an unwrapped object is_true = MultiMethod('nonzero', 1, []) # returns an unwrapped bool # XXX do something about __nonzero__ ! @@ -269,10 +268,51 @@ return self.newbool(w_one is w_two) + # add all regular multimethods to StdObjSpace for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: setattr(StdObjSpace, _name, MultiMethod(_symbol, _arity, _specialnames)) + +_name_mappings = { + 'and': 'and_', + 'or': 'or_', + 'not': 'not_', + } + +def register_all(module_dict, alt_ns=None): + """register implementations for multimethods. + + By default a (name, object) pair of the given module dictionary + is registered on the multimethod 'name' of StdObjSpace. + If the name doesn't exist then the alternative namespace is tried + for registration. + """ + + for name, obj in module_dict.items(): + if name.find('__')<1: + continue + funcname, sig = name.split('__') + l=[] + for i in sig.split('_'): + if i == 'ANY': + i = W_ANY + else: + i = module_dict.get('W_%s' % i) or module_dict.get('W_%sObject'%i) + l.append(i) + + if len(l) != obj.func_code.co_argcount-1: + raise ValueError, \ + "function name %s doesn't specify exactly %d arguments" % ( + repr(name), obj.func_code.co_argcount-1) + + funcname = _name_mappings.get(funcname, funcname) + + if hasattr(StdObjSpace, funcname): + getattr(StdObjSpace, funcname).register(obj, *l) + else: + getattr(alt_ns, funcname).register(obj, *l) + # import the common base W_ObjectObject as well as # default implementations of some multimethods for all objects # that don't explicitely override them or that raise FailedToImplement Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Sat Jun 14 19:15:16 2003 @@ -26,7 +26,7 @@ registerimplementation(W_SliceObject) -def getattr_slice_any(space, w_slice, w_attr): +def getattr__Slice_ANY(space, w_slice, w_attr): if space.is_true(space.eq(w_attr, space.wrap('start'))): if w_slice.w_start is None: return space.w_None @@ -48,4 +48,4 @@ raise FailedToImplement(space.w_AttributeError) -StdObjSpace.getattr.register(getattr_slice_any, W_SliceObject, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sat Jun 14 19:15:16 2003 @@ -6,7 +6,6 @@ from instmethobject import W_InstMethObject from noneobject import W_NoneObject from tupleobject import W_TupleObject -from pypy.interpreter.extmodule import make_builtin_func from rarray import CharArrayFromStr, CharArraySize @@ -27,7 +26,6 @@ registerimplementation(W_StringObject) - def _isspace(ch): return ord(ch) in (9, 10, 11, 12, 13, 32) @@ -68,28 +66,28 @@ return space.w_False return space.w_True -def str_isspace(space, w_self): +def str_isspace__String(space, w_self): return _is_generic(w_self, _isspace) -def str_isdigit(space, w_self): +def str_isdigit__String(space, w_self): return _is_generic(w_self, _isdigit) -def str_isalpha(space, w_self): +def str_isalpha__String(space, w_self): return _is_generic(w_self, _isalpha) -def str_isalnum(space, w_self): +def str_isalnum__String(space, w_self): return _is_generic(w_self, _isalnum) -def str_isupper(space, w_self): +def str_isupper__String(space, w_self): return _is_generic(w_self, _isupper) -def str_islower(space, w_self): +def str_islower__String(space, w_self): return _is_generic(w_self, _islower) def str_istitle(space, w_self): pass -def str_splitByWhitespace(space, w_self, w_none): +def str_split__String_None(space, w_self, w_none): res = [] inword = 0 value = w_self._value.value() @@ -107,7 +105,7 @@ res[i] = W_StringObject(space, res[i]) return W_ListObject(space, res) -def str_split(space, w_self, w_by): +def str_split__String_String(space, w_self, w_by): res = [] start = 0 value = w_self._value.value() @@ -123,23 +121,8 @@ res[i] = W_StringObject(w_self.space, res[i]) return W_ListObject(w_self.space, res) -# XXX temporary hack -W_StringType.str_split.register(str_split, W_StringObject, W_StringObject) -W_StringType.str_split.register(str_splitByWhitespace, - W_StringObject, W_NoneObject) -#We should erase the W_NoneObject, but register takes always -#the same number of parameters. So you have to call split with -#None as parameter instead of calling it without any parameter - -W_StringType.str_isspace.register(str_isspace, W_StringObject) -W_StringType.str_isdigit.register(str_isdigit, W_StringObject) -W_StringType.str_isalpha.register(str_isalpha, W_StringObject) -W_StringType.str_isupper.register(str_isupper, W_StringObject) -W_StringType.str_islower.register(str_islower, W_StringObject) -W_StringType.str_istitle.register(str_istitle, W_StringObject) -W_StringType.str_isalnum.register(str_isalnum, W_StringObject) -def str_join(space, w_self, w_list): +def str_join__String_ANY(space, w_self, w_list): list = space.unpackiterable(w_list) if list: firstelem = 1 @@ -167,39 +150,28 @@ else: return W_StringObject(space, "") -W_StringType.str_join.register(str_join, W_StringObject, W_ANY) -def str_ljust(space, w_str, w_arg): +def str_ljust__String_ANY(space, w_str, w_arg): # XXX look away for three lines, please :-) -- mwh u = space.unwrap w = space.wrap return w(u(w_str).ljust(u(w_arg))) -W_StringType.str_ljust.register(str_ljust, W_StringObject, W_ANY) - -def str_rjust(space, w_str, w_arg): +def str_rjust__String_ANY(space, w_str, w_arg): # XXX and another three -- mwh u = space.unwrap w = space.wrap return w(u(w_str).rjust(u(w_arg))) -W_StringType.str_rjust.register(str_rjust, W_StringObject, W_ANY) - -def str_unwrap(space, w_str): +def unwrap__String(space, w_str): return w_str._value.value() -StdObjSpace.unwrap.register(str_unwrap, W_StringObject) - -def str_is_true(space, w_str): +def is_true__String(space, w_str): return w_str._value.len != 0 -StdObjSpace.is_true.register(str_is_true, W_StringObject) - -def str_hash(space, w_str): +def hash__String(space, w_str): return W_IntObject(space, w_str._value.hash()) -StdObjSpace.hash.register(str_hash, W_StringObject) - EQ = 1 LE = 2 @@ -264,37 +236,25 @@ else: raise NotImplemented -def str_str_lt(space, w_str1, w_str2): +def lt__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, LT) -StdObjSpace.lt.register(str_str_lt, W_StringObject, W_StringObject) - -def str_str_le(space, w_str1, w_str2): +def le__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, LE) -StdObjSpace.le.register(str_str_le, W_StringObject, W_StringObject) - -def str_str_eq(space, w_str1, w_str2): +def eq__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, EQ) -StdObjSpace.eq.register(str_str_eq, W_StringObject, W_StringObject) - -def str_str_ne(space, w_str1, w_str2): +def ne__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, NE) -StdObjSpace.ne.register(str_str_ne, W_StringObject, W_StringObject) -def str_str_gt(space, w_str1, w_str2): +def gt__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, GT) -StdObjSpace.gt.register(str_str_gt, W_StringObject, W_StringObject) - -def str_str_ge(space, w_str1, w_str2): +def ge__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, GE) -StdObjSpace.ge.register(str_str_ge, W_StringObject, W_StringObject) - - -def getitem_str_int(space, w_str, w_int): +def getitem__String_Int(space, w_str, w_int): ival = w_int.intval slen = w_str._value.len if ival < 0: @@ -305,10 +265,7 @@ raise OperationError(space.w_IndexError, exc) return W_StringObject(space, w_str._value.charat(ival)) -StdObjSpace.getitem.register(getitem_str_int, - W_StringObject, W_IntObject) - -def getitem_str_slice(space, w_str, w_slice): +def getitem__String_Slice(space, w_str, w_slice): return space.gethelper(applicationfile).call( "getitem_string_slice", [w_str, w_slice]) w = space.wrap @@ -325,53 +282,39 @@ w_empty = space.newstring([]) return str_join(space, w_empty, w_r) -StdObjSpace.getitem.register(getitem_str_slice, - W_StringObject, W_SliceObject) - -def add_str_str(space, w_left, w_right): +def add__String_String(space, w_left, w_right): buf = CharArraySize(w_left._value.len + w_right._value.len) buf.setsubstring(0, w_left._value.value()) buf.setsubstring(w_left._value.len, w_right._value.value()) return W_StringObject(space, buf.value()) -StdObjSpace.add.register(add_str_str, W_StringObject, W_StringObject) - -def mod_str_ANY(space, w_left, w_right): - notImplemented - def mod_str_tuple(space, w_format, w_args): notImplemented -def len_str(space, w_str): +def len__String(space, w_str): return space.wrap(w_str._value.len) -StdObjSpace.len.register(len_str, W_StringObject) - -def str_str(space, w_str): +def str__String(space, w_str): return w_str -StdObjSpace.str.register(str_str, W_StringObject) - -def str_repr(space, w_str): +def repr__String(space, w_str): # XXX this is bogus -- mwh return space.wrap(repr(space.unwrap(w_str))) a = space.add q = space.wrap("'") return a(a(q, w_str), q) -StdObjSpace.repr.register(str_repr, W_StringObject) - -def str_ord(space, w_str): +def ord__String(space, w_str): return space.wrap(ord(space.unwrap(w_str))) -StdObjSpace.ord.register(str_ord, W_StringObject) +def mod__String_ANY(space, w_str, w_item): + return mod_str_tuple(space, w_str, space.newtuple([w_item])) -def str_mod_any(space, w_str, w_item): - return str_mod_tuple(space, w_str, space.newtuple([w_item])) +def mod__String_Tuple(space, w_str, w_tuple): + return space.wrap(space.unwrap(w_str)%space.unwrap(w_tuple)) -StdObjSpace.mod.register(str_mod_any, W_StringObject, W_ANY) -def str_mod_tuple(space, w_str, w_tuple): - return space.wrap(space.unwrap(w_str)%space.unwrap(w_tuple)) +# register all methods +register_all(vars(), W_StringType) + -StdObjSpace.mod.register(str_mod_tuple, W_StringObject, W_TupleObject) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sat Jun 14 19:15:16 2003 @@ -1,4 +1,4 @@ -from pypy.objspace.std.objspace import MultiMethod, StdObjSpace, W_ANY +from pypy.objspace.std.objspace import MultiMethod, StdObjSpace, W_ANY, register_all from typeobject import W_TypeObject @@ -20,7 +20,7 @@ str_rjust = MultiMethod('rjust', 2) # XXX we'll worry about the __new__/__init__ distinction later -def stringtype_new(space, w_stringtype, w_args, w_kwds): +def new__StringType_ANY_ANY(space, w_stringtype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) @@ -33,4 +33,4 @@ raise OperationError(space.w_TypeError, space.wrap("str() takes at most 1 argument")) -StdObjSpace.new.register(stringtype_new, W_StringType, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Sat Jun 14 19:15:16 2003 @@ -20,24 +20,18 @@ registerimplementation(W_TupleObject) -def tuple_unwrap(space, w_tuple): +def unwrap__Tuple(space, w_tuple): items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] return tuple(items) -StdObjSpace.unwrap.register(tuple_unwrap, W_TupleObject) - -def tuple_is_true(space, w_tuple): +def is_true__Tuple(space, w_tuple): return not not w_tuple.wrappeditems -StdObjSpace.is_true.register(tuple_is_true, W_TupleObject) - -def tuple_len(space, w_tuple): +def len__Tuple(space, w_tuple): result = len(w_tuple.wrappeditems) return W_IntObject(space, result) -StdObjSpace.len.register(tuple_len, W_TupleObject) - -def getitem_tuple_int(space, w_tuple, w_index): +def getitem__Tuple_Int(space, w_tuple, w_index): items = w_tuple.wrappeditems try: w_item = items[w_index.intval] @@ -46,9 +40,7 @@ space.wrap("tuple index out of range")) return w_item -StdObjSpace.getitem.register(getitem_tuple_int, W_TupleObject, W_IntObject) - -def getitem_tuple_slice(space, w_tuple, w_slice): +def getitem__Tuple_Slice(space, w_tuple, w_slice): items = w_tuple.wrappeditems w_length = space.wrap(len(items)) w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length) @@ -62,34 +54,25 @@ start += step return W_TupleObject(space, subitems) -StdObjSpace.getitem.register(getitem_tuple_slice, W_TupleObject, W_SliceObject) - -def tuple_iter(space, w_tuple): +def iter__Tuple(space, w_tuple): import iterobject return iterobject.W_SeqIterObject(space, w_tuple) -StdObjSpace.iter.register(tuple_iter, W_TupleObject) - -def tuple_add(space, w_tuple1, w_tuple2): +def add__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems return W_TupleObject(space, items1 + items2) -StdObjSpace.add.register(tuple_add, W_TupleObject, W_TupleObject) - -def tuple_int_mul(space, w_tuple, w_int): +def mul__Tuple_Int(space, w_tuple, w_int): items = w_tuple.wrappeditems times = w_int.intval return W_TupleObject(space, items * times) -StdObjSpace.mul.register(tuple_int_mul, W_TupleObject, W_IntObject) - -def int_tuple_mul(space, w_int, w_tuple): - return tuple_int_mul(space, w_tuple, w_int) -StdObjSpace.mul.register(int_tuple_mul, W_IntObject, W_TupleObject) +def mul__Int_Tuple(space, w_int, w_tuple): + return mul__Tuple_Int(space, w_tuple, w_int) -def tuple_eq(space, w_tuple1, w_tuple2): +def eq__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems if len(items1) != len(items2): @@ -99,14 +82,12 @@ return space.w_False return space.w_True -StdObjSpace.eq.register(tuple_eq, W_TupleObject, W_TupleObject) - def _min(a, b): if a < b: return a return b -def tuple_lt(space, w_tuple1, w_tuple2): +def lt__Tuple_Tuple(space, w_tuple1, w_tuple2): # XXX tuple_le, tuple_gt, tuple_ge, tuple_ne must also be explicitely done items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems @@ -118,10 +99,9 @@ # No more items to compare -- compare sizes return space.newbool(len(items1) < len(items2)) -StdObjSpace.lt.register(tuple_lt, W_TupleObject, W_TupleObject) - -def tuple_repr(space, w_tuple): +def repr__Tuple(space, w_tuple): # XXX slimy! --mwh return space.wrap(repr(space.unwrap(w_tuple))) -StdObjSpace.repr.register(tuple_repr, W_TupleObject) + +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sat Jun 14 19:15:16 2003 @@ -121,8 +121,8 @@ # self.w_type.typename, self.bound_position) # slice the multimethod and cache the result sliced = multimethod.slicetable(self.bound_position, self.w_type) - if sliced.is_empty(): - print "the slice is empty" + #if sliced.is_empty(): + # print "the slice is empty" self.slicedmultimethod = sliced.__get__(self.w_type.space, None) multimethod.cache_dependency(self) return self.slicedmultimethod @@ -154,27 +154,23 @@ return w_result -def type_call(space, w_type, w_args, w_kwds): +def call__Type_ANY_ANY(space, w_type, w_args, w_kwds): w_newobject = space.new(w_type, w_args, w_kwds) # XXX call __init__() later return w_newobject -StdObjSpace.call.register(type_call, W_TypeObject, W_ANY, W_ANY) - -def type_issubtype(space, w_type1, w_type2): +def issubtype__Type_Type(space, w_type1, w_type2): return space.newbool(w_type2 in w_type1.getmro()) -StdObjSpace.issubtype.register(type_issubtype, W_TypeObject, W_TypeObject) - -def type_repr(space, w_obj): +def repr__Type(space, w_obj): return space.wrap("" % w_obj.typename) -StdObjSpace.repr.register(type_repr, W_TypeObject) - -def type_getattr(space, w_type, w_attr): +def getattr__Type_ANY(space, w_type, w_attr): # XXX mwh doubts this is the Right Way to do this... if space.is_true(space.eq(w_attr, space.wrap('__name__'))): return w_type.w_tpname raise FailedToImplement -StdObjSpace.getattr.register(type_getattr, W_TypeObject, W_ANY) + +register_all(vars()) + Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Sat Jun 14 19:15:16 2003 @@ -71,19 +71,14 @@ return mostspecialized -def user_type(space, w_userobj): +def type__User(space, w_userobj): return w_userobj.w_uo_type -StdObjSpace.type.register(user_type, W_UserObject) - -def user_getdict(space, w_userobj): +def getdict__User(space, w_userobj): # XXX check getdict() of the base built-in implementation return w_userobj.w_uo_dict -StdObjSpace.getdict.register(user_getdict, W_UserObject) - - # We register here all multimethods with at least one W_UserObject. # No multimethod must be explicitely registered on W_UserObject except # here, unless you want to completely override a behavior for user-defined @@ -126,3 +121,6 @@ signature = [W_ANY] * multimethod.arity signature[i] = W_UserObject multimethod.register(user_operation, *signature) + + +register_all(vars()) From hpk at codespeak.net Sat Jun 14 19:38:56 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 14 Jun 2003 19:38:56 +0200 (MEST) Subject: [pypy-svn] rev 810 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030614173856.0FBF35A415@thoth.codespeak.net> Author: hpk Date: Sat Jun 14 19:38:55 2003 New Revision: 810 Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Log: fixed test_raise test checking for wrong error message Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Sat Jun 14 19:38:55 2003 @@ -101,7 +101,7 @@ def f(): raise 1 ''', 'f', []) - self.assertEquals(x, '<<>>') + self.assertEquals(x, '<<>>') def test_except2(self): x = self.codetest(''' From arigo at codespeak.net Sun Jun 15 20:51:24 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 15 Jun 2003 20:51:24 +0200 (MEST) Subject: [pypy-svn] rev 812 - in pypy/trunk/src/pypy: interpreter objspace/std objspace/std/test Message-ID: <20030615185124.773945A41A@thoth.codespeak.net> Author: arigo Date: Sun Jun 15 20:51:22 2003 New Revision: 812 Added: pypy/trunk/src/pypy/interpreter/threadlocals.py pypy/trunk/src/pypy/objspace/std/mm_notes.txt Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/interpreter/executioncontext.py pypy/trunk/src/pypy/objspace/std/boolobject.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/floatobject.py pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/objectobject.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/userobject.py Log: a major rewrite of the user-defined types and the delegation part of multi-methods. Now I'm starting to feel better about it. See comments in objspace.std.mm_notes.txt. --This line, and those below, will be ignored-- M /home/arigo/python/pypy/pypy/trunk/src/pypy/interpreter/test/test_interpreter.py A /home/arigo/python/pypy/pypy/trunk/src/pypy/interpreter/threadlocals.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/interpreter/executioncontext.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/interpreter/baseobjspace.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/objectobject.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/userobject.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/default.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/multimethod.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/floatobject.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/typeobject.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/objecttype.py A /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/mm_notes.txt M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/boolobject.py M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/objspace.py Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Sun Jun 15 20:51:22 2003 @@ -1,5 +1,5 @@ from executioncontext import ExecutionContext, OperationError, NoValue -import pyframe +import pyframe, threadlocals import pypy.module.builtin __all__ = ['ObjSpace', 'OperationError', 'NoValue', 'PyPyError'] @@ -48,15 +48,10 @@ def getexecutioncontext(self): "Return what we consider to be the active execution context." - import sys - f = sys._getframe() # !!hack!! - while f: - if f.f_locals.has_key('__executioncontext__'): - result = f.f_locals['__executioncontext__'] - if result.space is self: - return result - f = f.f_back - return ExecutionContext(self) + ec = threadlocals.getlocals().executioncontext + if ec is None: + ec = ExecutionContext(self) + return ec def gethelper(self, applicationfile): try: Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sun Jun 15 20:51:22 2003 @@ -1,4 +1,5 @@ import sys +import threadlocals class ExecutionContext: @@ -7,11 +8,14 @@ self.framestack = Stack() def eval_frame(self, frame): - __executioncontext__ = self + locals = threadlocals.getlocals() self.framestack.push(frame) + previous_ec = locals.executioncontext + locals.executioncontext = self try: result = frame.eval(self) finally: + locals.executioncontext = previous_ec self.framestack.pop() return result Added: pypy/trunk/src/pypy/interpreter/threadlocals.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/interpreter/threadlocals.py Sun Jun 15 20:51:22 2003 @@ -0,0 +1,13 @@ +# Thread-local storage. + +# XXX no thread support yet, so this is easy :-) + +class ThreadLocals: + pass + +locals = ThreadLocals() +locals.executioncontext = None + + +def getlocals(): + return locals Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Sun Jun 15 20:51:22 2003 @@ -17,10 +17,9 @@ # bool-to-int delegation requires translating the .boolvar attribute # to an .intval one -def bool_to_int(space, w_bool): +def delegate__Bool(space, w_bool): return intobject.W_IntObject(space, int(w_bool.boolval)) - -W_BoolObject.delegate_once[intobject.W_IntObject] = bool_to_int +delegate__Bool.priority = PRIORITY_PARENT_TYPE def is_true__Bool(space, w_bool): Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Sun Jun 15 20:51:22 2003 @@ -3,8 +3,27 @@ from pypy.objspace.std.objspace import * -# These are operations that must fall back to some default behavior that -# should not appear in the explicit object.__xxx__ methods. +# The default delegation mecanism is to allow any W_XxxObject class +# to be regarded as an instance of any of its parent classes. + +def class_to_parent_classes(space, w_obj): + converted = [] + W_Cls = w_obj.__class__ + while W_Cls is not W_Object: + assert len(W_Cls.__bases__) == 1, ( + "multimethod call with non wrapped argument: %r" % w_obj) + W_Cls, = W_Cls.__bases__ + converted.append((W_Cls, w_obj)) + return converted + +class_to_parent_classes.priority = PRIORITY_PARENT_IMPL +StdObjSpace.delegate.register(class_to_parent_classes, Ellipsis) +# 'Ellipsis' should not be used in other calls to register() + + +# These are operations that must fall back to some default behavior, +# but that should not appear explicitly at application-level. +# There is no default object.__xxx__() method for these. # 'eq' falls back to 'is' Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/floatobject.py Sun Jun 15 20:51:22 2003 @@ -8,7 +8,7 @@ ############################################################## import math -import intobject +from intobject import W_IntObject applicationfile = StdObjSpace.AppFile(__name__) @@ -26,9 +26,9 @@ registerimplementation(W_FloatObject) # int-to-float delegation -def int_to_float(space, w_intobj): +def delegate__Int(space, w_intobj): return W_FloatObject(space, float(w_intobj.intval)) -intobject.W_IntObject.delegate_once[W_FloatObject] = int_to_float +delegate__Int.priority = PRIORITY_CHANGE_TYPE def float_float(space,w_value): Added: pypy/trunk/src/pypy/objspace/std/mm_notes.txt ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/mm_notes.txt Sun Jun 15 20:51:22 2003 @@ -0,0 +1,145 @@ + + +Notes on Multimethods +********************* + + +Interpreter-level classes correspond to implementations of application-level +types. Several implementations can be given for the same type (e.g. several +ways to code strings or dictionaries), and conversely the same implementation +can cover several types (e.g. all instances of user-defined types currently +share the same implementation). + +The hierarchy among the classes used for the implementations is convenient +for implementation purposes. It is not related to any application-level type +hierarchy. + + +Dispatch +-------- + +Multimethods dispatch by looking in a set of registered functions. Each +registered function has a signature, which defines which object implementation +classes are accepted at the corresponding argument position. + +The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' +later). As it accepts anything, it is the only way to guarantee that the +registered function will be called with exactly the same object as was +passed originally. ATTENTION: in all other cases the argument received by +the function may have been converted in some way. It must thus not be +considered to be 'id'entical to the original argument. For example it should +not be stored in a data structure, nor be queried for type, nor be used for +another multimethod dispatch -- the only thing you should do is read and +write its internal data. + +For example, 'getattr(obj, attr)' is implemented with a W_StringObject second +argument when all it needs is just the name of the attr, and with a W_ANY +when the 'attr' object could be used as a key in obj.__dict__. + + +Delegation +---------- + +Delegation is a transparent convertion mechanism between object +implementations. The convertion can give a result of a different type +(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). +There is a global table of delegators. We should not rely on the delegators +to be tried in any particlar order, or at all (e.g. the int -> float delegator +could be ignored when we know that no registered function will accept a float +anyway). + +Delegation is also used to emulate inheritance between built-in types +(e.g. bool -> int). This is done by delegation because there is no reason +that a particular implementation of a sub-type can be trivially typecast +to some other particular implementation of the parent type; the process might +require some work. + + +Types +----- + +Types are implemented by the class W_TypeObject. This is where inheritance +and the Method Resolution Order are defined, and where attribute look-ups +are done. + +Instances of user-defined types are implementated as W_UserObjects. +A user-defined type can inherit from built-in types (maybe more than one, +although this is incompatible with CPython). The W_UserObject delegator +converts the object into any of these "parent objects" if needed. This is +how user-defined types appear to inherit all built-in operator +implementations. + +Delegators should be able to invoke user code; this would let us +implement special methods like __int__() by calling them within a +W_UserObject -> int delegator. + + +Specifics of multimethods +------------------------- + +Multimethods dispatch more-specific-first, left-to-right (i.e. if there is +an exact match for the first argument it will always be tried first). + +Delegators are automatically chained (i.e. A -> B and B -> C would be +combined to allow for A -> C delegation). + +Delegators do not publish the class of the converted object in advance, +so that the W_UserObject delegator can potentially produce any other +built-in implementation. This means chaining and chain loop detection cannot +be done statically (at least without help from an analysis tool like the +translator-to-C). To break loops, we can assume (unless a particular need +arises) that delegators are looping when they return an object of an +already-seen class. + + +Registration +------------ + +The register() method of multimethods adds a function to its database of +functions, with the given signature. A function that raises +FailedToImplement causes the next match to be tried. + +'delegate' is the special unary multimethod that should try to convert +its argument to something else. For greater control, it can also return +a list of 2-tuples (class, object), or an empty list for failure to convert +the argument to anything. All delegators will potentially be tried, and +recursively on each other's results to do chaining. + +A priority ordering between delegators is used. See objspace.PRIORITY_*. + + +Translation +----------- + +The code in multimethod.py is not supposed to be read by the +translator-to-C. Special optimized code will be generated instead +(typically some kind of precomputed dispatch tables). + +Delegation is special-cased too. Most delegators will be found +to return an object of a statically known class, which means that +most of the chaining and loop detection can be done in advance. + + +Multimethod slicing +------------------- + +Multimethods are visible to user code as (bound or unbound) methods +defined for the corresponding types. (At some point built-in functions +like len() and the operator.xxx() should really directly map to the +multimethods themselves, too.) + +To build a method from a multimethod (e.g. as in 'l.append' or +'int.__add__'), the result is actually a "slice" of the whole +multimethod, i.e. a sub-multimethod in which the registration table has +been trimmed down. (Delegation mechanisms are not restricted for sliced +multimethods.) + +Say that C is the class the new method is attached to (in the above +examples, respectively, C=type(l) and C=int). The restriction is +based on the registered class of the first argument ('self' for the +new method) in the signature. If this class corresponds to a fixed +type (as advertized by 'statictype'), and this fixed type is C or a +superclass of C, then we keep it. + +Some multimethods can also be sliced along their second argument, +e.g. for __radd__(). Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Sun Jun 15 20:51:22 2003 @@ -5,105 +5,189 @@ "Signals the dispatcher to try harder." -class MultiMethod(object): +# This file defines three major classes: +# +# MultiMethod is the class you instanciate explicitely. +# It is essentially just a collection of registered functions. +# If xxx is a MultiMethod, StdObjSpace.xxx is xxx again, +# and space.xxx is a BoundMultiMethod. +# +# BoundMultiMethod is a MultiMethod or UnboundMultiMethod which +# has been found to a specific object space. It is obtained by +# 'space.xxx' or explicitely by calling 'xxx.get(space)'. +# +# UnboundMultiMethod is a MultiMethod on which one argument +# (typically the first one) has been restricted to be of some +# statically known type. It is obtained by the syntax +# W_XxxType.yyy, where W_XxxType is the static type class, +# or explicitely by calling 'xxx.slice(typeclass, arg_position)'. +# Its dispatch table is always a subset of the dispatch table of +# the original MultiMethod; a new function registered in either +# one may be automatically registered in the other one to keep +# them in sync. + + +class AbstractMultiMethod(object): + """Abstract base class for MultiMethod and UnboundMultiMethod + i.e. the classes that are not bound to a specific space instance.""" - ASSERT_BASE_TYPE = None + class BASE_TYPE_OBJECT: pass - def __init__(self, operatorsymbol, arity, specialnames=None, defaults=()): - "MultiMethod dispatching on the first 'arity' arguments." + def __init__(self, operatorsymbol, arity): self.arity = arity self.operatorsymbol = operatorsymbol self.dispatch_table = {} - if specialnames is None: - specialnames = [operatorsymbol] - self.specialnames = specialnames # list like ['__xxx__', '__rxxx__'] - self.defaults = defaults - self.cache_dependencies = {} self.cache_table = {} def register(self, function, *types): # W_ANY can be used as a placeholder to dispatch on any value. - if types in self.dispatch_table: - raise error, "we already got an implementation for %r %r" % ( - self.operatorsymbol, types) - self.dispatch_table[types] = function - # clear caches - self.cache_table.clear() - for cache in self.cache_dependencies: - cache.cleardependency() - self.cache_dependencies.clear() - - def __get__(self, space, cls): - if space is None: - return self # <-------------------------- Hack - return BoundMultiMethod(space, self) - - def cache_dependency(self, cache): - self.cache_dependencies[cache] = 1 - - def buildchoices(self, types): - """Build a list of all possible combinations of delegated types, - sorted by cost.""" + functions = self.dispatch_table.setdefault(types, []) + if function not in functions: + functions.append(function) + self.cache_table.clear() + + def buildchoices(self, allowedtypes): + """Build a list of all possible implementations we can dispatch to, + sorted best-first, ignoring delegation.""" + # 'types' is a tuple of tuples of classes, one tuple of classes per + # argument. (Delegation needs to call buildchoice() with than one + # class for a single argument.) try: - result = self.cache_table[types] # try from the cache first + result = self.cache_table[allowedtypes] # try from the cache first except KeyError: - result = self.cache_table[types] = [] - self.internal_buildchoices(types, (), (), result) - # the result is sorted by costs by construction. - # it is a list of (delegator, function) pairs. + result = self.cache_table[allowedtypes] = [] + self.internal_buildchoices(allowedtypes, (), result) + self.postprocessresult(allowedtypes, result) + #print self.operatorsymbol, allowedtypes, result + # the result is a list a tuples (function, signature). return result - def internal_buildchoices(self, initialtypes, currenttypes, - currentdelegators, result): + def postprocessresult(self, allowedtypes, result): + pass + + def internal_buildchoices(self, initialtypes, currenttypes, result): if len(currenttypes) == self.arity: - try: - function = self.dispatch_table[currenttypes] - except KeyError: - pass - else: - newentry = (currentdelegators, function) - if newentry not in result: # don't add duplicates - result.append(newentry) + for func in self.dispatch_table.get(currenttypes, []): + if func not in result: # ignore duplicates + result.append((currenttypes, func)) else: - nexttype = initialtypes[len(currenttypes)] - delegators = {} - while 1: + classtuple = initialtypes[len(currenttypes)] + for i, nexttype in zip(range(len(classtuple)), classtuple): self.internal_buildchoices(initialtypes, currenttypes + (nexttype,), - currentdelegators + (None,), result) - #assert "delegate_once" in nexttype.__dict__, ( - # "you must call registerimplementation() to initialize %r" % - # nexttype) - if "delegate_once" in nexttype.__dict__: - for key, value in nexttype.__dict__["delegate_once"].items(): - if key not in delegators: - delegators[key] = value - # before general delegation, try superclasses - if not nexttype.__bases__: - # debugging assertion - if self.ASSERT_BASE_TYPE: - assert nexttype is self.ASSERT_BASE_TYPE, ( - "calling a multimethod with an argument " - "which is not wrapped") - break - nexttype, = nexttype.__bases__ # no multiple inheritance pleeease - for othertype, delegator in delegators.items(): - self.internal_buildchoices(initialtypes, - currenttypes + (othertype,), - currentdelegators + (delegator,), result) - def slicetable(self, position, slicetype): - m = MultiMethod(self.operatorsymbol, self.arity, self.specialnames) - for key, value in self.dispatch_table.iteritems(): - if slicetype.acceptclass(key[position]): - m.dispatch_table[key] = value - return m - def is_empty(self): return not self.dispatch_table +class MultiMethod(AbstractMultiMethod): + + def __init__(self, operatorsymbol, arity, specialnames=None, defaults=()): + "MultiMethod dispatching on the first 'arity' arguments." + AbstractMultiMethod.__init__(self, operatorsymbol, arity) + if arity < 1: + raise ValueError, "multimethods cannot dispatch on nothing" + if specialnames is None: + specialnames = [operatorsymbol] + self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__'] + self.defaults = defaults + self.unbound_versions = {} + + def __get__(self, space, cls=object): + if issubclass(cls, self.BASE_TYPE_OBJECT): + return self.slice(cls).get(space) + elif space is None: + return self # hack for "StdObjSpace.xyz" returning xyz + else: + return BoundMultiMethod(space, self) + + get = __get__ + + def slice(self, typeclass, bound_position=0): + try: + return self.unbound_versions[typeclass, bound_position] + except KeyError: + m = UnboundMultiMethod(self, typeclass, bound_position) + self.unbound_versions[typeclass, bound_position] = m + return m + + def register(self, function, *types): + AbstractMultiMethod.register(self, function, *types) + # register the function is unbound versions that match + for m in self.unbound_versions.values(): + if m.match(types): + AbstractMultiMethod.register(m, function, *types) + + +class DelegateMultiMethod(MultiMethod): + + def __init__(self): + MultiMethod.__init__(self, 'delegate', 1, []) + + def postprocessresult(self, allowedtypes, result): + # add the Ellipsis catch-all delegator(s) + for function in self.dispatch_table[Ellipsis,]: + for t in allowedtypes[0]: + result.append(((t,), function)) + + # sort the results in priority order, and insert None marks + # between jumps in the priority values. Higher priority values + # first. + by_priority = {} # classify delegators by priority + for signature, function in result: + assert hasattr(function, 'priority'), ( + "delegator function must have a priority") + sublist = by_priority.setdefault(function.priority, []) + sublist.append((signature, function)) + delegators = by_priority.items() + delegators.sort() + delegators.reverse() + del result[:] + for priority, sublist in delegators: + if result: + result.append(((None,), None)) + result += sublist + + +class UnboundMultiMethod(AbstractMultiMethod): + + def __init__(self, basemultimethod, typeclass, bound_position=0): + AbstractMultiMethod.__init__(self, + basemultimethod.operatorsymbol, + basemultimethod.arity) + self.basemultimethod = basemultimethod + self.typeclass = typeclass + self.bound_position = bound_position + # get all the already-registered matching functions from parent + for types, functions in basemultimethod.dispatch_table.iteritems(): + if self.match(types): + self.dispatch_table[types] = functions + #print basemultimethod.operatorsymbol, typeclass, self.dispatch_table + + def register(self, function, *types): + AbstractMultiMethod.register(self, function, *types) + # propagate the function registeration to the base multimethod + # and possibly other UnboundMultiMethods + self.basemultimethod.register(function, *types) + + def match(self, types): + # check if the 'types' signature statically corresponds to the + # restriction of the present UnboundMultiMethod. + # Only accept an exact match; having merely subclass should + # be taken care of by the general look-up rules. + t = types[self.bound_position].statictype + return t is self.typeclass + + def __get__(self, space, cls=None): + if space is None: + return self + else: + return BoundMultiMethod(space, self) + + get = __get__ + + class BoundMultiMethod: def __init__(self, space, multimethod): @@ -114,14 +198,14 @@ if len(args) < self.multimethod.arity: raise TypeError, ("multimethod needs at least %d arguments" % self.multimethod.arity) - dispatchargs = args[:self.multimethod.arity] - initialtypes = tuple([a.__class__ for a in dispatchargs]) try: - return self.perform_call(args, initialtypes) + return self.perform_call(args) except FailedToImplement, e: if e.args: raise OperationError(*e.args) else: + initialtypes = [a.__class__ + for a in args[:self.multimethod.arity]] if len(initialtypes) <= 1: plural = "" else: @@ -133,26 +217,83 @@ w_value = self.space.wrap(message) raise OperationError(self.space.w_TypeError, w_value) - def perform_call(self, args, initialtypes, prepend_space_argument=True): - extraargs = args[self.multimethod.arity:] - choicelist = self.multimethod.buildchoices(initialtypes) + def perform_call(self, args): + arity = self.multimethod.arity + extraargs = args[arity:] + + # look for an exact match first firstfailure = None - for delegators, function in choicelist: - newargs = [] - for delegator, arg in zip(delegators, args): - if delegator is not None: - arg = delegator(self.space, arg) - newargs.append(arg) - newargs = tuple(newargs) + extraargs - # XXX 'prepend_space_argument' should now always be True anyway - if prepend_space_argument: - newargs = (self.space,) + newargs + types = tuple([(a.__class__,) for a in args]) + choicelist = self.multimethod.buildchoices(types) + for signature, function in choicelist: try: - return function(*newargs) + return function(self.space, *args) except FailedToImplement, e: # we got FailedToImplement, record the first such error - if firstfailure is None: - firstfailure = e + firstfailure = firstfailure or e + + seen_functions = {} + for signature, function in choicelist: + seen_functions[function] = 1 + + # proceed by expanding the last argument by delegation, step by step + # until no longer possible, and then the previous argument, and so on. + expanded_args = () + expanded_types = () + delegate = self.space.delegate.multimethod + + for argi in range(arity-1, -1, -1): + curtypes = types[argi] # growing tuple of types we can delegate to + curobjs = {curtypes[0]: args[argi]} # maps them to actual objects + args = args[:argi] # initial segments of arguments before this one + types = types[:argi] # same with types (no deleg tried on them yet) + while 1: + choicelist = delegate.buildchoices((curtypes,)) + # the list is sorted by priority + progress = False + for (t,), function in choicelist: + if function is None: + # this marks a decrease in the priority. + # Don't try delegators with lower priority if + # we have already progressed. + if progress: + break + else: + converted = function(self.space, curobjs[t]) + if not isinstance(converted, list): + converted = [(converted.__class__, converted)] + for t, a in converted: + if t not in curobjs: + curtypes += (t,) + curobjs[t] = a + progress = True + else: + if not progress: + break # no progress, and delegators list exhausted + + # progress: try again to dispatch with this new set of types + choicelist = self.multimethod.buildchoices( + types + (curtypes,) + expanded_types) + for signature, function in choicelist: + if function not in seen_functions: + seen_functions[function] = 1 + # collect arguments: arguments after position i... + tail = [expanded_args[j][signature[j]] + for j in range(argi+1-arity, 0)] # nb. j<0 + # argments before and up to position i... + newargs= args + (curobjs[signature[argi]],) + tuple(tail) + try: + return function(self.space, *newargs+extraargs) + except FailedToImplement, e: + # record the first FailedToImplement + firstfailure = firstfailure or e + # end of while 1: try on delegating the same argument i + + # proceed to the next argument + expanded_args = (curobjs,) + expanded_args + expanded_types = (curtypes,) + expanded_types + + # complete exhaustion raise firstfailure or FailedToImplement() def is_empty(self): Modified: pypy/trunk/src/pypy/objspace/std/objectobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objectobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/objectobject.py Sun Jun 15 20:51:22 2003 @@ -3,9 +3,7 @@ class W_ObjectObject(W_Object): """Instances of this class are what the user can directly see with an - 'object()' call. Internally, they play the important role of ,,,, - types. All such instances are implemented by the present W_UserObject - class.""" + 'object()' call.""" #statictype = W_ObjectType (hacked into place below) @@ -14,124 +12,10 @@ registerimplementation(W_ObjectObject) -# default global delegation from W_ANY to W_ObjectObject -W_ANY.delegate_once[W_ObjectObject] = None # None means identity function +# any-to-object delegation is quite trivial, because W_ObjectObject is. +def delegate__ANY(space, w_obj): + return W_ObjectObject(space) +delegate__ANY.priority = PRIORITY_PARENT_TYPE -# these are the globally-defined operations that must appear as object.__xxx__. -# See also default.py. - - -# give objects some default attributes and a default way to complain -# about missing attributes - -def getattr__Object_ANY(space, w_obj, w_attr): - # XXX build a nicer error message along these lines: - #w_type = space.type(w_obj) - #w_typename = space.getattr(w_type, space.wrap('__name__')) - #... - - w_type = space.type(w_obj) - if space.is_true(space.eq(w_attr, space.wrap('__class__'))): - return w_type - - try: - w_dict = space.getdict(w_obj) - except OperationError, e: - # catch TypeError("unsupported type for getdict") - if not e.match(space, space.w_TypeError): - raise - else: - if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): - return w_dict - try: - w_value = space.getitem(w_dict, w_attr) - except OperationError, e: - # catch KeyErrors - if not e.match(space, space.w_KeyError): - raise - else: - return w_value # got a value from 'obj.__dict__[attr]' - - # XXX implement lookup as a multimethod? - from typeobject import W_TypeObject - if isinstance(w_type, W_TypeObject): # XXX must always be true at some point - try: - w_value = w_type.lookup(w_attr) - except KeyError: - pass - else: - return space.get(w_value, w_obj, w_type) - - raise OperationError(space.w_AttributeError, w_attr) - - -# set attributes, complaining about read-only ones -- -# a more declarative way to define attributes would be welcome - -def setattr__Object_ANY_ANY(space, w_obj, w_attr, w_value): - if space.is_true(space.eq(w_attr, space.wrap('__class__'))): - raise OperationError(space.w_AttributeError, - space.wrap("read-only attribute")) - try: - w_dict = space.getdict(w_obj) - except OperationError, e: - # catch TypeError("unsupported type for getdict") - if not e.match(space, space.w_TypeError): - raise - else: - if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): - raise OperationError(space.w_AttributeError, - space.wrap("read-only attribute")) - space.setitem(w_dict, w_attr, w_value) - return - - raise OperationError(space.w_AttributeError, w_attr) - - -def delattr__Object_ANY(space, w_obj, w_attr): - if space.is_true(space.eq(w_attr, space.wrap('__class__'))): - raise OperationError(space.w_AttributeError, - space.wrap("read-only attribute")) - try: - w_dict = space.getdict(w_obj) - except OperationError, e: - # catch TypeError("unsupported type for getdict") - if not e.match(space, space.w_TypeError): - raise - else: - if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): - raise OperationError(space.w_AttributeError, - space.wrap("read-only attribute")) - space.delitem(w_dict, w_attr) - return - - raise OperationError(space.w_AttributeError, w_attr) - -# static types - -def type__Object(space, w_obj): - if w_obj.statictype is None: - # XXX remove me, temporary - return space.wrap(space.unwrap(w_obj).__class__) - else: - w_type = space.get_typeinstance(w_obj.statictype) - return w_type - -# repr() - -def repr__Object(space, w_obj): - return space.wrap('<%s object at %s>'%( - space.type(w_obj).typename, space.unwrap(space.id(w_obj)))) - -# str() defaults to repr() and hash() defaults to id(). -# these should really be defined in default.py, but in CPython they -# are visible in the 'object' class. - -def str__Object(space, w_obj): - return space.repr(w_obj) - -def hash__Object(space, w_obj): - return space.id(w_obj) - register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Sun Jun 15 20:51:22 2003 @@ -9,11 +9,146 @@ typename = 'object' staticbases = () + # all multimethods that we want to be visible as object.__xxx__ + # should be defined here. + + object_getattr = StdObjSpace.getattr + object_setattr = StdObjSpace.setattr + object_delattr = StdObjSpace.delattr + object_type = StdObjSpace.type + object_repr = StdObjSpace.repr + object_str = StdObjSpace.str + object_hash = StdObjSpace.hash + # XXX we'll worry about the __new__/__init__ distinction later -def objecttype_new(space, w_objecttype, w_args, w_kwds): +def new__ObjectType_ANY_ANY(space, w_objecttype, w_args, w_kwds): # XXX 2.2 behavior: ignoring all arguments from objectobject import W_ObjectObject return W_ObjectObject(space) -StdObjSpace.new.register(objecttype_new, W_ObjectType, W_ANY, W_ANY) + +### The following implementations are registered to the +# W_ObjectType.object_xxx multimethods, which binds them to +# the 'object' type. They are however implemented on W_ANY, not +# on W_ObjectObject, so that they can receive any wrapped object +# unmodified (instead of an object converted to W_ObjectObject). +# The difference between these implementations and the ones +# defined in default.py lies in the fact that the latter are +# not registered against any particular type, which makes them +# invisible to application-level Python, whereas the functions +# below appear as object.__xxx__. + + +# give objects some default attributes and a default way to complain +# about missing attributes + +def object_getattr__ANY_ANY(space, w_obj, w_attr): + # XXX build a nicer error message along these lines: + #w_type = space.type(w_obj) + #w_typename = space.getattr(w_type, space.wrap('__name__')) + #... + + w_type = space.type(w_obj) + if space.is_true(space.eq(w_attr, space.wrap('__class__'))): + return w_type + + try: + w_dict = space.getdict(w_obj) + except OperationError, e: + # catch TypeError("unsupported type for getdict") + if not e.match(space, space.w_TypeError): + raise + else: + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + return w_dict + try: + w_value = space.getitem(w_dict, w_attr) + except OperationError, e: + # catch KeyErrors + if not e.match(space, space.w_KeyError): + raise + else: + return w_value # got a value from 'obj.__dict__[attr]' + + # XXX implement lookup as a multimethod? + from typeobject import W_TypeObject + if isinstance(w_type, W_TypeObject): # XXX must always be true at some point + try: + w_value = w_type.lookup(w_attr) + except KeyError: + pass + else: + return space.get(w_value, w_obj, w_type) # XXX 3rd arg is wrong + + raise OperationError(space.w_AttributeError, w_attr) + + +# set attributes, complaining about read-only ones -- +# a more declarative way to define attributes would be welcome + +def object_setattr__ANY_ANY_ANY(space, w_obj, w_attr, w_value): + if space.is_true(space.eq(w_attr, space.wrap('__class__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + try: + w_dict = space.getdict(w_obj) + except OperationError, e: + # catch TypeError("unsupported type for getdict") + if not e.match(space, space.w_TypeError): + raise + else: + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + space.setitem(w_dict, w_attr, w_value) + return + + raise OperationError(space.w_AttributeError, w_attr) + + +def object_delattr__ANY_ANY(space, w_obj, w_attr): + if space.is_true(space.eq(w_attr, space.wrap('__class__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + try: + w_dict = space.getdict(w_obj) + except OperationError, e: + # catch TypeError("unsupported type for getdict") + if not e.match(space, space.w_TypeError): + raise + else: + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + space.delitem(w_dict, w_attr) + return + + raise OperationError(space.w_AttributeError, w_attr) + + +# static types + +def object_type__ANY(space, w_obj): + if w_obj.statictype is None: + # XXX remove me, temporary + return space.wrap(space.unwrap(w_obj).__class__) + else: + w_type = space.get_typeinstance(w_obj.statictype) + return w_type + + +# repr(), str(), hash() + +def object_repr__ANY(space, w_obj): + return space.wrap('<%s object at %s>'%( + space.type(w_obj).typename, space.unwrap(space.id(w_obj)))) + +def object_str__ANY(space, w_obj): + return space.repr(w_obj) + +def object_hash__ANY(space, w_obj): + return space.id(w_obj) + + +register_all(vars(), W_ObjectType) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 15 20:51:22 2003 @@ -2,32 +2,34 @@ from pypy.interpreter.baseobjspace import * from multimethod import * -if not isinstance(bool, type): - booltype = () -else: - booltype = bool - class W_Object: "Parent base class for wrapped objects." - delegate_once = {} statictype = None def __init__(w_self, space): - w_self.space = space + w_self.space = space # XXX not sure this is ever used any more + + +class W_AbstractTypeObject(W_Object): + "Do not use. For W_TypeObject only." - def get_builtin_impl_class(w_self): - return w_self.__class__ W_ANY = W_Object # synonyms for use in .register() MultiMethod.ASSERT_BASE_TYPE = W_Object +MultiMethod.BASE_TYPE_OBJECT = W_AbstractTypeObject +# delegation priorities +PRIORITY_SAME_TYPE = 4 # converting between several impls of the same type +PRIORITY_PARENT_TYPE = 3 # converting to a base type (e.g. bool -> int) +PRIORITY_PARENT_IMPL = 2 # this one is always done implicitely in default.py +PRIORITY_CHANGE_TYPE = 1 # changing type altogether (e.g. int -> float) def registerimplementation(implcls): # this function should ultimately register the implementation class somewhere - # right now its only purpose is to make sure there is a - # delegate_once attribute. - implcls.__dict__.setdefault("delegate_once", {}) + # it may be modified to take 'statictype' instead of requiring it to be + # stored in 'implcls' itself + assert issubclass(implcls, W_Object) ################################################################## @@ -187,7 +189,7 @@ if isinstance(x, W_Object): raise TypeError, "attempt to wrap already wrapped object: %s"%(x,) if isinstance(x, int): - if isinstance(x, booltype): + if isinstance(bool, type) and isinstance(x, bool): return self.newbool(x) import intobject return intobject.W_IntObject(self, x) @@ -250,8 +252,10 @@ import stringobject return stringobject.W_StringObject(self, ''.join(chars)) - unwrap = MultiMethod('unwrap', 1, []) # returns an unwrapped object - is_true = MultiMethod('nonzero', 1, []) # returns an unwrapped bool + # special multimethods + delegate = DelegateMultiMethod() # delegators + unwrap = MultiMethod('unwrap', 1, []) # returns an unwrapped object + is_true = MultiMethod('nonzero', 1, []) # returns an unwrapped bool # XXX do something about __nonzero__ ! getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute @@ -296,10 +300,15 @@ l=[] for i in sig.split('_'): if i == 'ANY': - i = W_ANY + icls = W_ANY else: - i = module_dict.get('W_%s' % i) or module_dict.get('W_%sObject'%i) - l.append(i) + icls = (module_dict.get('W_%s' % i) or + module_dict.get('W_%sObject' % i)) + if icls is None: + raise ValueError, \ + "no W_%s or W_%sObject for the definition of %s" % ( + i, i, name) + l.append(icls) if len(l) != obj.func_code.co_argcount-1: raise ValueError, \ @@ -308,10 +317,10 @@ funcname = _name_mappings.get(funcname, funcname) - if hasattr(StdObjSpace, funcname): - getattr(StdObjSpace, funcname).register(obj, *l) - else: + if hasattr(alt_ns, funcname): getattr(alt_ns, funcname).register(obj, *l) + else: + getattr(StdObjSpace, funcname).register(obj, *l) # import the common base W_ObjectObject as well as # default implementations of some multimethods for all objects Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Sun Jun 15 20:51:22 2003 @@ -3,12 +3,21 @@ from pypy.objspace.std.multimethod import * -MultiMethod.ASSERT_BASE_TYPE = None -W_ANY = object + +# default delegator + +def class_to_parent_classes(space, w_obj): + converted = [] + W_Cls = w_obj.__class__ + while len(W_Cls.__bases__) == 1: + W_Cls, = W_Cls.__bases__ + converted.append((W_Cls, w_obj)) + return converted + +class_to_parent_classes.priority = 1 class X: - delegate_once = {} def __init__(self, value): self.value = value def __repr__(self): @@ -17,12 +26,24 @@ def from_y_to_x(space, yinstance): return X(yinstance) +from_y_to_x.priority = 2 + +def from_x_to_str_sometimes(space, xinstance): + if xinstance.value: + return '!' + repr(xinstance.value) + else: + return [] + +from_x_to_str_sometimes.priority = 2 + + class Y: - delegate_once = {X: from_y_to_x} def __init__(self, value): self.value = value def __repr__(self): return '' % self.value + def __nonzero__(self): + return self.value != 666 def add_x_x(space, x1, x2): @@ -52,7 +73,12 @@ add.register(add_y_y, Y, Y) add.register(add_string_string, str, str) add.register(add_int_string, int, str) - add.register(add_int_any, int, W_ANY) + add.register(add_int_any, int, object) + + delegate = DelegateMultiMethod() + delegate.register(from_y_to_x, Y) + delegate.register(from_x_to_str_sometimes, X) + delegate.register(class_to_parent_classes, Ellipsis) def wrap(self, x): return '' % (x,) @@ -95,6 +121,16 @@ self.assertRaises(OperationError, space.add, 3.0,'bla') + r = space.add(X(42),"spam") + self.assertEquals(repr(r), "('add_string_string', '!42', 'spam')") + + r = space.add(Y(20),"egg") + self.assertEquals(repr(r), "('add_string_string', '!', 'egg')") + + self.assertRaises(OperationError, space.add, X(0),"spam") + + self.assertRaises(OperationError, space.add, Y(666),"egg") + if __name__ == '__main__': unittest.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Sun Jun 15 20:51:22 2003 @@ -12,8 +12,8 @@ def test_int_sub(self): w = self.space.wrap for i in range(2): - meth = PyMultimethodCode(self.space.sub.multimethod, - i, self.space.w_int) + meth = PyMultimethodCode(self.space.sub.multimethod, + self.space.w_int.__class__, i) self.assertEqual(meth.slice().is_empty(), False) # test int.__sub__ and int.__rsub__ self.assertEqual_w(meth.eval_code(self.space, None, @@ -29,7 +29,7 @@ def test_empty_inplace_add(self): for i in range(2): meth = PyMultimethodCode(self.space.inplace_add.multimethod, - i, self.space.w_int) + self.space.w_int.__class__, i) self.assertEqual(meth.slice().is_empty(), True) def test_float_sub(self): @@ -37,7 +37,7 @@ w(1.5) # force floatobject imported for i in range(2): meth = PyMultimethodCode(self.space.sub.multimethod, - i, self.space.w_float) + self.space.w_float.__class__, i) self.assertEqual(meth.slice().is_empty(), False) # test float.__sub__ and float.__rsub__ Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sun Jun 15 20:51:22 2003 @@ -2,14 +2,14 @@ from pypy.objspace.std.objspace import * -class W_TypeObject(W_Object): +class W_TypeObject(W_AbstractTypeObject): """This class is abstract. Subclasses are defined in 'xxxtype.py' files. The instances of these subclasses are what the user sees as Python's type objects. This class defines all general type-oriented behavior like attribute lookup and method resolution order. Inheritance relationships are implemented *only* with the getbases() methods of W_TypeObject subclasses, *not* with interpreter-level inheritance between - X_Xxx classes *nor* with multimethod delegation.""" + W_Xxx classes *nor* with multimethod delegation.""" typename = None # to be overridden by subclasses or instances #statictype = W_TypeType (hacked into place below) @@ -19,18 +19,19 @@ W_Object.__init__(w_self, space) w_self.w_tpname = space.wrap(w_self.typename) w_self.multimethods = {} - # import all multimethods of the space and of the type class - for multimethod in (hack_out_multimethods(space.__class__) + - hack_out_multimethods(w_self.__class__)): + # import all multimethods of the type class and of the objspace + for multimethod in (hack_out_multimethods(w_self.__class__) + + hack_out_multimethods(space.__class__)): for i in range(len(multimethod.specialnames)): - # each PyMultimethodCode bytecode is a (lazy, cached, - # dynamically recomputed) slice of a multimethod. - code = PyMultimethodCode(multimethod, i, w_self) - w_self.multimethods[multimethod.specialnames[i]] = code + # each PyMultimethodCode embeds a multimethod + name = multimethod.specialnames[i] + code = PyMultimethodCode(multimethod, w_self.__class__, i) + w_self.multimethods[name] = code def getbases(w_self): parents = w_self.staticbases if parents is None: + # Note: this code is duplicated in multimethod.py import objecttype parents = (objecttype.W_ObjectType,) basetypes = [w_self.space.get_typeinstance(parent) for parent in parents] @@ -45,8 +46,9 @@ return tuple(mro) def lookup(w_self, w_key): - "XXX at some point, turn this into a multimethod" # note that this doesn't call __get__ on the result at all + # XXX this should probably also return the (parent) class in which + # the attribute was found for w_class in w_self.getmro(): try: return w_class.lookup_exactly_here(w_key) @@ -66,20 +68,6 @@ raise KeyError return space.newfunction(code, space.w_None, code.getdefaults(space)) - def acceptclass(w_self, cls): - # For multimethod slicing. This checks whether a Python object of - # type 'w_self' would be acceptable for a multimethod implementation - # defined on the 'W_Xxx' class specified by 'cls'. - # Currently implemented by following the 'statictype' attribute. - # This results in operations defined on W_ObjectObject to be accepted, - # but operations defined on W_ANY to be rejected. - statictypeclass = cls.statictype - if statictypeclass is not None: - for w_parent in w_self.getmro(): - if isinstance(w_parent, statictypeclass): - return True - return False - import typetype, objecttype W_TypeObject.statictype = typetype.W_TypeType @@ -87,13 +75,18 @@ def hack_out_multimethods(cls): - return [value for value in cls.__dict__.itervalues() - if isinstance(value, MultiMethod)] + result = [] + for base in cls.__bases__: + result += hack_out_multimethods(base) + for value in cls.__dict__.itervalues(): + if isinstance(value, MultiMethod): + result.append(value) + return result class PyMultimethodCode(pycode.PyBaseCode): - def __init__(self, multimethod, bound_position, w_type): + def __init__(self, multimethod, typeclass, bound_position=0): pycode.PyBaseCode.__init__(self) argnames = ['x%d'%(i+1) for i in range(multimethod.arity)] argnames.insert(0, argnames.pop(bound_position)) @@ -102,45 +95,26 @@ self.co_varnames = tuple(argnames) self.co_argcount = multimethod.arity self.basemultimethod = multimethod - self.slicedmultimethod = None + self.typeclass = typeclass self.bound_position = bound_position - self.w_type = w_type def getdefaults(self, space): return space.wrap(self.basemultimethod.defaults) - def cleardependency(self): - # called when the underlying dispatch table is modified - self.slicedmultimethod = None - def slice(self): - if self.slicedmultimethod is None: - multimethod = self.basemultimethod - #print "pypy: slicing %r for a %r argument at position %d" % ( - # multimethod.operatorsymbol, - # self.w_type.typename, self.bound_position) - # slice the multimethod and cache the result - sliced = multimethod.slicetable(self.bound_position, self.w_type) - #if sliced.is_empty(): - # print "the slice is empty" - self.slicedmultimethod = sliced.__get__(self.w_type.space, None) - multimethod.cache_dependency(self) - return self.slicedmultimethod + return self.basemultimethod.slice(self.typeclass, self.bound_position) def eval_code(self, space, w_globals, w_locals): """Call the multimethod, ignoring all implementations that do not have exactly the expected type at the bound_position.""" multimethod = self.slice() dispatchargs = [] - initialtypes = [] - for i in range(multimethod.multimethod.arity): + for i in range(multimethod.arity): w_arg = space.getitem(w_locals, space.wrap('x%d'%(i+1))) dispatchargs.append(w_arg) - initialtypes.append(w_arg.get_builtin_impl_class()) dispatchargs = tuple(dispatchargs) - initialtypes = tuple(initialtypes) try: - w_result = multimethod.perform_call(dispatchargs, initialtypes) + w_result = multimethod.get(space).perform_call(dispatchargs) except FailedToImplement, e: if e.args: raise OperationError(*e.args) @@ -169,8 +143,9 @@ # XXX mwh doubts this is the Right Way to do this... if space.is_true(space.eq(w_attr, space.wrap('__name__'))): return w_type.w_tpname + if space.is_true(space.eq(w_attr, space.wrap('__mro__'))): + return space.newtuple(list(w_type.getmro())) raise FailedToImplement register_all(vars()) - Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Sun Jun 15 20:51:22 2003 @@ -9,48 +9,18 @@ class.""" statictype = W_UserType - # Nota Bene: we expect W_UserObject instances whose type inherits - # from a built-in type to also contain the attributes of the - # corresponding W_XxxObject class. This is a non-restricted-Python- - # compliant hack that we may have to rethink at some point. - # It is similar to CPython's instances of subtypes of built-in - # types whose memory layout start with what looks like an instance - # of the parent built-in type. - def __init__(w_self, space, w_type, w_args, w_kwds): # the restriction that a single built-in type is allowed among the # bases is specific to our W_UserObject implementation of user # objects, and should thus not be enforced in W_UserType. - w_builtintype = getsinglebuiltintype(space, w_type) + # Note: w_type may be any object, not necessarily a W_UserType + # (in case 'type' is subclassed). - # first create an instance of the parent built-in type - w_preself = space.call(w_builtintype, w_args, w_kwds) - if not space.is_true(space.is_(space.type(w_preself), w_builtintype)): - raise OperationError(space.w_TypeError, - space.wrap("instantiating a subtype of a type " - "with a misbehaving constructor")) - - # add custom attributes - w_self.__dict__.update( - {'w_uo_preself': w_preself, - 'w_uo_type': w_type, - 'w_uo_dict': space.newdict([]), - }) - - def __getattr__(w_self, attr): - return getattr(w_self.w_uo_preself, attr) - - def __setattr__(w_self, attr, value): - if attr in w_self.__dict__: - w_self.__dict__[attr] = value - else: - setattr(w_self.w_preself, attr, value) - - def __delattr__(w_self, attr): - raise AttributeError, "we don't wants attribute deletion in RPython" - - def get_builtin_impl_class(w_self): - return w_self.w_uo_preself.get_builtin_impl_class() + # create an instance of the parent built-in type + w_builtintype = getsinglebuiltintype(space, w_type) + w_self.w_embedded = space.call(w_builtintype, w_args, w_kwds) + w_self.w_type = w_type + w_self.w_dict = space.newdict([]) registerimplementation(W_UserObject) @@ -59,7 +29,8 @@ def getsinglebuiltintype(space, w_type): "Return the (asserted unique) built-in type that w_type inherits from." mostspecialized = space.w_object - mro = list(w_type.getmro()) + mro = space.getattr(w_type, space.wrap('__mro__')) + mro = space.unpacktuple(mro) mro.reverse() for w_base in mro: if not isinstance(w_base, W_UserType): @@ -71,56 +42,67 @@ return mostspecialized -def type__User(space, w_userobj): - return w_userobj.w_uo_type +# W_UserObject-to-the-parent-builtin-type delegation +# So far this is the only delegation that produces a result +# of a variable type. +def delegate__User(space, w_userobj): + return w_userobj.w_embedded +delegate__User.priority = PRIORITY_PARENT_TYPE +def type__User(space, w_userobj): + return w_userobj.w_type + def getdict__User(space, w_userobj): # XXX check getdict() of the base built-in implementation - return w_userobj.w_uo_dict + return w_userobj.w_dict + -# We register here all multimethods with at least one W_UserObject. -# No multimethod must be explicitely registered on W_UserObject except -# here, unless you want to completely override a behavior for user-defined -# types, as in user_type and user_getdict. - -def build_user_operation(multimethod): - def user_operation(space, *args_w): - if len(args_w) != multimethod.arity: - raise TypeError, "wrong number of arguments" - for i in range(len(multimethod.specialnames)): - w_arg = args_w[i] - if isinstance(w_arg, W_UserObject): - specialname = multimethod.specialnames[i] - try: - w_value = w_arg.w_uo_type.lookup(space.wrap(specialname)) - except KeyError: - pass - else: - # 'w_value' is a __xxx__ function object - w_value = space.get(w_value, w_arg, w_arg.w_uo_type) - # 'w_value' is now a bound method. - # if it is a sliced multimethod it should do the - # get_builtin_impl_class() trick automatically, not - # dispatching again on W_UserObject. - rest_args = list(args_w) - del rest_args[i] - w_args_w = space.newtuple(rest_args) - w_result = space.call(w_value, w_args_w, space.newdict([])) - if not space.is_true(space.is_(w_result, - space.w_NotImplemented)): - return w_result # if w_result is not NotImplemented - raise FailedToImplement - return user_operation +# register an implementation for all multimethods that define special names +def user_specialmethod(space, *args_w): + # args_w is in the standard multimethod order + # we need it in the Python-friendly order (i.e. swapped for __rxxx__) + args_w = list(args_w) + w_userobj = args_w.pop(g_bound_position) + w_args = space.newtuple(args_w) + w_key = space.wrap(g_method_name) + mro = space.getattr(w_userobj.w_type, space.wrap('__mro__')) + mro = space.unpacktuple(mro) + for w_base in mro: + if not isinstance(w_base, W_UserType): + continue + try: + w_function = w_base.lookup_exactly_here(w_key) + except KeyError: + continue + w_method = space.get(w_function, w_userobj, w_base) + w_result = space.call(w_method, w_args, space.newdict([])) + # XXX hack to accept real Nones from operations with no return value + if w_result is None: + return space.w_None + elif space.is_true(space.is_(w_result, space.w_NotImplemented)): + raise FailedToImplement + else: + return w_result + raise FailedToImplement +import new for multimethod in typeobject.hack_out_multimethods(StdObjSpace): - if multimethod not in (StdObjSpace.getdict, - StdObjSpace.type): - user_operation = build_user_operation(multimethod) - for i in range(multimethod.arity): - signature = [W_ANY] * multimethod.arity - signature[i] = W_UserObject - multimethod.register(user_operation, *signature) + for i in range(len(multimethod.specialnames)): + # a hack to avoid nested scopes is to give the function + # a custom globals dictionary + + g = {'W_UserType' : W_UserType, + 'FailedToImplement': FailedToImplement, + '__builtins__' : __builtins__, + 'g_method_name' : multimethod.specialnames[i], + 'g_bound_position' : i} + f = new.function(user_specialmethod.func_code, g, + 'user_%s' % multimethod.specialnames[i]) + + signature = [W_ANY] * multimethod.arity + signature[i] = W_UserObject + multimethod.register(f, *signature) register_all(vars()) From arigo at codespeak.net Mon Jun 16 17:54:20 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 16 Jun 2003 17:54:20 +0200 (MEST) Subject: [pypy-svn] rev 813 - in pypy/trunk: doc src/pypy/objspace/std Message-ID: <20030616155420.27BD35C034@thoth.codespeak.net> Author: arigo Date: Mon Jun 16 17:54:19 2003 New Revision: 813 Added: pypy/trunk/doc/mm_notes.txt - copied unchanged from rev 812, pypy/trunk/src/pypy/objspace/std/mm_notes.txt Removed: pypy/trunk/src/pypy/objspace/std/mm_notes.txt Log: Moved this document to doc/ Deleted: pypy/trunk/src/pypy/objspace/std/mm_notes.txt ============================================================================== --- pypy/trunk/src/pypy/objspace/std/mm_notes.txt Mon Jun 16 17:54:19 2003 +++ (empty file) @@ -1,145 +0,0 @@ - - -Notes on Multimethods -********************* - - -Interpreter-level classes correspond to implementations of application-level -types. Several implementations can be given for the same type (e.g. several -ways to code strings or dictionaries), and conversely the same implementation -can cover several types (e.g. all instances of user-defined types currently -share the same implementation). - -The hierarchy among the classes used for the implementations is convenient -for implementation purposes. It is not related to any application-level type -hierarchy. - - -Dispatch --------- - -Multimethods dispatch by looking in a set of registered functions. Each -registered function has a signature, which defines which object implementation -classes are accepted at the corresponding argument position. - -The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' -later). As it accepts anything, it is the only way to guarantee that the -registered function will be called with exactly the same object as was -passed originally. ATTENTION: in all other cases the argument received by -the function may have been converted in some way. It must thus not be -considered to be 'id'entical to the original argument. For example it should -not be stored in a data structure, nor be queried for type, nor be used for -another multimethod dispatch -- the only thing you should do is read and -write its internal data. - -For example, 'getattr(obj, attr)' is implemented with a W_StringObject second -argument when all it needs is just the name of the attr, and with a W_ANY -when the 'attr' object could be used as a key in obj.__dict__. - - -Delegation ----------- - -Delegation is a transparent convertion mechanism between object -implementations. The convertion can give a result of a different type -(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). -There is a global table of delegators. We should not rely on the delegators -to be tried in any particlar order, or at all (e.g. the int -> float delegator -could be ignored when we know that no registered function will accept a float -anyway). - -Delegation is also used to emulate inheritance between built-in types -(e.g. bool -> int). This is done by delegation because there is no reason -that a particular implementation of a sub-type can be trivially typecast -to some other particular implementation of the parent type; the process might -require some work. - - -Types ------ - -Types are implemented by the class W_TypeObject. This is where inheritance -and the Method Resolution Order are defined, and where attribute look-ups -are done. - -Instances of user-defined types are implementated as W_UserObjects. -A user-defined type can inherit from built-in types (maybe more than one, -although this is incompatible with CPython). The W_UserObject delegator -converts the object into any of these "parent objects" if needed. This is -how user-defined types appear to inherit all built-in operator -implementations. - -Delegators should be able to invoke user code; this would let us -implement special methods like __int__() by calling them within a -W_UserObject -> int delegator. - - -Specifics of multimethods -------------------------- - -Multimethods dispatch more-specific-first, left-to-right (i.e. if there is -an exact match for the first argument it will always be tried first). - -Delegators are automatically chained (i.e. A -> B and B -> C would be -combined to allow for A -> C delegation). - -Delegators do not publish the class of the converted object in advance, -so that the W_UserObject delegator can potentially produce any other -built-in implementation. This means chaining and chain loop detection cannot -be done statically (at least without help from an analysis tool like the -translator-to-C). To break loops, we can assume (unless a particular need -arises) that delegators are looping when they return an object of an -already-seen class. - - -Registration ------------- - -The register() method of multimethods adds a function to its database of -functions, with the given signature. A function that raises -FailedToImplement causes the next match to be tried. - -'delegate' is the special unary multimethod that should try to convert -its argument to something else. For greater control, it can also return -a list of 2-tuples (class, object), or an empty list for failure to convert -the argument to anything. All delegators will potentially be tried, and -recursively on each other's results to do chaining. - -A priority ordering between delegators is used. See objspace.PRIORITY_*. - - -Translation ------------ - -The code in multimethod.py is not supposed to be read by the -translator-to-C. Special optimized code will be generated instead -(typically some kind of precomputed dispatch tables). - -Delegation is special-cased too. Most delegators will be found -to return an object of a statically known class, which means that -most of the chaining and loop detection can be done in advance. - - -Multimethod slicing -------------------- - -Multimethods are visible to user code as (bound or unbound) methods -defined for the corresponding types. (At some point built-in functions -like len() and the operator.xxx() should really directly map to the -multimethods themselves, too.) - -To build a method from a multimethod (e.g. as in 'l.append' or -'int.__add__'), the result is actually a "slice" of the whole -multimethod, i.e. a sub-multimethod in which the registration table has -been trimmed down. (Delegation mechanisms are not restricted for sliced -multimethods.) - -Say that C is the class the new method is attached to (in the above -examples, respectively, C=type(l) and C=int). The restriction is -based on the registered class of the first argument ('self' for the -new method) in the signature. If this class corresponds to a fixed -type (as advertized by 'statictype'), and this fixed type is C or a -superclass of C, then we keep it. - -Some multimethods can also be sliced along their second argument, -e.g. for __radd__(). From mwh at codespeak.net Mon Jun 16 20:02:02 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 16 Jun 2003 20:02:02 +0200 (MEST) Subject: [pypy-svn] rev 814 - pypy/trunk/src/pypy/interpreter Message-ID: <20030616180202.64C2B5C028@thoth.codespeak.net> Author: mwh Date: Mon Jun 16 20:02:00 2003 New Revision: 814 Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py Log: fix potential UnboundLocalError Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode_app.py Mon Jun 16 20:02:00 2003 @@ -71,6 +71,8 @@ # XXX This should be improved to show the parameters that # shouldn't be here. raise TypeError, 'Setting keyword parameter that does not exist in formal parameter list.' + else: + newkw = {} # Fill in with defaults, starting at argcount - defcount if defs: From mwh at codespeak.net Mon Jun 16 20:05:25 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 16 Jun 2003 20:05:25 +0200 (MEST) Subject: [pypy-svn] rev 815 - pypy/trunk/src/pypy/objspace Message-ID: <20030616180525.F2A6E5C028@thoth.codespeak.net> Author: mwh Date: Mon Jun 16 20:05:25 2003 New Revision: 815 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: tweaks, to allow running dis-pregoal under the trivial object space. Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 16 20:05:25 2003 @@ -66,10 +66,17 @@ self.w_None = None self.w_True = True self.w_False = False + self.w_NotImplemented = NotImplemented + self.w_Ellipsis = Ellipsis import __builtin__, types newstuff = {"False": self.w_False, "True" : self.w_True, + "NotImplemented" : self.w_NotImplemented, "None" : self.w_None, + "Ellipsis" : self.w_Ellipsis, + "buffer": buffer, + "xrange": xrange, + "slice": slice, } for n, c in __builtin__.__dict__.iteritems(): if isinstance(c, types.TypeType): @@ -255,7 +262,7 @@ def __init__(self, space, code, globals, defaultarguments, closure): self.space = space self.__name__ = code.co_name - self.code = code + self.func_code = self.code = code self.globals = globals self.defaultarguments = defaultarguments self.closure = closure From mwh at codespeak.net Tue Jun 17 16:40:56 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 16:40:56 +0200 (MEST) Subject: [pypy-svn] rev 816 - pypy/trunk/src/pypy/interpreter Message-ID: <20030617144056.669175C040@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 16:40:55 2003 New Revision: 816 Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py Log: wrap long line Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode_app.py Tue Jun 17 16:40:55 2003 @@ -70,7 +70,8 @@ if count: # XXX This should be improved to show the parameters that # shouldn't be here. - raise TypeError, 'Setting keyword parameter that does not exist in formal parameter list.' + raise TypeError('Setting keyword parameter that does ' + 'not exist in formal parameter list.') else: newkw = {} From mwh at codespeak.net Tue Jun 17 17:23:17 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 17:23:17 +0200 (MEST) Subject: [pypy-svn] rev 817 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030617152317.AF4015C03F@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 17:23:17 2003 New Revision: 817 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py Log: make dictionaries iterable Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 17 17:23:17 2003 @@ -106,6 +106,12 @@ return space.w_True return space.w_False +def iter__Dict(space, w_dict): + import iterobject + w_keys = dict_keys__Dict(space, w_dict) + return iterobject.W_SeqIterObject(space, w_keys) + + ##def getattr_dict(space, w_dict, w_attr): ## if space.is_true(space.eq(w_attr, space.wrap('copy'))): ## w_builtinfn = make_builtin_func(space, W_DictObject.copy) @@ -155,5 +161,4 @@ for w_key,cell in w_self.non_empties()]) - register_all(vars(), W_DictType) From mwh at codespeak.net Tue Jun 17 17:24:31 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 17:24:31 +0200 (MEST) Subject: [pypy-svn] rev 818 - in pypy/trunk/src/pypy/interpreter: . test Message-ID: <20030617152431.5D1965C040@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 17:24:30 2003 New Revision: 818 Modified: pypy/trunk/src/pypy/interpreter/extmodule.py pypy/trunk/src/pypy/interpreter/pycode.py pypy/trunk/src/pypy/interpreter/test/test_extmodule.py Log: support for varadic and varkeywordic (sic) builtin functions i have a feeling i may be being overly clever again in extmodule.py, feel free to quibble (OTOH, it works & has tests) Modified: pypy/trunk/src/pypy/interpreter/extmodule.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/extmodule.py (original) +++ pypy/trunk/src/pypy/interpreter/extmodule.py Tue Jun 17 17:24:30 2003 @@ -14,6 +14,8 @@ return self.data +# a little excercise in OOP, Python 2.2-style: + class PyBuiltinCode(pycode.PyBaseCode): """The code object implementing a built-in (interpreter-level) hook.""" @@ -23,8 +25,6 @@ co = func.func_code self.co_name = func.__name__ self.co_flags = co.co_flags - # extract argument names from 'co', - # removing 'self' and the 'w_' prefixes if boundmethod: assert co.co_varnames[0] == "self" start = 1 @@ -36,18 +36,72 @@ argnames.append(argname[2:]) self.co_varnames = tuple(argnames) self.co_argcount = co.co_argcount - start + self.next_arg = self.co_argcount + start - def eval_code(self, space, w_globals, w_locals): - # this isn't quite complete: varargs and kwargs are missing + def prepare_args(self, space, w_locals): args = [] - for argname in self.co_varnames: + for argname in self.co_varnames[:self.co_argcount]: w_arg = space.getitem(w_locals, space.wrap(argname)) args.append(w_arg) - w_ret = self.func(*args) - return w_ret + return args + + def eval_code(self, space, w_globals, w_locals): + args = self.prepare_args(space, w_locals) + return self.func(*args) + + +class PyBuiltinVarCode(PyBuiltinCode): + + def __init__(self, func, boundmethod=False): + super(PyBuiltinVarCode, self).__init__(func, boundmethod) + self.vararg_name = func.func_code.co_varnames[self.next_arg] + self.co_varnames += (self.vararg_name,) + assert self.vararg_name.endswith('_w'), "%s, arg %d: %s"%( + func.func_name, self.co_argcount + 1, self.vararg_name) + self.next_arg += 1 + + def prepare_args(self, space, w_locals): + args = super(PyBuiltinVarCode, self).prepare_args(space, w_locals) + w_args = space.getitem(w_locals, space.wrap(self.vararg_name)) + args.extend(space.unpackiterable(w_args)) + return args + + +class PyBuiltinKwCode(PyBuiltinCode): + def __init__(self, func, boundmethod=False): + super(PyBuiltinKwCode, self).__init__(func, boundmethod) + self.kwarg_name = func.func_code.co_varnames[self.next_arg] + self.co_varnames += (self.kwarg_name,) + assert self.kwarg_name.endswith('_w'), "%s, arg %d: %s"%( + func.func_name, self.co_argcount + 1, self.kwarg_name) + self.next_arg += 1 + + def eval_code(self, space, w_globals, w_locals): + args = self.prepare_args(space, w_locals) + w_kws = space.getitem(w_locals, space.wrap(self.kwarg_name)) + kws = {} + for w_key in space.unpackiterable(w_kws): + kws[space.unwrap(w_key)] = space.getitem(w_kws, w_key) + + return self.func(*args, **kws) + + +class PyBuiltinVarKwCode(PyBuiltinKwCode, PyBuiltinVarCode): + pass + def make_builtin_func(space, func, boundmethod=False): - code = PyBuiltinCode(func, boundmethod) + if func.func_code.co_flags & pycode.CO_VARARGS: + if func.func_code.co_flags & pycode.CO_VARKEYWORDS: + code_cls = PyBuiltinVarKwCode + else: + code_cls = PyBuiltinVarCode + else: + if func.func_code.co_flags & pycode.CO_VARKEYWORDS: + code_cls = PyBuiltinKwCode + else: + code_cls = PyBuiltinCode + code = code_cls(func, boundmethod) w_defaults = space.wrap(func.func_defaults) w_function = space.newfunction(code, space.w_None, w_defaults) return w_function Modified: pypy/trunk/src/pypy/interpreter/pycode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode.py Tue Jun 17 17:24:30 2003 @@ -25,7 +25,7 @@ CO_VARKEYWORDS = 0x0008 -class PyBaseCode: +class PyBaseCode(object): def __init__(self): self.co_name = "" self.co_flags = 0 Modified: pypy/trunk/src/pypy/interpreter/test/test_extmodule.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_extmodule.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_extmodule.py Tue Jun 17 17:24:30 2003 @@ -98,7 +98,34 @@ self.assertEqual_w(w_res, w(65)) w_res = space.call_function(builtin_f, w_input, w(100)) self.assertEqual_w(w_res, w(142)) - + + def test_varargs(self): + s = self.space + w = s.wrap + def f(w_first, *args_w): + w_r = w_first + for w_i in args_w: + w_r = s.add(w_r, w_i) + return w_r + builtin_f = extmodule.make_builtin_func(s, f) + self.assertEqual_w(s.call_function(builtin_f, w(1)), w(1)) + self.assertEqual_w(s.call_function(builtin_f, w(1), w(2), w(3)), w(6)) + + def test_kwargs(self): + s = self.space + w = s.wrap + def f(**kws_w): + return s.add(kws_w['a'], kws_w['b']) + builtin_f = extmodule.make_builtin_func(s, f) + self.assertEqual_w(s.call_function(builtin_f, a=w(1), b=w(2)), w(3)) + + def test_varkwargs(self): + s = self.space + w = s.wrap + def f(*args_w, **kws_w): + return s.add(args_w[0], kws_w['a']) + builtin_f = extmodule.make_builtin_func(s, f) + self.assertEqual_w(s.call_function(builtin_f, w(2), a=w(1)), w(3)) if __name__ == '__main__': testsupport.main() From mwh at codespeak.net Tue Jun 17 17:26:14 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 17:26:14 +0200 (MEST) Subject: [pypy-svn] rev 819 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030617152614.D73035C040@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 17:26:13 2003 New Revision: 819 Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: skip test_extended_slices when it's going to fail anyway (running under TrivialObjSpace in Python < 2.3). Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Tue Jun 17 17:26:13 2003 @@ -94,6 +94,10 @@ def test_extended_slice(self): space = self.space + if self.space.__class__.__name__.startswith('Trivial'): + import sys + if sys.version < (2, 3): + return w_None = space.w_None w = space.wrap w_str = w('hello') From mwh at codespeak.net Tue Jun 17 17:29:48 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 17:29:48 +0200 (MEST) Subject: [pypy-svn] rev 820 - pypy/trunk/src/pypy/interpreter Message-ID: <20030617152948.DC8CE5C040@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 17:29:48 2003 New Revision: 820 Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py Log: support for app-space tests: derive a testcase from i testsupport.AppTestCase (relavent changes to the testsupport.py files will follow next) Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/unittest_w.py (original) +++ pypy/trunk/src/pypy/interpreter/unittest_w.py Tue Jun 17 17:29:48 2003 @@ -1,7 +1,70 @@ import sys, os import unittest +import testtools -class TestCase_w(unittest.TestCase): +def wrap_func(space, func): + # this is generally useful enough that it should probably go + # somewhere more obvious (objspace method?) + from pypy.interpreter import pycode + code = pycode.PyByteCode() + code._from_code(func.func_code) + return space.newfunction(code, space.newdict([]), + space.wrap(func.func_defaults), None) + + +def make_testcase_class(space, tc_w): + # XXX this is all a bit insane (but it works) + + from pypy.interpreter.extmodule import make_builtin_func + w = space.wrap + d = space.newdict([]) + for name in dir(AppTestCase): + if name.startswith('assert') or name.startswith('fail'): + if hasattr(tc_w, 'app_' + name): + builtin_func = make_builtin_func(space, getattr(tc_w, "app_" + name), + boundmethod=True) + space.setitem(d, w(name), builtin_func) + w_tc = space.call_function(space.w_type, + w('TestCase'), + space.newtuple([]), + d) + return space.call_function(w_tc) + + +class WrappedFunc(object): + def __init__(self, testCase, testMethod): + self.testCase = testCase + self.testMethod = testMethod + def __call__(self): + from pypy.interpreter import executioncontext + from pypy.interpreter import pyframe + s = self.testCase.space + w = s.wrap + + w_tc_attr = 'tc-attr-hacky-thing' + if hasattr(s, w_tc_attr): + w_tc = getattr(s, w_tc_attr) + else: + w_tc = make_testcase_class(s, self.testCase) + setattr(s, w_tc_attr, w_tc) + + w_f = wrap_func(s, self.testMethod.im_func) + try: + s.call_function(w_f, w_tc) + except executioncontext.OperationError, oe: + oe.print_application_traceback(s) + import __builtin__ + w_res = s.gethelper(pyframe.appfile).call( + "normalize_exception", [oe.w_type, oe.w_value]) + w_value = s.getitem(w_res, s.wrap(1)) + exc_name = s.getattr(s.getattr(w_value, w('__class__')), + w('__name__')) + exc_type = getattr(__builtin__, s.unwrap(exc_name)) + # it's a tad annoying we can't fake the traceback + raise exc_type(*s.unwrap(s.getattr(w_value, w('args')))) + + +class IntTestCase(unittest.TestCase): """ enrich TestCase with wrapped-methods """ def failUnless_w(self, w_condition, msg=None): @@ -43,3 +106,50 @@ self.failUnless(e.match(self.space, w_exc_class)) else: self.fail('should have got an exception') + + +class AppTestCase(IntTestCase): + def __init__(self, methodName='runTest'): + self.methodName = methodName + unittest.TestCase.__init__(self, methodName) + + def __call__(self, result=None): + setattr(self, self.methodName, + WrappedFunc(self, getattr(self, self.methodName))) + return unittest.TestCase.__call__(self, result) + + def setUp(self): + self.space = testtools.objspace() + + def app_fail(self, w_self, w_msg=None): + msg = self.space.unwrap(w_msg) + self.fail(msg) + + def app_failIf(self, w_self, w_expr, w_msg=None): + msg = self.space.unwrap(w_msg) + self.failIf_w(w_expr) + + def app_failUnless(self, w_self, w_expr, w_msg=None): + msg = self.space.unwrap(w_msg) + self.failUnless_w(w_expr) + + def app_failUnlessRaises(self, w_self, w_exc_class, + w_callable, *args_w, **kw_w): + self.assertWRaises_w(w_exc_class, w_callable, *args_w, **kw_w) + + def app_failUnlessEqual(self, w_self, w_first, w_second, w_msg=None): + msg = self.space.unwrap(w_msg) + self.assertEqual_w(w_first, w_second, msg) + + def app_failIfEqual(self, w_self, w_first, w_second, w_msg=None): + msg = self.space.unwrap(w_msg) + self.assertNotEqual_w(w_first, w_second, msg) + + app_assertEqual = app_assertEquals = app_failUnlessEqual + + app_assertNotEqual = app_assertNotEquals = app_failIfEqual + + app_assertRaises = app_failUnlessRaises + + app_assert_ = app_failUnless + From mwh at codespeak.net Tue Jun 17 17:30:15 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 17:30:15 +0200 (MEST) Subject: [pypy-svn] rev 821 - in pypy/trunk/src/pypy: . appspace/test interpreterinterpreter/test module/test objspace/std/test Message-ID: <20030617153015.12FBD5C040@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 17:30:14 2003 New Revision: 821 Modified: pypy/trunk/src/pypy/appspace/test/testsupport.py pypy/trunk/src/pypy/interpreter/test/testsupport.py pypy/trunk/src/pypy/interpreter/testsupport.py pypy/trunk/src/pypy/module/test/testsupport.py pypy/trunk/src/pypy/objspace/std/test/testsupport.py pypy/trunk/src/pypy/testsupport.py Log: changes to testsupport files to support app-space tests Modified: pypy/trunk/src/pypy/appspace/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/testsupport.py (original) +++ pypy/trunk/src/pypy/appspace/test/testsupport.py Tue Jun 17 17:30:14 2003 @@ -43,7 +43,8 @@ import pypy.interpreter.unittest_w from pypy.interpreter.testtools import * -TestCase = pypy.interpreter.unittest_w.TestCase_w +TestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase main = unittest.main if __name__ == '__main__': Modified: pypy/trunk/src/pypy/interpreter/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/testsupport.py (original) +++ pypy/trunk/src/pypy/interpreter/test/testsupport.py Tue Jun 17 17:30:14 2003 @@ -43,7 +43,8 @@ import pypy.interpreter.unittest_w from pypy.interpreter.testtools import * -TestCase = pypy.interpreter.unittest_w.TestCase_w +TestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase main = unittest.main if __name__ == '__main__': Modified: pypy/trunk/src/pypy/interpreter/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/testsupport.py (original) +++ pypy/trunk/src/pypy/interpreter/testsupport.py Tue Jun 17 17:30:14 2003 @@ -43,7 +43,8 @@ import pypy.interpreter.unittest_w from pypy.interpreter.testtools import * -TestCase = pypy.interpreter.unittest_w.TestCase_w +TestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase main = unittest.main if __name__ == '__main__': Modified: pypy/trunk/src/pypy/module/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/module/test/testsupport.py (original) +++ pypy/trunk/src/pypy/module/test/testsupport.py Tue Jun 17 17:30:14 2003 @@ -43,7 +43,8 @@ import pypy.interpreter.unittest_w from pypy.interpreter.testtools import * -TestCase = pypy.interpreter.unittest_w.TestCase_w +TestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase main = unittest.main if __name__ == '__main__': Modified: pypy/trunk/src/pypy/objspace/std/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/testsupport.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/testsupport.py Tue Jun 17 17:30:14 2003 @@ -43,7 +43,8 @@ import pypy.interpreter.unittest_w from pypy.interpreter.testtools import * -TestCase = pypy.interpreter.unittest_w.TestCase_w +TestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase main = unittest.main if __name__ == '__main__': Modified: pypy/trunk/src/pypy/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/testsupport.py (original) +++ pypy/trunk/src/pypy/testsupport.py Tue Jun 17 17:30:14 2003 @@ -43,7 +43,8 @@ import pypy.interpreter.unittest_w from pypy.interpreter.testtools import * -TestCase = pypy.interpreter.unittest_w.TestCase_w +TestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase main = unittest.main if __name__ == '__main__': From mwh at codespeak.net Tue Jun 17 17:30:55 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 17:30:55 +0200 (MEST) Subject: [pypy-svn] rev 822 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030617153055.CA28F5C040@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 17:30:55 2003 New Revision: 822 Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Log: convert some tests to app-space tests (to prove it works :-) Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Tue Jun 17 17:30:55 2003 @@ -35,33 +35,6 @@ def setUp(self): self.space = testsupport.objspace() - def test_trivial(self): - x = self.codetest(''' -def g(): return 42''', 'g', []) - self.assertEquals(x, 42) - - def test_trivial_call(self): - x = self.codetest(''' -def f(): return 42 -def g(): return f()''', 'g', []) - self.assertEquals(x, 42) - - def test_trivial_call2(self): - x = self.codetest(''' -def f(): return 1 + 1 -def g(): return f()''', 'g', []) - self.assertEquals(x, 2) - - def test_print(self): - x = self.codetest(''' -def g(): print 10''', 'g', []) - self.assertEquals(x, None) - - def test_identity(self): - x = self.codetest(''' -def g(x): return x''', 'g', [666]) - self.assertEquals(x, 666) - def test_exception_trivial(self): x = self.codetest(''' def f(): @@ -96,12 +69,12 @@ self.assertEquals(self.codetest(code, 'f', [0]), -12) self.assertEquals(self.codetest(code, 'f', [1]), 1) - def test_raise(self): - x = self.codetest(''' -def f(): - raise 1 -''', 'f', []) - self.assertEquals(x, '<<>>') +## def test_raise(self): +## x = self.codetest(''' +## def f(): +## raise 1 +## ''', 'f', []) +## self.assertEquals(x, '<<>>') def test_except2(self): x = self.codetest(''' @@ -168,6 +141,63 @@ self.assertEquals(self.codetest(code, 'f', [9]), 1+2+3 + 5+6+7+8+900) +class AppTestInterpreter(testsupport.AppTestCase): + def test_exception(self): + try: + raise Exception, 1 + except Exception, e: + self.assertEquals(e.args[0], 1) + + def test_trivial(self): + x = 42 + self.assertEquals(x, 42) + + def test_raise(self): + def f(): + raise Exception + self.assertRaises(Exception, f) + + def test_exception(self): + try: + raise Exception + self.fail("exception failed to raise") + except: + pass + else: + self.fail("exception executing else clause!") + + def test_raise2(self): + def f(r): + try: + raise r + except LookupError: + return 1 + self.assertRaises(Exception, f, Exception) + self.assertEquals(f(IndexError), 1) + + def test_raise3(self): + try: + raise 1 + except TypeError: + pass + else: + self.fail("shouldn't be able to raise 1") + + def test_trivial_call(self): + def f(): return 42 + self.assertEquals(f(), 42) + + def test_trivial_call2(self): + def f(): return 1 + 1 + self.assertEquals(f(), 2) + + def test_print(self): + print 10 + + def test_identity(self): + def f(x): return x + self.assertEquals(f(666), 666) + if __name__ == '__main__': testsupport.main() From mwh at codespeak.net Tue Jun 17 18:35:41 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 18:35:41 +0200 (MEST) Subject: [pypy-svn] rev 823 - in pypy/trunk/src/pypy: . appspace/test interpreterinterpreter/test module/test objspace/std/test Message-ID: <20030617163541.8175F5C05A@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 18:35:40 2003 New Revision: 823 Modified: pypy/trunk/src/pypy/appspace/test/testsupport.py pypy/trunk/src/pypy/interpreter/test/testsupport.py pypy/trunk/src/pypy/interpreter/testsupport.py pypy/trunk/src/pypy/module/test/testsupport.py pypy/trunk/src/pypy/objspace/std/test/testsupport.py pypy/trunk/src/pypy/testsupport.py Log: holger pointed out that the call to get_tests_for_dir wasn't quite right Modified: pypy/trunk/src/pypy/appspace/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/testsupport.py (original) +++ pypy/trunk/src/pypy/appspace/test/testsupport.py Tue Jun 17 18:35:40 2003 @@ -49,4 +49,4 @@ if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(this_path)) Modified: pypy/trunk/src/pypy/interpreter/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/testsupport.py (original) +++ pypy/trunk/src/pypy/interpreter/test/testsupport.py Tue Jun 17 18:35:40 2003 @@ -49,4 +49,4 @@ if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(this_path)) Modified: pypy/trunk/src/pypy/interpreter/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/testsupport.py (original) +++ pypy/trunk/src/pypy/interpreter/testsupport.py Tue Jun 17 18:35:40 2003 @@ -49,4 +49,4 @@ if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(this_path)) Modified: pypy/trunk/src/pypy/module/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/module/test/testsupport.py (original) +++ pypy/trunk/src/pypy/module/test/testsupport.py Tue Jun 17 18:35:40 2003 @@ -49,4 +49,4 @@ if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(this_path)) Modified: pypy/trunk/src/pypy/objspace/std/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/testsupport.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/testsupport.py Tue Jun 17 18:35:40 2003 @@ -49,4 +49,4 @@ if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(this_path)) Modified: pypy/trunk/src/pypy/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/testsupport.py (original) +++ pypy/trunk/src/pypy/testsupport.py Tue Jun 17 18:35:40 2003 @@ -49,4 +49,4 @@ if __name__ == '__main__': runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(os.path.dirname(sys.argv[0]))) + runner.run(get_tests_for_dir(this_path)) From mwh at codespeak.net Tue Jun 17 18:36:26 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 17 Jun 2003 18:36:26 +0200 (MEST) Subject: [pypy-svn] rev 824 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030617163626.0EA845C0D2@thoth.codespeak.net> Author: mwh Date: Tue Jun 17 18:36:25 2003 New Revision: 824 Modified: pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py Log: i wonder how long this has been broken? Modified: pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py Tue Jun 17 18:36:25 2003 @@ -1,5 +1,5 @@ import unittest -import support +import testsupport from pypy.interpreter.pyframe_app import decode_frame_arguments class CodeObject: From hpk at codespeak.net Tue Jun 17 20:17:28 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 17 Jun 2003 20:17:28 +0200 (MEST) Subject: [pypy-svn] rev 825 - pypy/trunk/src/pypy/test Message-ID: <20030617181728.A8AB35C0E2@thoth.codespeak.net> Author: hpk Date: Tue Jun 17 20:17:27 2003 New Revision: 825 Added: pypy/trunk/src/pypy/test/ Log: added a new directory "test" which will contain all centrally important test files. The idea is to be able to say python test/all.py instead of dropping random .py files into our pypy root. before i make the "real" checkin of the test-cleanup i'll post on pypy-dev ... From lac at codespeak.net Tue Jun 17 20:50:33 2003 From: lac at codespeak.net (lac at codespeak.net) Date: Tue, 17 Jun 2003 20:50:33 +0200 (MEST) Subject: [pypy-svn] rev 826 - pypy/trunk/doc Message-ID: <20030617185033.34B9C5C11C@thoth.codespeak.net> Author: lac Date: Tue Jun 17 20:50:32 2003 New Revision: 826 Added: pypy/trunk/doc/oscon2003-paper.txt Modified: pypy/trunk/doc/builtins.txt Log: Holger had a better idea. Put the OSCON paper here. Modified: pypy/trunk/doc/builtins.txt ============================================================================== --- pypy/trunk/doc/builtins.txt (original) +++ pypy/trunk/doc/builtins.txt Tue Jun 17 20:50:32 2003 @@ -132,7 +132,7 @@ deon pow n t property n v quit -- (see exit) -n pi range +d pi range nepn raw_input n pn reduce nhpn reload Added: pypy/trunk/doc/oscon2003-paper.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/oscon2003-paper.txt Tue Jun 17 20:50:32 2003 @@ -0,0 +1,519 @@ +Implementing Python in Python -- A report from the PyPy project + +The PyPython project aims at producing a simple runtime-system for the +Python language, written in Python itself. Sooner or later, this +happens to most interesting computer languages. The temptation is +great. Each significant computer language has a certain +expressiveness and power, and it is frustrating to not be able to use +that expressiveness and power when writing the language itself. Thus +we have Scheme, Lisp-written-in-Lisp, and Squeak, +Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? + +Besides using the expressiveness of Python to write Python, we also +aim to produce a minimal core which is Simple and Flexible, and no +longer dependent on CPython. We will take care that PyPy will integrate +easily with PSYCO and Stackless -- goals that are attainable with both +Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) +on the team. Samuele Pedroni, catches us when we unwittingly make +C-ish assumptions. By keeping things Simple and Flexible we can +produce code that has attractions for both industry and academia. +Academics will find that this Python is even easier to teach concepts +of language design with. And ending the dependence on CPython means +that we can produce a Python with a smaller footprint. Eventually, +we would like to produce a faster Python. We are very far from that +now, since we have spent no effort on speed and have only worked on +Simple and Flexible. + +1. How have we set about it. + +Most of you know what happens if you type + +'import this' + +at your favourite Python prompt. You get 'The Zen of Python', +by Tim Peters. It starts + + Beautiful is better than ugly. + Explicit is better than implicit. + Simple is better than complex. + +and ends with: + + Namespaces are one honking great idea -- let's do more of those! + +What would 'doing more of those' mean? Here is one approach. + + In a Python-like language, a running interpreter has three main parts: + + * the main loop, which suffles data around and calls the operations + defined in the object library according to the bytecode. + + * the compiler, which represents the static optimization of the + source code into an intermediate format, the bytecode; + + * the object library, implementing the various types of objects + and their semantics; + +In PyPy, the three parts are clearly separated and can be replaced +independently. The main loop generally assumes little about the semantics +of the objects: they are essentially black boxes (PyObject pointers). The +interpreter stack and the variables only contain such black boxes. +Every operation is done via calls to the object library, such as +PyNumber_Add(). We haven't done much to make the compiler and the main +lac at ratthing-b246:~/Mail/pypy/paper$ cat paper +Implementing Python in Python -- A report from the PyPy project + +The PyPython project aims at producing a simple runtime-system for the +Python language, written in Python itself. Sooner or later, this +happens to most interesting computer languages. The temptation is +great. Each significant computer language has a certain +expressiveness and power, and it is frustrating to not be able to use +that expressiveness and power when writing the language itself. Thus +we have Scheme, Lisp-written-in-Lisp, and Squeak, +Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? + +Besides using the expressiveness of Python to write Python, we also +aim to produce a minimal core which is Simple and Flexible, and no +longer dependent on CPython. We will take care that PyPy will integrate +easily with PSYCO and Stackless -- goals that are attainable with both +Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) +on the team. Samuele Pedroni, catches us when we unwittingly make +C-ish assumptions. By keeping things Simple and Flexible we can +produce code that has attractions for both industry and academia. +Academics will find that this Python is even easier to teach concepts +of language design with. And ending the dependence on CPython means +that we can produce a Python with a smaller footprint. Eventually, +we would like to produce a faster Python. We are very far from that +now, since we have spent no effort on speed and have only worked on +Simple and Flexible. + +1. How have we set about it. + +Most of you know what happens if you type + +'import this' + +at your favourite Python prompt. You get 'The Zen of Python', +by Tim Peters. It starts + + Beautiful is better than ugly. + Explicit is better than implicit. + Simple is better than complex. + +and ends with: + + Namespaces are one honking great idea -- let's do more of those! + +What would 'doing more of those' mean? Here is one approach. + + In a Python-like language, a running interpreter has three main parts: + + * the main loop, which suffles data around and calls the operations + defined in the object library according to the bytecode. + + * the compiler, which represents the static optimization of the + source code into an intermediate format, the bytecode; + + * the object library, implementing the various types of objects + and their semantics; + +In PyPy, the three parts are clearly separated and can be replaced +independently. The main loop generally assumes little about the semantics +of the objects: they are essentially black boxes (PyObject pointers). The +interpreter stack and the variables only contain such black boxes. +Every operation is done via calls to the object library, such as +PyNumber_Add(). We haven't done much to make the compiler and the main +loop into explicit concepts (yet), because we have been concentrating +on making seprable object libraries. + +We call the separable object library, an Object Space. +We call Wrapped Objects the black boxes of an Object Space. + +But the exciting thing is that while existing languages implement _one_ +Object Space, by separating things we have produced an architecture +which will enable us to run more than one Object Space in the same +interpreter at the same time. This idea has some exciting implications. + +So let us dream for a bit. + +First dream: How do you get computer science concepts in language design +more effectively into student brains? + +Traditionally, academics come up with interesting new ideas and +concepts, but, to the extent that they are truly new end up creating +another language to express these ideas in. Unfortunately, many +languages end up merely as a vehicle for too few new ideas. We end up +force-feeding our poor students with too many computer languages, too +quickly -- each language designed to teach a particular point. And +many of our languages are particularly weak on everything _but_ the +point we wish to make. + +Things would go a lot more smoothly if we could only create an Object +Space which obeys the new rules we have thought up, and drop it into +an existing language. Comparisons between other ways of doing things +would also be a lot simpler. Finally, we could reasonably ask our +students to implement these ideas in Python and let them drop them in, +leaving all the other bits, irrelevant for our educational purposes as +they already are written. There is no better way to learn about +compiler writing, than writing compilers, but a lot of todays +education in compiler writing leaves a huge gap between 'the theory +that is in the book which the student is expected to learn' and 'what +is reasonable for a student to implement as coursework'. Students can +spend all semester overcoming difficulties in _actually getting the IO +to work_, and _interfacing with the runtime libraries_, while only +spending a fraction of the time on the concepts which you are trying +to teach. + +Object Spaces will provide a better fit between the the abstract +concepts we wish to teach and the code written to implement just that. + +Dream number Two: A Slimmer Python + +People who write code for handhelds and other embed Python into other +devices often wish that they could have a much smaller footprint. Now +they can ask for a Tiny Object Space which only implements the +behaviour which they need, and skips the parts that they do not. + +Dream number Three -- What is the best way to implement a dict? + +This depends on how much data you intend to store in your dict. If you +never expect your dict to have more than a half dozen items, a really +fast list may be best. Larger dicts might best be implemented as +hashes. And for storing enormous amounts of data, a binary tree +might be just what you would be interested in. In principal, there is +nothing to stop your interpreter from keeping statistics on how it is +being used, and to move from strategy to strategy at runtime. + +Dream number Four -- How would you like your operators to work today? + +Consider y = int(x). How would you like this to work when x is 4.2, +4.5, -4.2 and -4.5? Currently Python says 4, 4, -4 and -4, truncating +towards zero. But for certain applications, this is not what is desired. +You would prefer round behaviour 4, 5, -4 -5 -- rounding away from zero. +Or you would like to always return the larger integer 5 5 -4 -4. Sometimes +just running an existing program and changing such behaviour can reveal +interesting embedded assumptions of which the author may be unaware. + +Changing the behaviour and seeing how the results change ought to be +straight-forward, simple, and easy. + +Dream number Five -- Running different Object Spaces on different processors +of the same machine. + +Dream number Six -- Running different Object Spaces on different machines. + +This is one of the unrealised dreams of distributed computing. It would +often be convenient to allow the various machines on a network to share +cpu resources. Thus one could begin a computation on a small device, +say a mobile phone, or a PDA, and have the program automatically notice +that the computation was too strenuous for such a divice, and automatically +forward the computation to a machine with more computational power. + +Dream number Seven -- A Smarter, more Dynamic Interpreter + +There is no reason why your Python interpreter could not keep statistics +of how it is being used, and automatically select from a collection of +algorithms the one which is best suited for the data at hand. + +Dream number Eight -- How to avoid painful conversion of your code base +to new versions of the language. + +This dream is a bit far-fetched, but it is worth investigating. Right +now, whenever a new release of Python comes out, existing Python +programs have to be modified whenever there are conflicts. Thus there +is a trade off between getting the new features which contribute to +increased productivity in program design, and having to fix piles of +old code that wasn't broken until the language changed. With this +approach it may be possible to save your cake and eat it too. You +could demand that all your old modules use PyPy Object Space Nov 16 +2004, while immediately have your new modules use the brand new PyPy +Object Space which was defined yesterday. You could update any old +modules that would particularily benefit from having the new features, +and leave the old ones alone. + +Dream number Nine: faster Python + +While we are writing an adaptive, smarter compiler, we ought to be able +to make it faster. We think faster than C Python is a realistic goal, +eventually. When faster algorithms are discovered, we will be able to +quickly place them in the interpreter, because the components are +more or less independent. This is something that Armin Rigo +and Christian Tismer know a lot about, and I know very little. + +Dream number Ten: world domination and .... +(Well, if we can pull off Dreams 1-9, this should just drop out of the +design...) + +And if we don't pull this off, we will have at least learned a lot. This +in itself makes the project worth doing. Plus it's fun... + +But away from the dreams and back to what do we currently have? + +We currently implement (or partially implement) two Object Spaces, and +have plans to implement a third in short order. + +1. The Trivial Object Space + +A PyPy interpreter using the TrivialObjectSpace is an interpreter with +its own main loop (written in Python), and nothing else. This main +loop manipulates real Python objects and all operations are done +directly on the Python objects. For example, "1" really means "1" and +when the interpreter encounters the BINARY_ADD bytecode instructions +the TrivialObjectSpace will just add two real Python objects together +using Python's "+". The same for lists, dictionaries, classes... We +just use Python's own. + +This Object Space is only useful for testing the concept of Object Spaces, +and our interpreter, or even interpreting different kinds of bytecodes. +This is already done; it is funny to watch "dis.dis" disassembling itself +painfully slowly. + +Getting this to work was a goal of the Hildesheim Sprint February 16-23. +It demonstrated that our Object Space Concept was viable, and that our +interpreter worked. + +2. The Standard Object Space + +The Standard Object Space is the object space that works just like +Python's, that is, the object space whose black boxes are real Python +objects that work as expected. This is where the bulk of the work in +PyPy has been done to date. Getting the Standard Object Space to +work was a goal of the Gothenburg Sprint May 24 - 31. + +Specifically we needed to get this code: + +aStr = 'hello world' +print len(aStr) + +to run. We needed types and builtins to work. This ran, slowly. + +Then we added strings. Getting this code to work was the second +goal. + +### a trivial program to test strings, lists, functions and methods ### + +def addstr(s1,s2): + return s1 + s2 + +str = "an interesting string" +str2 = 'another::string::xxx::y:aa' +str3 = addstr(str,str2) +arr = [] +for word in str.split(): + if word in str2.split('::'): + arr.append(word) +print ''.join(arr) +print "str + str2 = ", str3 + +This we accomplished by mid-week. + +By the end of the Sprint we produced our first Python program that +ran under PyPy which simply 'did something we wanted to do' and wasn't +an artificial goal. Specifically, it calculated the share in foodbill +for each of the 9 Sprint participants. + +lips=[(1, 'Kals MatMarkn', 6150, 'Chutney for Curry', 'dinner Saturday'), + (2, 'Kals MatMarkn', 32000, 'Spaghetti, Beer', 'dinner Monday'), + (2, 'Kals MatMarkn', -810, 'Deposit on Beer Bottles', 'various'), + (3, 'Fram', 7700, 'Rice and Curry Spice', 'dinner Saturday'), + (4, 'Kals MatMarkn', 25000, 'Alcohol-Free Beer, sundries', 'various'), + (4, 'Kals MatMarkn', -1570, "Michael's toothpaste", 'none'), + (4, 'Kals MatMarkn', -1690, "Laura's toothpaste", 'none'), + (4, 'Kals MatMarkn', -720, 'Deposit on Beer Bottles', 'various'), + (4, 'Kals MatMarkn', -60, 'Deposit on another Beer Bottle', 'various'), + (5, 'Kals MatMarkn', 26750, 'lunch bread meat cheese', 'lunch Monday'), + (6, 'Kals MatMarkn', 15950, 'various', 'dinner Tuesday and Thursday'), + (7, 'Kals MatMarkn', 3650, 'Drottningsylt, etc.', 'dinner Thursday'), + (8, 'Kals MatMarkn', 26150, 'Chicken and Mushroom Sauce', 'dinner Wed'), (8, 'Kals MatMarkn', -2490, 'Jacob and Laura -- juice', 'dinner Wed'), + (8, 'Kals MatMarkn', -2990, "Chicken we didn't cook", 'dinner Wednesday'), + (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), + (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), + (10, 'Kals MatMarkn', 26900, 'Jansons Frestelse', 'dinner Sunday'), + (10, 'Kals MatMarkn', -540, 'Deposit on Beer Bottles', 'dinner Sunday'), (11, 'Kals MatMarkn', 22650, 'lunch bread meat cheese', 'lunch Thursday'), + (11, 'Kals MatMarkn', -2190, 'Jacob and Laura -- juice', 'lunch Thursday'), + (11, 'Kals MatMarkn', -2790, 'Jacob and Laura -- cereal', 'lunch Thurs'), (11, 'Kals MatMarkn', -760, 'Jacob and Laura -- milk', 'lunch Thursday'), (12, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'lunch Friday'), (13, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Sun'), + (14, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Tues'), + (15, 'Kals MatMarkn', 20000, 'lunch bread meat cheese', 'guestimate Wed'), + (16, 'Kals MatMarkn', 42050, 'grillfest', 'dinner Friday'), + (16, 'Kals MatMarkn', -1350, 'Deposit on Beer Bottles', 'dinner Friday'), (17, 'System Bolaget', 15500, 'Cederlunds Caloric', 'dinner Thursday'), + (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), (17, 'System Bolaget', 13800, '2 x Jacobs Creek 69SEK', 'various'), + (18, 'J and Ls winecabinet', 10800, '2 x Parrotes 54SEK', 'various'), + (18, 'J and Ls winecabinet', 14700, '3 x Saint Paulin 49SEK', 'various'), (18, 'J and Ls winecabinet', 10400, '2 x Farnese Sangioves 52SEK', + 'cheaper when we bought it'), + (18, 'J and Ls winecabinet', 17800, '2 x Le Poiane 89SEK', 'various'), + (18, 'J and Ls winecabinet', 9800, '2 x Something Else 49SEK', 'various'), + (19, 'Konsum', 26000, 'Saturday Bread and Fruit', 'Slip MISSING'), + (20, 'Konsum', 15245, 'Mooseburgers', 'found slip'), + (21, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), + (22, 'J and Ls freezer', 21000, 'Meat for Curry, grilling', ''), + (22, 'J and Ls cupboard', 3000, 'Rice', ''), + (22, 'J and Ls cupboard', 4000, 'Charcoal', ''), + (23, 'Fram', 2975, 'Potatoes', '3.5 kg @ 8.50SEK'), + (23, 'Fram', 1421, 'Peas', 'Thursday dinner'), + (24, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), + (24, 'Kals MatMarkn', -2990, 'TP', 'None'), + (24, 'Kals MatMarkn', -2320, 'T-Gul', 'None') + ] + +print [t[2] for t in slips] +print (reduce(lambda x, y: x+y, [t[2] for t in slips], 0))/900 + +Pypy said: 603. Dinner for a week cost 603 Swedish Krona -- or approximately +50$ US. So if we can't have world domination, or get our Object Space +to work, a new career in Sprint cost control beckons. :-) + +3. The Translate Object Space + +The Translate Object Space is the next goal. It is an example of an +ObjectSpace that differs a lot from StandardObjectSpace. We have to +translate the Python code we have into C code. This is the sine qua +non condition for our work to be actually usable. Quite unexpectedly, +the major piece of the translator is itself an object space, the +TranslateObjectSpace. Its goal is to run any Python code and produce C +code in the background as it does so. + +Specifically, we take our PyPy interpreter with the Translate Object +Space instead of the Standard Object Space, and run that, asking it to +interpret our generated bytecode. A wrapped object is now the name of +a variable in the C program we are emitting, for example: + + The add method in the Translate Object Space takes two variable +names, x and y, and emits the C code z = x + y; where z is a new variable +name which is returned as the result of add. (We will actually need to +make the wrapped objects a bit more elaborate so that we can also record, +besides the C variable name, its basic type). + +At the time of this writing, it is not clear whether this is too +ambitious a goal for the Third Sprint, held in Louvain-la-Neuve, +Belgium (near Brussels), June 21 - 24 . + +------------ + +More details on how we actually do this stuff. + +A crucial concept is Multimethods (yanked from the wiki) + +Interpreter-level classes correspond to implementations of +application-level types. The hierarchy among the classes used for the +implementations is convenient for implementation purposes. It is not +related to any application-level type hierarchy. + +Dispatch + +Multimethods dispatch by looking in a set of registered +functions. Each registered function has a signature, which defines +which object implementation classes are accepted at the corresponding +argument position. + +The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly +'object' later). As it accepts anything, it is the only way to +guarantee that the registered function will be called with exactly the +same object as was passed originally. ATTENTION: in all other cases +the argument received by the function may have been converted in some +way. It must thus not be considered to be 'id'entical to the original +argument. For example it should not be stored in a data structure, nor +be queried for type, nor be used for another multimethod dispatch -- +the only thing you should do is read and write its internal data. + +For example, 'getattr(obj, attr)' is implemented with a W_StringObject +second argument when all it needs is just the name of the attr, and +with a W_ANY when the 'attr' object could be used as a key in +obj.__dict__. + +Delegation + +Delegation is a transparent convertion mechanism between object +implementations. The convertion can give a result of a different type +(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> +str). There is a global table of delegators. We should not rely on the +delegators to be tried in any particlar order, or at all (e.g. the int +-> float delegator could be ignored when we know that no registered +function will accept a float anyway). + +Delegation is also used to emulate inheritance between built-in types +(e.g. bool -> int). This is done by delegation because there is no +reason that a particular implementation of a sub-type can be trivially +typecast to some other particular implementation of the parent type; +the process might require some work. + +Types + +Types are implemented by the class W_TypeObject. This is where +inheritance and the Method Resolution Order are defined, and where +attribute look-ups are done. + +Instances of user-defined types are implementated as W_UserObjects. A +user-defined type can inherit from built-in types (maybe more than +one, although this is incompatible with CPython). The W_UserObject +delegator converts the object into any of these "parent objects" if +needed. This is how user-defined types appear to inherit all built-in +operator implementations. + +Delegators should be able to invoke user code; this would let us +implement special methods like __int__() by calling them within a +W_UserObject -> int delegator. + +Specifics of multimethods + +Multimethods dispatch more-specific-first, left-to-right (i.e. if +there is an exact match for the first argument it will always be tried +first). + +Delegators are automatically chained (i.e. A -> B and B -> C would be +combined to allow for A -> C delegation). + +Delegators do not publish the class of the converted object in +advance, so that the W_UserObject delegator can potentially produce +any other built-in implementation. This means chaining and chain loop +detection cannot be done statically (at least without help from an +analysis tool like the translator-to-C). To break loops, we can assume +(unless a particular need arises) that delegators are looping when +they return an object of an already-seen class. + +Registration + +The register() method of multimethods adds a function to its database +of functions, with the given signature. A function that raises +FailedToImplement causes the next match to be tried. + +'delegate' is the special unary multimethod that should try to convert +its argument to something else. For greater control, it can also +return a list of 2-tuples (class, object), or an empty list for +failure to convert the argument to anything. All delegators will +potentially be tried, and recursively on each other's results to do +chaining. + +A priority ordering between delegators is used. See objspace.PRIORITY_*. + +Translation + +The code in multimethod.py is not supposed to be read by the +translator-to-C. Special optimized code will be generated instead +(typically some kind of precomputed dispatch tables). + +Delegation is special-cased too. Most delegators will be found to +return an object of a statically known class, which means that most of +the chaining and loop detection can be done in advance. + +Multimethod slicing + +Multimethods are visible to user code as (bound or unbound) methods +defined for the corresponding types. (At some point built-in functions +like len() and the operator.xxx() should really directly map to the +multimethods themselves, too.) + +To build a method from a multimethod (e.g. as in 'l.append' or +'int.__add__'), the result is actually a "slice" of the whole +multimethod, i.e. a sub-multimethod in which the registration table +has been trimmed down. (Delegation mechanisms are not restricted for +sliced multimethods.) + +Say that C is the class the new method is attached to (in the above +examples, respectively, C=type(l) and C=int). The restriction is based +on the registered class of the first argument ('self' for the new +method) in the signature. If this class corresponds to a fixed type +(as advertized by 'statictype'), and this fixed type is C or a +superclass of C, then we keep it. + +Some multimethods can also be sliced along their second argument, +e.g. for __radd__(). From hpk at codespeak.net Tue Jun 17 23:41:09 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 17 Jun 2003 23:41:09 +0200 (MEST) Subject: [pypy-svn] rev 827 - pypy/trunk/src/pypy/interpreter Message-ID: <20030617214109.615F15C044@thoth.codespeak.net> Author: hpk Date: Tue Jun 17 23:41:09 2003 New Revision: 827 Modified: pypy/trunk/src/pypy/interpreter/opcode.py Log: issue the opcode-warning via a call to warnings.warn because otherwise i get spammed when using my XPython :-) Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Tue Jun 17 23:41:09 2003 @@ -702,7 +702,8 @@ if opname in globals(): fn = globals()[opname] elif not opname.startswith('<') and i>0: - print "* Warning, missing opcode %s" % opname + import warnings + warnings.warn("* Warning, missing opcode %s" % opname) dispatch_table.append(fn) From hpk at codespeak.net Wed Jun 18 00:05:00 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 18 Jun 2003 00:05:00 +0200 (MEST) Subject: [pypy-svn] rev 828 - in pypy/trunk/src/pypy/objspace: . std Message-ID: <20030617220500.7F36F5C040@thoth.codespeak.net> Author: hpk Date: Wed Jun 18 00:04:59 2003 New Revision: 828 Modified: pypy/trunk/src/pypy/objspace/std/__init__.py pypy/trunk/src/pypy/objspace/trivial.py Log: added aliases so that you can uniformely import like this from pypy.objspace.std import Space from pypy.objspace.trivial import Space and instantiate 'Space'. Seems nicer to me than those ugly long CamelCaseNames. If people don't like this we can back it out. Modified: pypy/trunk/src/pypy/objspace/std/__init__.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/__init__.py (original) +++ pypy/trunk/src/pypy/objspace/std/__init__.py Wed Jun 18 00:04:59 2003 @@ -1 +1,2 @@ from objspace import StdObjSpace +Space = StdObjSpace Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Wed Jun 18 00:04:59 2003 @@ -344,3 +344,5 @@ for m in ObjSpace.MethodTable: if not hasattr(TrivialObjSpace, m[0]): print m[0] + +Space = TrivialObjSpace From ale at codespeak.net Wed Jun 18 00:15:48 2003 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 18 Jun 2003 00:15:48 +0200 (MEST) Subject: [pypy-svn] rev 829 - pypy/trunk/doc Message-ID: <20030617221548.9349E5A550@thoth.codespeak.net> Author: ale Date: Wed Jun 18 00:15:48 2003 New Revision: 829 Modified: pypy/trunk/doc/oscon2003-paper.txt Log: I've fixed some spelling errors and the beginning was in twice. I havent finished reading the whole paper yet (just trying to see if I can commit changes) Modified: pypy/trunk/doc/oscon2003-paper.txt ============================================================================== --- pypy/trunk/doc/oscon2003-paper.txt (original) +++ pypy/trunk/doc/oscon2003-paper.txt Wed Jun 18 00:15:48 2003 @@ -1,519 +1,464 @@ -Implementing Python in Python -- A report from the PyPy project - -The PyPython project aims at producing a simple runtime-system for the -Python language, written in Python itself. Sooner or later, this -happens to most interesting computer languages. The temptation is -great. Each significant computer language has a certain -expressiveness and power, and it is frustrating to not be able to use -that expressiveness and power when writing the language itself. Thus -we have Scheme, Lisp-written-in-Lisp, and Squeak, -Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? - -Besides using the expressiveness of Python to write Python, we also -aim to produce a minimal core which is Simple and Flexible, and no -longer dependent on CPython. We will take care that PyPy will integrate -easily with PSYCO and Stackless -- goals that are attainable with both -Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) -on the team. Samuele Pedroni, catches us when we unwittingly make -C-ish assumptions. By keeping things Simple and Flexible we can -produce code that has attractions for both industry and academia. -Academics will find that this Python is even easier to teach concepts -of language design with. And ending the dependence on CPython means -that we can produce a Python with a smaller footprint. Eventually, -we would like to produce a faster Python. We are very far from that -now, since we have spent no effort on speed and have only worked on -Simple and Flexible. - -1. How have we set about it. - -Most of you know what happens if you type - -'import this' - -at your favourite Python prompt. You get 'The Zen of Python', -by Tim Peters. It starts - - Beautiful is better than ugly. - Explicit is better than implicit. - Simple is better than complex. - -and ends with: - - Namespaces are one honking great idea -- let's do more of those! - -What would 'doing more of those' mean? Here is one approach. - - In a Python-like language, a running interpreter has three main parts: - - * the main loop, which suffles data around and calls the operations - defined in the object library according to the bytecode. - - * the compiler, which represents the static optimization of the - source code into an intermediate format, the bytecode; - - * the object library, implementing the various types of objects - and their semantics; - -In PyPy, the three parts are clearly separated and can be replaced -independently. The main loop generally assumes little about the semantics -of the objects: they are essentially black boxes (PyObject pointers). The -interpreter stack and the variables only contain such black boxes. -Every operation is done via calls to the object library, such as -PyNumber_Add(). We haven't done much to make the compiler and the main -lac at ratthing-b246:~/Mail/pypy/paper$ cat paper -Implementing Python in Python -- A report from the PyPy project - -The PyPython project aims at producing a simple runtime-system for the -Python language, written in Python itself. Sooner or later, this -happens to most interesting computer languages. The temptation is -great. Each significant computer language has a certain -expressiveness and power, and it is frustrating to not be able to use -that expressiveness and power when writing the language itself. Thus -we have Scheme, Lisp-written-in-Lisp, and Squeak, -Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? - -Besides using the expressiveness of Python to write Python, we also -aim to produce a minimal core which is Simple and Flexible, and no -longer dependent on CPython. We will take care that PyPy will integrate -easily with PSYCO and Stackless -- goals that are attainable with both -Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) -on the team. Samuele Pedroni, catches us when we unwittingly make -C-ish assumptions. By keeping things Simple and Flexible we can -produce code that has attractions for both industry and academia. -Academics will find that this Python is even easier to teach concepts -of language design with. And ending the dependence on CPython means -that we can produce a Python with a smaller footprint. Eventually, -we would like to produce a faster Python. We are very far from that -now, since we have spent no effort on speed and have only worked on -Simple and Flexible. - -1. How have we set about it. - -Most of you know what happens if you type - -'import this' - -at your favourite Python prompt. You get 'The Zen of Python', -by Tim Peters. It starts - - Beautiful is better than ugly. - Explicit is better than implicit. - Simple is better than complex. - -and ends with: - - Namespaces are one honking great idea -- let's do more of those! - -What would 'doing more of those' mean? Here is one approach. - - In a Python-like language, a running interpreter has three main parts: - - * the main loop, which suffles data around and calls the operations - defined in the object library according to the bytecode. - - * the compiler, which represents the static optimization of the - source code into an intermediate format, the bytecode; - - * the object library, implementing the various types of objects - and their semantics; - -In PyPy, the three parts are clearly separated and can be replaced -independently. The main loop generally assumes little about the semantics -of the objects: they are essentially black boxes (PyObject pointers). The -interpreter stack and the variables only contain such black boxes. -Every operation is done via calls to the object library, such as -PyNumber_Add(). We haven't done much to make the compiler and the main -loop into explicit concepts (yet), because we have been concentrating -on making seprable object libraries. - -We call the separable object library, an Object Space. -We call Wrapped Objects the black boxes of an Object Space. - -But the exciting thing is that while existing languages implement _one_ -Object Space, by separating things we have produced an architecture -which will enable us to run more than one Object Space in the same -interpreter at the same time. This idea has some exciting implications. - -So let us dream for a bit. - -First dream: How do you get computer science concepts in language design -more effectively into student brains? - -Traditionally, academics come up with interesting new ideas and -concepts, but, to the extent that they are truly new end up creating -another language to express these ideas in. Unfortunately, many -languages end up merely as a vehicle for too few new ideas. We end up -force-feeding our poor students with too many computer languages, too -quickly -- each language designed to teach a particular point. And -many of our languages are particularly weak on everything _but_ the -point we wish to make. - -Things would go a lot more smoothly if we could only create an Object -Space which obeys the new rules we have thought up, and drop it into -an existing language. Comparisons between other ways of doing things -would also be a lot simpler. Finally, we could reasonably ask our -students to implement these ideas in Python and let them drop them in, -leaving all the other bits, irrelevant for our educational purposes as -they already are written. There is no better way to learn about -compiler writing, than writing compilers, but a lot of todays -education in compiler writing leaves a huge gap between 'the theory -that is in the book which the student is expected to learn' and 'what -is reasonable for a student to implement as coursework'. Students can -spend all semester overcoming difficulties in _actually getting the IO -to work_, and _interfacing with the runtime libraries_, while only -spending a fraction of the time on the concepts which you are trying -to teach. - -Object Spaces will provide a better fit between the the abstract -concepts we wish to teach and the code written to implement just that. - -Dream number Two: A Slimmer Python - -People who write code for handhelds and other embed Python into other -devices often wish that they could have a much smaller footprint. Now -they can ask for a Tiny Object Space which only implements the -behaviour which they need, and skips the parts that they do not. - -Dream number Three -- What is the best way to implement a dict? - -This depends on how much data you intend to store in your dict. If you -never expect your dict to have more than a half dozen items, a really -fast list may be best. Larger dicts might best be implemented as -hashes. And for storing enormous amounts of data, a binary tree -might be just what you would be interested in. In principal, there is -nothing to stop your interpreter from keeping statistics on how it is -being used, and to move from strategy to strategy at runtime. - -Dream number Four -- How would you like your operators to work today? - -Consider y = int(x). How would you like this to work when x is 4.2, -4.5, -4.2 and -4.5? Currently Python says 4, 4, -4 and -4, truncating -towards zero. But for certain applications, this is not what is desired. -You would prefer round behaviour 4, 5, -4 -5 -- rounding away from zero. -Or you would like to always return the larger integer 5 5 -4 -4. Sometimes -just running an existing program and changing such behaviour can reveal -interesting embedded assumptions of which the author may be unaware. - -Changing the behaviour and seeing how the results change ought to be -straight-forward, simple, and easy. - -Dream number Five -- Running different Object Spaces on different processors -of the same machine. - -Dream number Six -- Running different Object Spaces on different machines. - -This is one of the unrealised dreams of distributed computing. It would -often be convenient to allow the various machines on a network to share -cpu resources. Thus one could begin a computation on a small device, -say a mobile phone, or a PDA, and have the program automatically notice -that the computation was too strenuous for such a divice, and automatically -forward the computation to a machine with more computational power. - -Dream number Seven -- A Smarter, more Dynamic Interpreter - -There is no reason why your Python interpreter could not keep statistics -of how it is being used, and automatically select from a collection of -algorithms the one which is best suited for the data at hand. - -Dream number Eight -- How to avoid painful conversion of your code base -to new versions of the language. - -This dream is a bit far-fetched, but it is worth investigating. Right -now, whenever a new release of Python comes out, existing Python -programs have to be modified whenever there are conflicts. Thus there -is a trade off between getting the new features which contribute to -increased productivity in program design, and having to fix piles of -old code that wasn't broken until the language changed. With this -approach it may be possible to save your cake and eat it too. You -could demand that all your old modules use PyPy Object Space Nov 16 -2004, while immediately have your new modules use the brand new PyPy -Object Space which was defined yesterday. You could update any old -modules that would particularily benefit from having the new features, -and leave the old ones alone. - -Dream number Nine: faster Python - -While we are writing an adaptive, smarter compiler, we ought to be able -to make it faster. We think faster than C Python is a realistic goal, -eventually. When faster algorithms are discovered, we will be able to -quickly place them in the interpreter, because the components are -more or less independent. This is something that Armin Rigo -and Christian Tismer know a lot about, and I know very little. - -Dream number Ten: world domination and .... -(Well, if we can pull off Dreams 1-9, this should just drop out of the -design...) - -And if we don't pull this off, we will have at least learned a lot. This -in itself makes the project worth doing. Plus it's fun... - -But away from the dreams and back to what do we currently have? - -We currently implement (or partially implement) two Object Spaces, and -have plans to implement a third in short order. - -1. The Trivial Object Space - -A PyPy interpreter using the TrivialObjectSpace is an interpreter with -its own main loop (written in Python), and nothing else. This main -loop manipulates real Python objects and all operations are done -directly on the Python objects. For example, "1" really means "1" and -when the interpreter encounters the BINARY_ADD bytecode instructions -the TrivialObjectSpace will just add two real Python objects together -using Python's "+". The same for lists, dictionaries, classes... We -just use Python's own. - -This Object Space is only useful for testing the concept of Object Spaces, -and our interpreter, or even interpreting different kinds of bytecodes. -This is already done; it is funny to watch "dis.dis" disassembling itself -painfully slowly. - -Getting this to work was a goal of the Hildesheim Sprint February 16-23. -It demonstrated that our Object Space Concept was viable, and that our -interpreter worked. - -2. The Standard Object Space - -The Standard Object Space is the object space that works just like -Python's, that is, the object space whose black boxes are real Python -objects that work as expected. This is where the bulk of the work in -PyPy has been done to date. Getting the Standard Object Space to -work was a goal of the Gothenburg Sprint May 24 - 31. - -Specifically we needed to get this code: - -aStr = 'hello world' -print len(aStr) - -to run. We needed types and builtins to work. This ran, slowly. - -Then we added strings. Getting this code to work was the second -goal. - -### a trivial program to test strings, lists, functions and methods ### - -def addstr(s1,s2): - return s1 + s2 - -str = "an interesting string" -str2 = 'another::string::xxx::y:aa' -str3 = addstr(str,str2) -arr = [] -for word in str.split(): - if word in str2.split('::'): - arr.append(word) -print ''.join(arr) -print "str + str2 = ", str3 - -This we accomplished by mid-week. - -By the end of the Sprint we produced our first Python program that -ran under PyPy which simply 'did something we wanted to do' and wasn't -an artificial goal. Specifically, it calculated the share in foodbill -for each of the 9 Sprint participants. - -lips=[(1, 'Kals MatMarkn', 6150, 'Chutney for Curry', 'dinner Saturday'), - (2, 'Kals MatMarkn', 32000, 'Spaghetti, Beer', 'dinner Monday'), - (2, 'Kals MatMarkn', -810, 'Deposit on Beer Bottles', 'various'), - (3, 'Fram', 7700, 'Rice and Curry Spice', 'dinner Saturday'), - (4, 'Kals MatMarkn', 25000, 'Alcohol-Free Beer, sundries', 'various'), - (4, 'Kals MatMarkn', -1570, "Michael's toothpaste", 'none'), - (4, 'Kals MatMarkn', -1690, "Laura's toothpaste", 'none'), - (4, 'Kals MatMarkn', -720, 'Deposit on Beer Bottles', 'various'), - (4, 'Kals MatMarkn', -60, 'Deposit on another Beer Bottle', 'various'), - (5, 'Kals MatMarkn', 26750, 'lunch bread meat cheese', 'lunch Monday'), - (6, 'Kals MatMarkn', 15950, 'various', 'dinner Tuesday and Thursday'), - (7, 'Kals MatMarkn', 3650, 'Drottningsylt, etc.', 'dinner Thursday'), - (8, 'Kals MatMarkn', 26150, 'Chicken and Mushroom Sauce', 'dinner Wed'), (8, 'Kals MatMarkn', -2490, 'Jacob and Laura -- juice', 'dinner Wed'), - (8, 'Kals MatMarkn', -2990, "Chicken we didn't cook", 'dinner Wednesday'), - (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), - (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), - (10, 'Kals MatMarkn', 26900, 'Jansons Frestelse', 'dinner Sunday'), - (10, 'Kals MatMarkn', -540, 'Deposit on Beer Bottles', 'dinner Sunday'), (11, 'Kals MatMarkn', 22650, 'lunch bread meat cheese', 'lunch Thursday'), - (11, 'Kals MatMarkn', -2190, 'Jacob and Laura -- juice', 'lunch Thursday'), - (11, 'Kals MatMarkn', -2790, 'Jacob and Laura -- cereal', 'lunch Thurs'), (11, 'Kals MatMarkn', -760, 'Jacob and Laura -- milk', 'lunch Thursday'), (12, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'lunch Friday'), (13, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Sun'), - (14, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Tues'), - (15, 'Kals MatMarkn', 20000, 'lunch bread meat cheese', 'guestimate Wed'), - (16, 'Kals MatMarkn', 42050, 'grillfest', 'dinner Friday'), - (16, 'Kals MatMarkn', -1350, 'Deposit on Beer Bottles', 'dinner Friday'), (17, 'System Bolaget', 15500, 'Cederlunds Caloric', 'dinner Thursday'), - (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), (17, 'System Bolaget', 13800, '2 x Jacobs Creek 69SEK', 'various'), - (18, 'J and Ls winecabinet', 10800, '2 x Parrotes 54SEK', 'various'), - (18, 'J and Ls winecabinet', 14700, '3 x Saint Paulin 49SEK', 'various'), (18, 'J and Ls winecabinet', 10400, '2 x Farnese Sangioves 52SEK', - 'cheaper when we bought it'), - (18, 'J and Ls winecabinet', 17800, '2 x Le Poiane 89SEK', 'various'), - (18, 'J and Ls winecabinet', 9800, '2 x Something Else 49SEK', 'various'), - (19, 'Konsum', 26000, 'Saturday Bread and Fruit', 'Slip MISSING'), - (20, 'Konsum', 15245, 'Mooseburgers', 'found slip'), - (21, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), - (22, 'J and Ls freezer', 21000, 'Meat for Curry, grilling', ''), - (22, 'J and Ls cupboard', 3000, 'Rice', ''), - (22, 'J and Ls cupboard', 4000, 'Charcoal', ''), - (23, 'Fram', 2975, 'Potatoes', '3.5 kg @ 8.50SEK'), - (23, 'Fram', 1421, 'Peas', 'Thursday dinner'), - (24, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), - (24, 'Kals MatMarkn', -2990, 'TP', 'None'), - (24, 'Kals MatMarkn', -2320, 'T-Gul', 'None') - ] - -print [t[2] for t in slips] -print (reduce(lambda x, y: x+y, [t[2] for t in slips], 0))/900 - -Pypy said: 603. Dinner for a week cost 603 Swedish Krona -- or approximately -50$ US. So if we can't have world domination, or get our Object Space -to work, a new career in Sprint cost control beckons. :-) - -3. The Translate Object Space - -The Translate Object Space is the next goal. It is an example of an -ObjectSpace that differs a lot from StandardObjectSpace. We have to -translate the Python code we have into C code. This is the sine qua -non condition for our work to be actually usable. Quite unexpectedly, -the major piece of the translator is itself an object space, the -TranslateObjectSpace. Its goal is to run any Python code and produce C -code in the background as it does so. - -Specifically, we take our PyPy interpreter with the Translate Object -Space instead of the Standard Object Space, and run that, asking it to -interpret our generated bytecode. A wrapped object is now the name of -a variable in the C program we are emitting, for example: - - The add method in the Translate Object Space takes two variable -names, x and y, and emits the C code z = x + y; where z is a new variable -name which is returned as the result of add. (We will actually need to -make the wrapped objects a bit more elaborate so that we can also record, -besides the C variable name, its basic type). - -At the time of this writing, it is not clear whether this is too -ambitious a goal for the Third Sprint, held in Louvain-la-Neuve, -Belgium (near Brussels), June 21 - 24 . - ------------- - -More details on how we actually do this stuff. - -A crucial concept is Multimethods (yanked from the wiki) - -Interpreter-level classes correspond to implementations of -application-level types. The hierarchy among the classes used for the -implementations is convenient for implementation purposes. It is not -related to any application-level type hierarchy. - -Dispatch - -Multimethods dispatch by looking in a set of registered -functions. Each registered function has a signature, which defines -which object implementation classes are accepted at the corresponding -argument position. - -The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly -'object' later). As it accepts anything, it is the only way to -guarantee that the registered function will be called with exactly the -same object as was passed originally. ATTENTION: in all other cases -the argument received by the function may have been converted in some -way. It must thus not be considered to be 'id'entical to the original -argument. For example it should not be stored in a data structure, nor -be queried for type, nor be used for another multimethod dispatch -- -the only thing you should do is read and write its internal data. - -For example, 'getattr(obj, attr)' is implemented with a W_StringObject -second argument when all it needs is just the name of the attr, and -with a W_ANY when the 'attr' object could be used as a key in -obj.__dict__. - -Delegation - -Delegation is a transparent convertion mechanism between object -implementations. The convertion can give a result of a different type -(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> -str). There is a global table of delegators. We should not rely on the -delegators to be tried in any particlar order, or at all (e.g. the int --> float delegator could be ignored when we know that no registered -function will accept a float anyway). - -Delegation is also used to emulate inheritance between built-in types -(e.g. bool -> int). This is done by delegation because there is no -reason that a particular implementation of a sub-type can be trivially -typecast to some other particular implementation of the parent type; -the process might require some work. - -Types - -Types are implemented by the class W_TypeObject. This is where -inheritance and the Method Resolution Order are defined, and where -attribute look-ups are done. - -Instances of user-defined types are implementated as W_UserObjects. A -user-defined type can inherit from built-in types (maybe more than -one, although this is incompatible with CPython). The W_UserObject -delegator converts the object into any of these "parent objects" if -needed. This is how user-defined types appear to inherit all built-in -operator implementations. - -Delegators should be able to invoke user code; this would let us -implement special methods like __int__() by calling them within a -W_UserObject -> int delegator. - -Specifics of multimethods - -Multimethods dispatch more-specific-first, left-to-right (i.e. if -there is an exact match for the first argument it will always be tried -first). - -Delegators are automatically chained (i.e. A -> B and B -> C would be -combined to allow for A -> C delegation). - -Delegators do not publish the class of the converted object in -advance, so that the W_UserObject delegator can potentially produce -any other built-in implementation. This means chaining and chain loop -detection cannot be done statically (at least without help from an -analysis tool like the translator-to-C). To break loops, we can assume -(unless a particular need arises) that delegators are looping when -they return an object of an already-seen class. - -Registration - -The register() method of multimethods adds a function to its database -of functions, with the given signature. A function that raises -FailedToImplement causes the next match to be tried. - -'delegate' is the special unary multimethod that should try to convert -its argument to something else. For greater control, it can also -return a list of 2-tuples (class, object), or an empty list for -failure to convert the argument to anything. All delegators will -potentially be tried, and recursively on each other's results to do -chaining. - -A priority ordering between delegators is used. See objspace.PRIORITY_*. - -Translation - -The code in multimethod.py is not supposed to be read by the -translator-to-C. Special optimized code will be generated instead -(typically some kind of precomputed dispatch tables). - -Delegation is special-cased too. Most delegators will be found to -return an object of a statically known class, which means that most of -the chaining and loop detection can be done in advance. - -Multimethod slicing - -Multimethods are visible to user code as (bound or unbound) methods -defined for the corresponding types. (At some point built-in functions -like len() and the operator.xxx() should really directly map to the -multimethods themselves, too.) - -To build a method from a multimethod (e.g. as in 'l.append' or -'int.__add__'), the result is actually a "slice" of the whole -multimethod, i.e. a sub-multimethod in which the registration table -has been trimmed down. (Delegation mechanisms are not restricted for -sliced multimethods.) - -Say that C is the class the new method is attached to (in the above -examples, respectively, C=type(l) and C=int). The restriction is based -on the registered class of the first argument ('self' for the new -method) in the signature. If this class corresponds to a fixed type -(as advertized by 'statictype'), and this fixed type is C or a -superclass of C, then we keep it. - -Some multimethods can also be sliced along their second argument, -e.g. for __radd__(). +Implementing Python in Python -- A report from the PyPy project + +The PyPython project aims at producing a simple runtime-system for the +Python language, written in Python itself. Sooner or later, this +happens to most interesting computer languages. The temptation is +great. Each significant computer language has a certain +expressiveness and power, and it is frustrating to not be able to use +that expressiveness and power when writing the language itself. Thus +we have Scheme, Lisp-written-in-Lisp, and Squeak, +Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? + +Besides using the expressiveness of Python to write Python, we also +aim to produce a minimal core which is Simple and Flexible, and no +longer dependent on CPython. We will take care that PyPy will integrate +easily with PSYCO and Stackless -- goals that are attainable with both +Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) +on the team. Samuele Pedroni, catches us when we unwittingly make +C-ish assumptions. By keeping things Simple and Flexible we can +produce code that has attractions for both industry and academia. +Academics will find that this Python is even easier to teach concepts +of language design with. And ending the dependence on CPython means +that we can produce a Python with a smaller footprint. Eventually, +we would like to produce a faster Python. We are very far from that +now, since we have spent no effort on speed and have only worked on +Simple and Flexible. + +1. How have we set about it. + +Most of you know what happens if you type + +'import this' + +at your favourite Python prompt. You get 'The Zen of Python', +by Tim Peters. It starts + + Beautiful is better than ugly. + Explicit is better than implicit. + Simple is better than complex. + +and ends with: + + Namespaces are one honking great idea -- let's do more of those! + +What would 'doing more of those' mean? Here is one approach. + + In a Python-like language, a running interpreter has three main parts: + + * the main loop, which suffles data around and calls the operations + defined in the object library according to the bytecode. + + * the compiler, which represents the static optimization of the + source code into an intermediate format, the bytecode; + + * the object library, implementing the various types of objects + and their semantics; + +In PyPy, the three parts are clearly separated and can be replaced +independently. The main loop generally assumes little about the semantics +of the objects: they are essentially black boxes (PyObject pointers). The +interpreter stack and the variables only contain such black boxes. +Every operation is done via calls to the object library, such as +PyNumber_Add(). We haven't done much to make the compiler and the main +loop into explicit concepts (yet), because we have been concentrating +on making separable object libraries. + +We call the separable object library, an Object Space. +We call Wrapped Objects the black boxes of an Object Space. + +But the exciting thing is that while existing languages implement _one_ +Object Space, by separating things we have produced an architecture +which will enable us to run more than one Object Space in the same +interpreter at the same time. This idea has some exciting implications. + +So let us dream for a bit. + +First dream: How do you get computer science concepts in language design +more effectively into student brains? + +Traditionally, academics come up with interesting new ideas and +concepts, but, to the extent that they are truly new end up creating +another language to express these ideas in. Unfortunately, many +languages end up merely as a vehicle for too few new ideas. We end up +force-feeding our poor students with too many computer languages, too +quickly -- each language designed to teach a particular point. And +many of our languages are particularly weak on everything _but_ the +point we wish to make. + +Things would go a lot more smoothly if we could only create an Object +Space which obeys the new rules we have thought up, and drop it into +an existing language. Comparisons between other ways of doing things +would also be a lot simpler. Finally, we could reasonably ask our +students to implement these ideas in Python and let them drop them in, +leaving all the other bits, irrelevant for our educational purposes as +they already are written. There is no better way to learn about +compiler writing, than writing compilers, but a lot of todays +education in compiler writing leaves a huge gap between 'the theory +that is in the book which the student is expected to learn' and 'what +is reasonable for a student to implement as coursework'. Students can +spend all semester overcoming difficulties in _actually getting the IO +to work_, and _interfacing with the runtime libraries_, while only +spending a fraction of the time on the concepts which you are trying +to teach. + +Object Spaces will provide a better fit between the the abstract +concepts we wish to teach and the code written to implement just that. + +Dream number Two: A Slimmer Python + +People who write code for handhelds and other embedded devices often wish +that they could have a much smaller footprint. Now they can ask for a +Tiny Object Space which only implements the behaviour which they need, +and skips the parts that they do not. + +Dream number Three -- What is the best way to implement a dict? + +This depends on how much data you intend to store in your dict. If you +never expect your dict to have more than a half dozen items, a really +fast list may be best. Larger dicts might best be implemented as +hashes. And for storing enormous amounts of data, a binary tree +might be just what you would be interested in. In principel, there is +nothing to stop your interpreter from keeping statistics on how it is +being used, and to move from strategy to strategy at runtime. + +Dream number Four -- How would you like your operators to work today? + +Consider y = int(x). How would you like this to work when x is 4.2, +4.5, -4.2 and -4.5? Currently Python says 4, 4, -4 and -4, truncating +towards zero. But for certain applications, this is not what is desired. +You would prefer round behaviour 4, 5, -4 -5 -- rounding away from zero. +Or you would like to always return the larger integer 5 5 -4 -4. Sometimes +just running an existing program and changing such behaviour can reveal +interesting embedded assumptions of which the author may be unaware. + +Changing the behaviour and seeing how the results change ought to be +straight-forward, simple, and easy. + +Dream number Five -- Running different Object Spaces on different processors +of the same machine. + +Dream number Six -- Running different Object Spaces on different machines. + +This is one of the unrealised dreams of distributed computing. It would +often be convenient to allow the various machines on a network to share +cpu resources. Thus one could begin a computation on a small device, +say a mobile phone, or a PDA, and have the program automatically notice +that the computation was too strenuous for such a device, and automatically +forward the computation to a machine with more computational power. + +Dream number Seven -- A Smarter, more Dynamic Interpreter + +There is no reason why your Python interpreter could not keep statistics +of how it is being used, and automatically select from a collection of +algorithms the one which is best suited for the data at hand. + +Dream number Eight -- How to avoid painful conversion of your code base +to new versions of the language. + +This dream is a bit far-fetched, but it is worth investigating. Right +now, whenever a new release of Python comes out, existing Python +programs have to be modified whenever there are conflicts. Thus there +is a trade off between getting the new features which contribute to +increased productivity in program design, and having to fix piles of +old code that wasn't broken until the language changed. With this +approach it may be possible to save your cake and eat it too. You +could demand that all your old modules use PyPy Object Space Nov 16 +2004, while immediately have your new modules use the brand new PyPy +Object Space which was defined yesterday. You could update any old +modules that would particularily benefit from having the new features, +and leave the old ones alone. + +Dream number Nine: faster Python + +While we are writing an adaptive, smarter compiler, we ought to be able +to make it faster. We think faster than C Python is a realistic goal, +eventually. When faster algorithms are discovered, we will be able to +quickly place them in the interpreter, because the components are +more or less independent. This is something that Armin Rigo +and Christian Tismer know a lot about, and I know very little. + +Dream number Ten: world domination and .... +(Well, if we can pull off Dreams 1-9, this should just drop out of the +design...) + +And if we don't pull this off, we will have at least learned a lot. This +in itself makes the project worth doing. Plus it's fun... + +But away from the dreams and back to what do we currently have? + +We currently implement (or partially implement) two Object Spaces, and +have plans to implement a third in short order. + +1. The Trivial Object Space + +A PyPy interpreter using the TrivialObjectSpace is an interpreter with +its own main loop (written in Python), and nothing else. This main +loop manipulates real Python objects and all operations are done +directly on the Python objects. For example, "1" really means "1" and +when the interpreter encounters the BINARY_ADD bytecode instructions +the TrivialObjectSpace will just add two real Python objects together +using Python's "+". The same for lists, dictionaries, classes... We +just use Python's own. + +This Object Space is only useful for testing the concept of Object Spaces, +and our interpreter, or even interpreting different kinds of bytecodes. +This is already done; it is funny to watch "dis.dis" disassembling itself +painfully slowly. + +Getting this to work was a goal of the Hildesheim Sprint February 16-23. +It demonstrated that our Object Space Concept was viable, and that our +interpreter worked. + +2. The Standard Object Space + +The Standard Object Space is the object space that works just like +Python's, that is, the object space whose black boxes are real Python +objects that work as expected. This is where the bulk of the work in +PyPy has been done to date. Getting the Standard Object Space to +work was a goal of the Gothenburg Sprint May 24 - 31. + +Specifically we needed to get this code: + +aStr = 'hello world' +print len(aStr) + +to run. We needed types and builtins to work. This ran, slowly. + +Then we added strings. Getting this code to work was the second +goal. + +### a trivial program to test strings, lists, functions and methods ### + +def addstr(s1,s2): + return s1 + s2 + +str = "an interesting string" +str2 = 'another::string::xxx::y:aa' +str3 = addstr(str,str2) +arr = [] +for word in str.split(): + if word in str2.split('::'): + arr.append(word) +print ''.join(arr) +print "str + str2 = ", str3 + +This we accomplished by mid-week. + +By the end of the Sprint we produced our first Python program that +ran under PyPy which simply 'did something we wanted to do' and wasn't +an artificial goal. Specifically, it calculated the share in foodbill +for each of the 9 Sprint participants. + +slips=[(1, 'Kals MatMarkn', 6150, 'Chutney for Curry', 'dinner Saturday'), + (2, 'Kals MatMarkn', 32000, 'Spaghetti, Beer', 'dinner Monday'), + (2, 'Kals MatMarkn', -810, 'Deposit on Beer Bottles', 'various'), + (3, 'Fram', 7700, 'Rice and Curry Spice', 'dinner Saturday'), + (4, 'Kals MatMarkn', 25000, 'Alcohol-Free Beer, sundries', 'various'), + (4, 'Kals MatMarkn', -1570, "Michael's toothpaste", 'none'), + (4, 'Kals MatMarkn', -1690, "Laura's toothpaste", 'none'), + (4, 'Kals MatMarkn', -720, 'Deposit on Beer Bottles', 'various'), + (4, 'Kals MatMarkn', -60, 'Deposit on another Beer Bottle', 'various'), + (5, 'Kals MatMarkn', 26750, 'lunch bread meat cheese', 'lunch Monday'), + (6, 'Kals MatMarkn', 15950, 'various', 'dinner Tuesday and Thursday'), + (7, 'Kals MatMarkn', 3650, 'Drottningsylt, etc.', 'dinner Thursday'), + (8, 'Kals MatMarkn', 26150, 'Chicken and Mushroom Sauce', 'dinner Wed'), + (8, 'Kals MatMarkn', -2490, 'Jacob and Laura -- juice', 'dinner Wed'), + (8, 'Kals MatMarkn', -2990, "Chicken we didn't cook", 'dinner Wednesday'), + (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), + (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), + (10, 'Kals MatMarkn', 26900, 'Jansons Frestelse', 'dinner Sunday'), + (10, 'Kals MatMarkn', -540, 'Deposit on Beer Bottles', 'dinner Sunday'), + (11, 'Kals MatMarkn', 22650, 'lunch bread meat cheese', 'lunch Thursday'), + (11, 'Kals MatMarkn', -2190, 'Jacob and Laura -- juice', 'lunch Thursday'), + (11, 'Kals MatMarkn', -2790, 'Jacob and Laura -- cereal', 'lunch Thurs'), + (11, 'Kals MatMarkn', -760, 'Jacob and Laura -- milk', 'lunch Thursday'), + (12, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'lunch Friday'), + (13, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Sun'), + (14, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Tues'), + (15, 'Kals MatMarkn', 20000, 'lunch bread meat cheese', 'guestimate Wed'), + (16, 'Kals MatMarkn', 42050, 'grillfest', 'dinner Friday'), + (16, 'Kals MatMarkn', -1350, 'Deposit on Beer Bottles', 'dinner Friday'), + (17, 'System Bolaget', 15500, 'Cederlunds Caloric', 'dinner Thursday'), + (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), + (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), + (17, 'System Bolaget', 13800, '2 x Jacobs Creek 69SEK', 'various'), + (18, 'J and Ls winecabinet', 10800, '2 x Parrotes 54SEK', 'various'), + (18, 'J and Ls winecabinet', 14700, '3 x Saint Paulin 49SEK', 'various'), + (18, 'J and Ls winecabinet', 10400, '2 x Farnese Sangioves 52SEK','cheaper when we bought it'), + (18, 'J and Ls winecabinet', 17800, '2 x Le Poiane 89SEK', 'various'), + (18, 'J and Ls winecabinet', 9800, '2 x Something Else 49SEK', 'various'), + (19, 'Konsum', 26000, 'Saturday Bread and Fruit', 'Slip MISSING'), + (20, 'Konsum', 15245, 'Mooseburgers', 'found slip'), + (21, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), + (22, 'J and Ls freezer', 21000, 'Meat for Curry, grilling', ''), + (22, 'J and Ls cupboard', 3000, 'Rice', ''), + (22, 'J and Ls cupboard', 4000, 'Charcoal', ''), + (23, 'Fram', 2975, 'Potatoes', '3.5 kg @ 8.50SEK'), + (23, 'Fram', 1421, 'Peas', 'Thursday dinner'), + (24, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), + (24, 'Kals MatMarkn', -2990, 'TP', 'None'), + (24, 'Kals MatMarkn', -2320, 'T-Gul', 'None') + ] + +print [t[2] for t in slips] +print (reduce(lambda x, y: x+y, [t[2] for t in slips], 0))/900 + +Pypy said: 603. Dinner for a week cost 603 Swedish Krona -- or approximately +50$ US. So if we can't have world domination, or get our Object Space +to work, a new career in Sprint cost control beckons. :-) + +3. The Translate Object Space + +The Translate Object Space is the next goal. It is an example of an +ObjectSpace that differs a lot from StandardObjectSpace. We have to +translate the Python code we have into C code. This is the sine qua +non condition for our work to be actually usable. Quite unexpectedly, +the major piece of the translator is itself an object space, the +TranslateObjectSpace. Its goal is to run any Python code and produce C +code in the background as it does so. + +Specifically, we take our PyPy interpreter with the Translate Object +Space instead of the Standard Object Space, and run that, asking it to +interpret our generated bytecode. A wrapped object is now the name of +a variable in the C program we are emitting, for example: + + The add method in the Translate Object Space takes two variable +names, x and y, and emits the C code z = x + y; where z is a new variable +name which is returned as the result of add. (We will actually need to +make the wrapped objects a bit more elaborate so that we can also record, +besides the C variable name, its basic type). + +At the time of this writing, it is not clear whether this is too +ambitious a goal for the Third Sprint, held in Louvain-la-Neuve, +Belgium (near Brussels), June 21 - 24 . + +------------ + +More details on how we actually do this stuff. + +A crucial concept is Multimethods (yanked from the wiki) + +Interpreter-level classes correspond to implementations of +application-level types. The hierarchy among the classes used for the +implementations is convenient for implementation purposes. It is not +related to any application-level type hierarchy. + +Dispatch + +Multimethods dispatch by looking in a set of registered +functions. Each registered function has a signature, which defines +which object implementation classes are accepted at the corresponding +argument position. + +The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly +'object' later). As it accepts anything, it is the only way to +guarantee that the registered function will be called with exactly the +same object as was passed originally. ATTENTION: in all other cases +the argument received by the function may have been converted in some +way. It must thus not be considered to be 'id'entical to the original +argument. For example it should not be stored in a data structure, nor +be queried for type, nor be used for another multimethod dispatch -- +the only thing you should do is read and write its internal data. + +For example, 'getattr(obj, attr)' is implemented with a W_StringObject +second argument when all it needs is just the name of the attr, and +with a W_ANY when the 'attr' object could be used as a key in +obj.__dict__. + +Delegation + +Delegation is a transparent convertion mechanism between object +implementations. The convertion can give a result of a different type +(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> +str). There is a global table of delegators. We should not rely on the +delegators to be tried in any particlar order, or at all (e.g. the int +-> float delegator could be ignored when we know that no registered +function will accept a float anyway). + +Delegation is also used to emulate inheritance between built-in types +(e.g. bool -> int). This is done by delegation because there is no +reason that a particular implementation of a sub-type can be trivially +typecast to some other particular implementation of the parent type; +the process might require some work. + +Types + +Types are implemented by the class W_TypeObject. This is where +inheritance and the Method Resolution Order are defined, and where +attribute look-ups are done. + +Instances of user-defined types are implementated as W_UserObjects. A +user-defined type can inherit from built-in types (maybe more than +one, although this is incompatible with CPython). The W_UserObject +delegator converts the object into any of these "parent objects" if +needed. This is how user-defined types appear to inherit all built-in +operator implementations. + +Delegators should be able to invoke user code; this would let us +implement special methods like __int__() by calling them within a +W_UserObject -> int delegator. + +Specifics of multimethods + +Multimethods dispatch more-specific-first, left-to-right (i.e. if +there is an exact match for the first argument it will always be tried +first). + +Delegators are automatically chained (i.e. A -> B and B -> C would be +combined to allow for A -> C delegation). + +Delegators do not publish the class of the converted object in +advance, so that the W_UserObject delegator can potentially produce +any other built-in implementation. This means chaining and chain loop +detection cannot be done statically (at least without help from an +analysis tool like the translator-to-C). To break loops, we can assume +(unless a particular need arises) that delegators are looping when +they return an object of an already-seen class. + +Registration + +The register() method of multimethods adds a function to its database +of functions, with the given signature. A function that raises +FailedToImplement causes the next match to be tried. + +'delegate' is the special unary multimethod that should try to convert +its argument to something else. For greater control, it can also +return a list of 2-tuples (class, object), or an empty list for +failure to convert the argument to anything. All delegators will +potentially be tried, and recursively on each other's results to do +chaining. + +A priority ordering between delegators is used. See objspace.PRIORITY_*. + +Translation + +The code in multimethod.py is not supposed to be read by the +translator-to-C. Special optimized code will be generated instead +(typically some kind of precomputed dispatch tables). + +Delegation is special-cased too. Most delegators will be found to +return an object of a statically known class, which means that most of +the chaining and loop detection can be done in advance. + +Multimethod slicing + +Multimethods are visible to user code as (bound or unbound) methods +defined for the corresponding types. (At some point built-in functions +like len() and the operator.xxx() should really directly map to the +multimethods themselves, too.) + +To build a method from a multimethod (e.g. as in 'l.append' or +'int.__add__'), the result is actually a "slice" of the whole +multimethod, i.e. a sub-multimethod in which the registration table +has been trimmed down. (Delegation mechanisms are not restricted for +sliced multimethods.) + +Say that C is the class the new method is attached to (in the above +examples, respectively, C=type(l) and C=int). The restriction is based +on the registered class of the first argument ('self' for the new +method) in the signature. If this class corresponds to a fixed type +(as advertized by 'statictype'), and this fixed type is C or a +superclass of C, then we keep it. + +Some multimethods can also be sliced along their second argument, +e.g. for __radd__(). From mwh at codespeak.net Wed Jun 18 14:58:18 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 18 Jun 2003 14:58:18 +0200 (MEST) Subject: [pypy-svn] rev 830 - pypy/trunk/doc Message-ID: <20030618125818.6C2675A550@thoth.codespeak.net> Author: mwh Date: Wed Jun 18 14:58:17 2003 New Revision: 830 Modified: pypy/trunk/doc/oscon2003-paper.txt (contents, props changed) Log: set svn:eol-style to native (bah) convert line-endings to *my* platform's native value -- hope this was the right thing to do Modified: pypy/trunk/doc/oscon2003-paper.txt ============================================================================== --- pypy/trunk/doc/oscon2003-paper.txt (original) +++ pypy/trunk/doc/oscon2003-paper.txt Wed Jun 18 14:58:17 2003 @@ -1,464 +1,464 @@ -Implementing Python in Python -- A report from the PyPy project - -The PyPython project aims at producing a simple runtime-system for the -Python language, written in Python itself. Sooner or later, this -happens to most interesting computer languages. The temptation is -great. Each significant computer language has a certain -expressiveness and power, and it is frustrating to not be able to use -that expressiveness and power when writing the language itself. Thus -we have Scheme, Lisp-written-in-Lisp, and Squeak, -Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? - -Besides using the expressiveness of Python to write Python, we also -aim to produce a minimal core which is Simple and Flexible, and no -longer dependent on CPython. We will take care that PyPy will integrate -easily with PSYCO and Stackless -- goals that are attainable with both -Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) -on the team. Samuele Pedroni, catches us when we unwittingly make -C-ish assumptions. By keeping things Simple and Flexible we can -produce code that has attractions for both industry and academia. -Academics will find that this Python is even easier to teach concepts -of language design with. And ending the dependence on CPython means -that we can produce a Python with a smaller footprint. Eventually, -we would like to produce a faster Python. We are very far from that -now, since we have spent no effort on speed and have only worked on -Simple and Flexible. - -1. How have we set about it. - -Most of you know what happens if you type - -'import this' - -at your favourite Python prompt. You get 'The Zen of Python', -by Tim Peters. It starts - - Beautiful is better than ugly. - Explicit is better than implicit. - Simple is better than complex. - -and ends with: - - Namespaces are one honking great idea -- let's do more of those! - -What would 'doing more of those' mean? Here is one approach. - - In a Python-like language, a running interpreter has three main parts: - - * the main loop, which suffles data around and calls the operations - defined in the object library according to the bytecode. - - * the compiler, which represents the static optimization of the - source code into an intermediate format, the bytecode; - - * the object library, implementing the various types of objects - and their semantics; - -In PyPy, the three parts are clearly separated and can be replaced -independently. The main loop generally assumes little about the semantics -of the objects: they are essentially black boxes (PyObject pointers). The -interpreter stack and the variables only contain such black boxes. -Every operation is done via calls to the object library, such as -PyNumber_Add(). We haven't done much to make the compiler and the main -loop into explicit concepts (yet), because we have been concentrating -on making separable object libraries. - -We call the separable object library, an Object Space. -We call Wrapped Objects the black boxes of an Object Space. - -But the exciting thing is that while existing languages implement _one_ -Object Space, by separating things we have produced an architecture -which will enable us to run more than one Object Space in the same -interpreter at the same time. This idea has some exciting implications. - -So let us dream for a bit. - -First dream: How do you get computer science concepts in language design -more effectively into student brains? - -Traditionally, academics come up with interesting new ideas and -concepts, but, to the extent that they are truly new end up creating -another language to express these ideas in. Unfortunately, many -languages end up merely as a vehicle for too few new ideas. We end up -force-feeding our poor students with too many computer languages, too -quickly -- each language designed to teach a particular point. And -many of our languages are particularly weak on everything _but_ the -point we wish to make. - -Things would go a lot more smoothly if we could only create an Object -Space which obeys the new rules we have thought up, and drop it into -an existing language. Comparisons between other ways of doing things -would also be a lot simpler. Finally, we could reasonably ask our -students to implement these ideas in Python and let them drop them in, -leaving all the other bits, irrelevant for our educational purposes as -they already are written. There is no better way to learn about -compiler writing, than writing compilers, but a lot of todays -education in compiler writing leaves a huge gap between 'the theory -that is in the book which the student is expected to learn' and 'what -is reasonable for a student to implement as coursework'. Students can -spend all semester overcoming difficulties in _actually getting the IO -to work_, and _interfacing with the runtime libraries_, while only -spending a fraction of the time on the concepts which you are trying -to teach. - -Object Spaces will provide a better fit between the the abstract -concepts we wish to teach and the code written to implement just that. - -Dream number Two: A Slimmer Python - -People who write code for handhelds and other embedded devices often wish -that they could have a much smaller footprint. Now they can ask for a -Tiny Object Space which only implements the behaviour which they need, -and skips the parts that they do not. - -Dream number Three -- What is the best way to implement a dict? - -This depends on how much data you intend to store in your dict. If you -never expect your dict to have more than a half dozen items, a really -fast list may be best. Larger dicts might best be implemented as -hashes. And for storing enormous amounts of data, a binary tree -might be just what you would be interested in. In principel, there is -nothing to stop your interpreter from keeping statistics on how it is -being used, and to move from strategy to strategy at runtime. - -Dream number Four -- How would you like your operators to work today? - -Consider y = int(x). How would you like this to work when x is 4.2, -4.5, -4.2 and -4.5? Currently Python says 4, 4, -4 and -4, truncating -towards zero. But for certain applications, this is not what is desired. -You would prefer round behaviour 4, 5, -4 -5 -- rounding away from zero. -Or you would like to always return the larger integer 5 5 -4 -4. Sometimes -just running an existing program and changing such behaviour can reveal -interesting embedded assumptions of which the author may be unaware. - -Changing the behaviour and seeing how the results change ought to be -straight-forward, simple, and easy. - -Dream number Five -- Running different Object Spaces on different processors -of the same machine. - -Dream number Six -- Running different Object Spaces on different machines. - -This is one of the unrealised dreams of distributed computing. It would -often be convenient to allow the various machines on a network to share -cpu resources. Thus one could begin a computation on a small device, -say a mobile phone, or a PDA, and have the program automatically notice -that the computation was too strenuous for such a device, and automatically -forward the computation to a machine with more computational power. - -Dream number Seven -- A Smarter, more Dynamic Interpreter - -There is no reason why your Python interpreter could not keep statistics -of how it is being used, and automatically select from a collection of -algorithms the one which is best suited for the data at hand. - -Dream number Eight -- How to avoid painful conversion of your code base -to new versions of the language. - -This dream is a bit far-fetched, but it is worth investigating. Right -now, whenever a new release of Python comes out, existing Python -programs have to be modified whenever there are conflicts. Thus there -is a trade off between getting the new features which contribute to -increased productivity in program design, and having to fix piles of -old code that wasn't broken until the language changed. With this -approach it may be possible to save your cake and eat it too. You -could demand that all your old modules use PyPy Object Space Nov 16 -2004, while immediately have your new modules use the brand new PyPy -Object Space which was defined yesterday. You could update any old -modules that would particularily benefit from having the new features, -and leave the old ones alone. - -Dream number Nine: faster Python - -While we are writing an adaptive, smarter compiler, we ought to be able -to make it faster. We think faster than C Python is a realistic goal, -eventually. When faster algorithms are discovered, we will be able to -quickly place them in the interpreter, because the components are -more or less independent. This is something that Armin Rigo -and Christian Tismer know a lot about, and I know very little. - -Dream number Ten: world domination and .... -(Well, if we can pull off Dreams 1-9, this should just drop out of the -design...) - -And if we don't pull this off, we will have at least learned a lot. This -in itself makes the project worth doing. Plus it's fun... - -But away from the dreams and back to what do we currently have? - -We currently implement (or partially implement) two Object Spaces, and -have plans to implement a third in short order. - -1. The Trivial Object Space - -A PyPy interpreter using the TrivialObjectSpace is an interpreter with -its own main loop (written in Python), and nothing else. This main -loop manipulates real Python objects and all operations are done -directly on the Python objects. For example, "1" really means "1" and -when the interpreter encounters the BINARY_ADD bytecode instructions -the TrivialObjectSpace will just add two real Python objects together -using Python's "+". The same for lists, dictionaries, classes... We -just use Python's own. - -This Object Space is only useful for testing the concept of Object Spaces, -and our interpreter, or even interpreting different kinds of bytecodes. -This is already done; it is funny to watch "dis.dis" disassembling itself -painfully slowly. - -Getting this to work was a goal of the Hildesheim Sprint February 16-23. -It demonstrated that our Object Space Concept was viable, and that our -interpreter worked. - -2. The Standard Object Space - -The Standard Object Space is the object space that works just like -Python's, that is, the object space whose black boxes are real Python -objects that work as expected. This is where the bulk of the work in -PyPy has been done to date. Getting the Standard Object Space to -work was a goal of the Gothenburg Sprint May 24 - 31. - -Specifically we needed to get this code: - -aStr = 'hello world' -print len(aStr) - -to run. We needed types and builtins to work. This ran, slowly. - -Then we added strings. Getting this code to work was the second -goal. - -### a trivial program to test strings, lists, functions and methods ### - -def addstr(s1,s2): - return s1 + s2 - -str = "an interesting string" -str2 = 'another::string::xxx::y:aa' -str3 = addstr(str,str2) -arr = [] -for word in str.split(): - if word in str2.split('::'): - arr.append(word) -print ''.join(arr) -print "str + str2 = ", str3 - -This we accomplished by mid-week. - -By the end of the Sprint we produced our first Python program that -ran under PyPy which simply 'did something we wanted to do' and wasn't -an artificial goal. Specifically, it calculated the share in foodbill -for each of the 9 Sprint participants. - -slips=[(1, 'Kals MatMarkn', 6150, 'Chutney for Curry', 'dinner Saturday'), - (2, 'Kals MatMarkn', 32000, 'Spaghetti, Beer', 'dinner Monday'), - (2, 'Kals MatMarkn', -810, 'Deposit on Beer Bottles', 'various'), - (3, 'Fram', 7700, 'Rice and Curry Spice', 'dinner Saturday'), - (4, 'Kals MatMarkn', 25000, 'Alcohol-Free Beer, sundries', 'various'), - (4, 'Kals MatMarkn', -1570, "Michael's toothpaste", 'none'), - (4, 'Kals MatMarkn', -1690, "Laura's toothpaste", 'none'), - (4, 'Kals MatMarkn', -720, 'Deposit on Beer Bottles', 'various'), - (4, 'Kals MatMarkn', -60, 'Deposit on another Beer Bottle', 'various'), - (5, 'Kals MatMarkn', 26750, 'lunch bread meat cheese', 'lunch Monday'), - (6, 'Kals MatMarkn', 15950, 'various', 'dinner Tuesday and Thursday'), - (7, 'Kals MatMarkn', 3650, 'Drottningsylt, etc.', 'dinner Thursday'), - (8, 'Kals MatMarkn', 26150, 'Chicken and Mushroom Sauce', 'dinner Wed'), - (8, 'Kals MatMarkn', -2490, 'Jacob and Laura -- juice', 'dinner Wed'), - (8, 'Kals MatMarkn', -2990, "Chicken we didn't cook", 'dinner Wednesday'), - (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), - (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), - (10, 'Kals MatMarkn', 26900, 'Jansons Frestelse', 'dinner Sunday'), - (10, 'Kals MatMarkn', -540, 'Deposit on Beer Bottles', 'dinner Sunday'), - (11, 'Kals MatMarkn', 22650, 'lunch bread meat cheese', 'lunch Thursday'), - (11, 'Kals MatMarkn', -2190, 'Jacob and Laura -- juice', 'lunch Thursday'), - (11, 'Kals MatMarkn', -2790, 'Jacob and Laura -- cereal', 'lunch Thurs'), - (11, 'Kals MatMarkn', -760, 'Jacob and Laura -- milk', 'lunch Thursday'), - (12, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'lunch Friday'), - (13, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Sun'), - (14, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Tues'), - (15, 'Kals MatMarkn', 20000, 'lunch bread meat cheese', 'guestimate Wed'), - (16, 'Kals MatMarkn', 42050, 'grillfest', 'dinner Friday'), - (16, 'Kals MatMarkn', -1350, 'Deposit on Beer Bottles', 'dinner Friday'), - (17, 'System Bolaget', 15500, 'Cederlunds Caloric', 'dinner Thursday'), - (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), - (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), - (17, 'System Bolaget', 13800, '2 x Jacobs Creek 69SEK', 'various'), - (18, 'J and Ls winecabinet', 10800, '2 x Parrotes 54SEK', 'various'), - (18, 'J and Ls winecabinet', 14700, '3 x Saint Paulin 49SEK', 'various'), - (18, 'J and Ls winecabinet', 10400, '2 x Farnese Sangioves 52SEK','cheaper when we bought it'), - (18, 'J and Ls winecabinet', 17800, '2 x Le Poiane 89SEK', 'various'), - (18, 'J and Ls winecabinet', 9800, '2 x Something Else 49SEK', 'various'), - (19, 'Konsum', 26000, 'Saturday Bread and Fruit', 'Slip MISSING'), - (20, 'Konsum', 15245, 'Mooseburgers', 'found slip'), - (21, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), - (22, 'J and Ls freezer', 21000, 'Meat for Curry, grilling', ''), - (22, 'J and Ls cupboard', 3000, 'Rice', ''), - (22, 'J and Ls cupboard', 4000, 'Charcoal', ''), - (23, 'Fram', 2975, 'Potatoes', '3.5 kg @ 8.50SEK'), - (23, 'Fram', 1421, 'Peas', 'Thursday dinner'), - (24, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), - (24, 'Kals MatMarkn', -2990, 'TP', 'None'), - (24, 'Kals MatMarkn', -2320, 'T-Gul', 'None') - ] - -print [t[2] for t in slips] -print (reduce(lambda x, y: x+y, [t[2] for t in slips], 0))/900 - -Pypy said: 603. Dinner for a week cost 603 Swedish Krona -- or approximately -50$ US. So if we can't have world domination, or get our Object Space -to work, a new career in Sprint cost control beckons. :-) - -3. The Translate Object Space - -The Translate Object Space is the next goal. It is an example of an -ObjectSpace that differs a lot from StandardObjectSpace. We have to -translate the Python code we have into C code. This is the sine qua -non condition for our work to be actually usable. Quite unexpectedly, -the major piece of the translator is itself an object space, the -TranslateObjectSpace. Its goal is to run any Python code and produce C -code in the background as it does so. - -Specifically, we take our PyPy interpreter with the Translate Object -Space instead of the Standard Object Space, and run that, asking it to -interpret our generated bytecode. A wrapped object is now the name of -a variable in the C program we are emitting, for example: - - The add method in the Translate Object Space takes two variable -names, x and y, and emits the C code z = x + y; where z is a new variable -name which is returned as the result of add. (We will actually need to -make the wrapped objects a bit more elaborate so that we can also record, -besides the C variable name, its basic type). - -At the time of this writing, it is not clear whether this is too -ambitious a goal for the Third Sprint, held in Louvain-la-Neuve, -Belgium (near Brussels), June 21 - 24 . - ------------- - -More details on how we actually do this stuff. - -A crucial concept is Multimethods (yanked from the wiki) - -Interpreter-level classes correspond to implementations of -application-level types. The hierarchy among the classes used for the -implementations is convenient for implementation purposes. It is not -related to any application-level type hierarchy. - -Dispatch - -Multimethods dispatch by looking in a set of registered -functions. Each registered function has a signature, which defines -which object implementation classes are accepted at the corresponding -argument position. - -The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly -'object' later). As it accepts anything, it is the only way to -guarantee that the registered function will be called with exactly the -same object as was passed originally. ATTENTION: in all other cases -the argument received by the function may have been converted in some -way. It must thus not be considered to be 'id'entical to the original -argument. For example it should not be stored in a data structure, nor -be queried for type, nor be used for another multimethod dispatch -- -the only thing you should do is read and write its internal data. - -For example, 'getattr(obj, attr)' is implemented with a W_StringObject -second argument when all it needs is just the name of the attr, and -with a W_ANY when the 'attr' object could be used as a key in -obj.__dict__. - -Delegation - -Delegation is a transparent convertion mechanism between object -implementations. The convertion can give a result of a different type -(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> -str). There is a global table of delegators. We should not rely on the -delegators to be tried in any particlar order, or at all (e.g. the int --> float delegator could be ignored when we know that no registered -function will accept a float anyway). - -Delegation is also used to emulate inheritance between built-in types -(e.g. bool -> int). This is done by delegation because there is no -reason that a particular implementation of a sub-type can be trivially -typecast to some other particular implementation of the parent type; -the process might require some work. - -Types - -Types are implemented by the class W_TypeObject. This is where -inheritance and the Method Resolution Order are defined, and where -attribute look-ups are done. - -Instances of user-defined types are implementated as W_UserObjects. A -user-defined type can inherit from built-in types (maybe more than -one, although this is incompatible with CPython). The W_UserObject -delegator converts the object into any of these "parent objects" if -needed. This is how user-defined types appear to inherit all built-in -operator implementations. - -Delegators should be able to invoke user code; this would let us -implement special methods like __int__() by calling them within a -W_UserObject -> int delegator. - -Specifics of multimethods - -Multimethods dispatch more-specific-first, left-to-right (i.e. if -there is an exact match for the first argument it will always be tried -first). - -Delegators are automatically chained (i.e. A -> B and B -> C would be -combined to allow for A -> C delegation). - -Delegators do not publish the class of the converted object in -advance, so that the W_UserObject delegator can potentially produce -any other built-in implementation. This means chaining and chain loop -detection cannot be done statically (at least without help from an -analysis tool like the translator-to-C). To break loops, we can assume -(unless a particular need arises) that delegators are looping when -they return an object of an already-seen class. - -Registration - -The register() method of multimethods adds a function to its database -of functions, with the given signature. A function that raises -FailedToImplement causes the next match to be tried. - -'delegate' is the special unary multimethod that should try to convert -its argument to something else. For greater control, it can also -return a list of 2-tuples (class, object), or an empty list for -failure to convert the argument to anything. All delegators will -potentially be tried, and recursively on each other's results to do -chaining. - -A priority ordering between delegators is used. See objspace.PRIORITY_*. - -Translation - -The code in multimethod.py is not supposed to be read by the -translator-to-C. Special optimized code will be generated instead -(typically some kind of precomputed dispatch tables). - -Delegation is special-cased too. Most delegators will be found to -return an object of a statically known class, which means that most of -the chaining and loop detection can be done in advance. - -Multimethod slicing - -Multimethods are visible to user code as (bound or unbound) methods -defined for the corresponding types. (At some point built-in functions -like len() and the operator.xxx() should really directly map to the -multimethods themselves, too.) - -To build a method from a multimethod (e.g. as in 'l.append' or -'int.__add__'), the result is actually a "slice" of the whole -multimethod, i.e. a sub-multimethod in which the registration table -has been trimmed down. (Delegation mechanisms are not restricted for -sliced multimethods.) - -Say that C is the class the new method is attached to (in the above -examples, respectively, C=type(l) and C=int). The restriction is based -on the registered class of the first argument ('self' for the new -method) in the signature. If this class corresponds to a fixed type -(as advertized by 'statictype'), and this fixed type is C or a -superclass of C, then we keep it. - -Some multimethods can also be sliced along their second argument, -e.g. for __radd__(). +Implementing Python in Python -- A report from the PyPy project + +The PyPython project aims at producing a simple runtime-system for the +Python language, written in Python itself. Sooner or later, this +happens to most interesting computer languages. The temptation is +great. Each significant computer language has a certain +expressiveness and power, and it is frustrating to not be able to use +that expressiveness and power when writing the language itself. Thus +we have Scheme, Lisp-written-in-Lisp, and Squeak, +Smalltalk-written-in-Smalltalk. So why not Python-written-in-Python? + +Besides using the expressiveness of Python to write Python, we also +aim to produce a minimal core which is Simple and Flexible, and no +longer dependent on CPython. We will take care that PyPy will integrate +easily with PSYCO and Stackless -- goals that are attainable with both +Armin Rigo (author of PSYCO) and Christian Tismer (author of Stackless) +on the team. Samuele Pedroni, catches us when we unwittingly make +C-ish assumptions. By keeping things Simple and Flexible we can +produce code that has attractions for both industry and academia. +Academics will find that this Python is even easier to teach concepts +of language design with. And ending the dependence on CPython means +that we can produce a Python with a smaller footprint. Eventually, +we would like to produce a faster Python. We are very far from that +now, since we have spent no effort on speed and have only worked on +Simple and Flexible. + +1. How have we set about it. + +Most of you know what happens if you type + +'import this' + +at your favourite Python prompt. You get 'The Zen of Python', +by Tim Peters. It starts + + Beautiful is better than ugly. + Explicit is better than implicit. + Simple is better than complex. + +and ends with: + + Namespaces are one honking great idea -- let's do more of those! + +What would 'doing more of those' mean? Here is one approach. + + In a Python-like language, a running interpreter has three main parts: + + * the main loop, which suffles data around and calls the operations + defined in the object library according to the bytecode. + + * the compiler, which represents the static optimization of the + source code into an intermediate format, the bytecode; + + * the object library, implementing the various types of objects + and their semantics; + +In PyPy, the three parts are clearly separated and can be replaced +independently. The main loop generally assumes little about the semantics +of the objects: they are essentially black boxes (PyObject pointers). The +interpreter stack and the variables only contain such black boxes. +Every operation is done via calls to the object library, such as +PyNumber_Add(). We haven't done much to make the compiler and the main +loop into explicit concepts (yet), because we have been concentrating +on making separable object libraries. + +We call the separable object library, an Object Space. +We call Wrapped Objects the black boxes of an Object Space. + +But the exciting thing is that while existing languages implement _one_ +Object Space, by separating things we have produced an architecture +which will enable us to run more than one Object Space in the same +interpreter at the same time. This idea has some exciting implications. + +So let us dream for a bit. + +First dream: How do you get computer science concepts in language design +more effectively into student brains? + +Traditionally, academics come up with interesting new ideas and +concepts, but, to the extent that they are truly new end up creating +another language to express these ideas in. Unfortunately, many +languages end up merely as a vehicle for too few new ideas. We end up +force-feeding our poor students with too many computer languages, too +quickly -- each language designed to teach a particular point. And +many of our languages are particularly weak on everything _but_ the +point we wish to make. + +Things would go a lot more smoothly if we could only create an Object +Space which obeys the new rules we have thought up, and drop it into +an existing language. Comparisons between other ways of doing things +would also be a lot simpler. Finally, we could reasonably ask our +students to implement these ideas in Python and let them drop them in, +leaving all the other bits, irrelevant for our educational purposes as +they already are written. There is no better way to learn about +compiler writing, than writing compilers, but a lot of todays +education in compiler writing leaves a huge gap between 'the theory +that is in the book which the student is expected to learn' and 'what +is reasonable for a student to implement as coursework'. Students can +spend all semester overcoming difficulties in _actually getting the IO +to work_, and _interfacing with the runtime libraries_, while only +spending a fraction of the time on the concepts which you are trying +to teach. + +Object Spaces will provide a better fit between the the abstract +concepts we wish to teach and the code written to implement just that. + +Dream number Two: A Slimmer Python + +People who write code for handhelds and other embedded devices often wish +that they could have a much smaller footprint. Now they can ask for a +Tiny Object Space which only implements the behaviour which they need, +and skips the parts that they do not. + +Dream number Three -- What is the best way to implement a dict? + +This depends on how much data you intend to store in your dict. If you +never expect your dict to have more than a half dozen items, a really +fast list may be best. Larger dicts might best be implemented as +hashes. And for storing enormous amounts of data, a binary tree +might be just what you would be interested in. In principel, there is +nothing to stop your interpreter from keeping statistics on how it is +being used, and to move from strategy to strategy at runtime. + +Dream number Four -- How would you like your operators to work today? + +Consider y = int(x). How would you like this to work when x is 4.2, +4.5, -4.2 and -4.5? Currently Python says 4, 4, -4 and -4, truncating +towards zero. But for certain applications, this is not what is desired. +You would prefer round behaviour 4, 5, -4 -5 -- rounding away from zero. +Or you would like to always return the larger integer 5 5 -4 -4. Sometimes +just running an existing program and changing such behaviour can reveal +interesting embedded assumptions of which the author may be unaware. + +Changing the behaviour and seeing how the results change ought to be +straight-forward, simple, and easy. + +Dream number Five -- Running different Object Spaces on different processors +of the same machine. + +Dream number Six -- Running different Object Spaces on different machines. + +This is one of the unrealised dreams of distributed computing. It would +often be convenient to allow the various machines on a network to share +cpu resources. Thus one could begin a computation on a small device, +say a mobile phone, or a PDA, and have the program automatically notice +that the computation was too strenuous for such a device, and automatically +forward the computation to a machine with more computational power. + +Dream number Seven -- A Smarter, more Dynamic Interpreter + +There is no reason why your Python interpreter could not keep statistics +of how it is being used, and automatically select from a collection of +algorithms the one which is best suited for the data at hand. + +Dream number Eight -- How to avoid painful conversion of your code base +to new versions of the language. + +This dream is a bit far-fetched, but it is worth investigating. Right +now, whenever a new release of Python comes out, existing Python +programs have to be modified whenever there are conflicts. Thus there +is a trade off between getting the new features which contribute to +increased productivity in program design, and having to fix piles of +old code that wasn't broken until the language changed. With this +approach it may be possible to save your cake and eat it too. You +could demand that all your old modules use PyPy Object Space Nov 16 +2004, while immediately have your new modules use the brand new PyPy +Object Space which was defined yesterday. You could update any old +modules that would particularily benefit from having the new features, +and leave the old ones alone. + +Dream number Nine: faster Python + +While we are writing an adaptive, smarter compiler, we ought to be able +to make it faster. We think faster than C Python is a realistic goal, +eventually. When faster algorithms are discovered, we will be able to +quickly place them in the interpreter, because the components are +more or less independent. This is something that Armin Rigo +and Christian Tismer know a lot about, and I know very little. + +Dream number Ten: world domination and .... +(Well, if we can pull off Dreams 1-9, this should just drop out of the +design...) + +And if we don't pull this off, we will have at least learned a lot. This +in itself makes the project worth doing. Plus it's fun... + +But away from the dreams and back to what do we currently have? + +We currently implement (or partially implement) two Object Spaces, and +have plans to implement a third in short order. + +1. The Trivial Object Space + +A PyPy interpreter using the TrivialObjectSpace is an interpreter with +its own main loop (written in Python), and nothing else. This main +loop manipulates real Python objects and all operations are done +directly on the Python objects. For example, "1" really means "1" and +when the interpreter encounters the BINARY_ADD bytecode instructions +the TrivialObjectSpace will just add two real Python objects together +using Python's "+". The same for lists, dictionaries, classes... We +just use Python's own. + +This Object Space is only useful for testing the concept of Object Spaces, +and our interpreter, or even interpreting different kinds of bytecodes. +This is already done; it is funny to watch "dis.dis" disassembling itself +painfully slowly. + +Getting this to work was a goal of the Hildesheim Sprint February 16-23. +It demonstrated that our Object Space Concept was viable, and that our +interpreter worked. + +2. The Standard Object Space + +The Standard Object Space is the object space that works just like +Python's, that is, the object space whose black boxes are real Python +objects that work as expected. This is where the bulk of the work in +PyPy has been done to date. Getting the Standard Object Space to +work was a goal of the Gothenburg Sprint May 24 - 31. + +Specifically we needed to get this code: + +aStr = 'hello world' +print len(aStr) + +to run. We needed types and builtins to work. This ran, slowly. + +Then we added strings. Getting this code to work was the second +goal. + +### a trivial program to test strings, lists, functions and methods ### + +def addstr(s1,s2): + return s1 + s2 + +str = "an interesting string" +str2 = 'another::string::xxx::y:aa' +str3 = addstr(str,str2) +arr = [] +for word in str.split(): + if word in str2.split('::'): + arr.append(word) +print ''.join(arr) +print "str + str2 = ", str3 + +This we accomplished by mid-week. + +By the end of the Sprint we produced our first Python program that +ran under PyPy which simply 'did something we wanted to do' and wasn't +an artificial goal. Specifically, it calculated the share in foodbill +for each of the 9 Sprint participants. + +slips=[(1, 'Kals MatMarkn', 6150, 'Chutney for Curry', 'dinner Saturday'), + (2, 'Kals MatMarkn', 32000, 'Spaghetti, Beer', 'dinner Monday'), + (2, 'Kals MatMarkn', -810, 'Deposit on Beer Bottles', 'various'), + (3, 'Fram', 7700, 'Rice and Curry Spice', 'dinner Saturday'), + (4, 'Kals MatMarkn', 25000, 'Alcohol-Free Beer, sundries', 'various'), + (4, 'Kals MatMarkn', -1570, "Michael's toothpaste", 'none'), + (4, 'Kals MatMarkn', -1690, "Laura's toothpaste", 'none'), + (4, 'Kals MatMarkn', -720, 'Deposit on Beer Bottles', 'various'), + (4, 'Kals MatMarkn', -60, 'Deposit on another Beer Bottle', 'various'), + (5, 'Kals MatMarkn', 26750, 'lunch bread meat cheese', 'lunch Monday'), + (6, 'Kals MatMarkn', 15950, 'various', 'dinner Tuesday and Thursday'), + (7, 'Kals MatMarkn', 3650, 'Drottningsylt, etc.', 'dinner Thursday'), + (8, 'Kals MatMarkn', 26150, 'Chicken and Mushroom Sauce', 'dinner Wed'), + (8, 'Kals MatMarkn', -2490, 'Jacob and Laura -- juice', 'dinner Wed'), + (8, 'Kals MatMarkn', -2990, "Chicken we didn't cook", 'dinner Wednesday'), + (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), + (9, 'Kals MatMarkn', 1380, 'fruit for Curry', 'dinner Saturday'), + (10, 'Kals MatMarkn', 26900, 'Jansons Frestelse', 'dinner Sunday'), + (10, 'Kals MatMarkn', -540, 'Deposit on Beer Bottles', 'dinner Sunday'), + (11, 'Kals MatMarkn', 22650, 'lunch bread meat cheese', 'lunch Thursday'), + (11, 'Kals MatMarkn', -2190, 'Jacob and Laura -- juice', 'lunch Thursday'), + (11, 'Kals MatMarkn', -2790, 'Jacob and Laura -- cereal', 'lunch Thurs'), + (11, 'Kals MatMarkn', -760, 'Jacob and Laura -- milk', 'lunch Thursday'), + (12, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'lunch Friday'), + (13, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Sun'), + (14, 'Kals MatMarkn', 18850, 'lunch bread meat cheese', 'guestimate Tues'), + (15, 'Kals MatMarkn', 20000, 'lunch bread meat cheese', 'guestimate Wed'), + (16, 'Kals MatMarkn', 42050, 'grillfest', 'dinner Friday'), + (16, 'Kals MatMarkn', -1350, 'Deposit on Beer Bottles', 'dinner Friday'), + (17, 'System Bolaget', 15500, 'Cederlunds Caloric', 'dinner Thursday'), + (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), + (17, 'System Bolaget', 22400, '4 x Farnese Sangiovese 56SEK', 'various'), + (17, 'System Bolaget', 13800, '2 x Jacobs Creek 69SEK', 'various'), + (18, 'J and Ls winecabinet', 10800, '2 x Parrotes 54SEK', 'various'), + (18, 'J and Ls winecabinet', 14700, '3 x Saint Paulin 49SEK', 'various'), + (18, 'J and Ls winecabinet', 10400, '2 x Farnese Sangioves 52SEK','cheaper when we bought it'), + (18, 'J and Ls winecabinet', 17800, '2 x Le Poiane 89SEK', 'various'), + (18, 'J and Ls winecabinet', 9800, '2 x Something Else 49SEK', 'various'), + (19, 'Konsum', 26000, 'Saturday Bread and Fruit', 'Slip MISSING'), + (20, 'Konsum', 15245, 'Mooseburgers', 'found slip'), + (21, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), + (22, 'J and Ls freezer', 21000, 'Meat for Curry, grilling', ''), + (22, 'J and Ls cupboard', 3000, 'Rice', ''), + (22, 'J and Ls cupboard', 4000, 'Charcoal', ''), + (23, 'Fram', 2975, 'Potatoes', '3.5 kg @ 8.50SEK'), + (23, 'Fram', 1421, 'Peas', 'Thursday dinner'), + (24, 'Kals MatMarkn', 20650, 'Grilling', 'Friday dinner'), + (24, 'Kals MatMarkn', -2990, 'TP', 'None'), + (24, 'Kals MatMarkn', -2320, 'T-Gul', 'None') + ] + +print [t[2] for t in slips] +print (reduce(lambda x, y: x+y, [t[2] for t in slips], 0))/900 + +Pypy said: 603. Dinner for a week cost 603 Swedish Krona -- or approximately +50$ US. So if we can't have world domination, or get our Object Space +to work, a new career in Sprint cost control beckons. :-) + +3. The Translate Object Space + +The Translate Object Space is the next goal. It is an example of an +ObjectSpace that differs a lot from StandardObjectSpace. We have to +translate the Python code we have into C code. This is the sine qua +non condition for our work to be actually usable. Quite unexpectedly, +the major piece of the translator is itself an object space, the +TranslateObjectSpace. Its goal is to run any Python code and produce C +code in the background as it does so. + +Specifically, we take our PyPy interpreter with the Translate Object +Space instead of the Standard Object Space, and run that, asking it to +interpret our generated bytecode. A wrapped object is now the name of +a variable in the C program we are emitting, for example: + + The add method in the Translate Object Space takes two variable +names, x and y, and emits the C code z = x + y; where z is a new variable +name which is returned as the result of add. (We will actually need to +make the wrapped objects a bit more elaborate so that we can also record, +besides the C variable name, its basic type). + +At the time of this writing, it is not clear whether this is too +ambitious a goal for the Third Sprint, held in Louvain-la-Neuve, +Belgium (near Brussels), June 21 - 24 . + +------------ + +More details on how we actually do this stuff. + +A crucial concept is Multimethods (yanked from the wiki) + +Interpreter-level classes correspond to implementations of +application-level types. The hierarchy among the classes used for the +implementations is convenient for implementation purposes. It is not +related to any application-level type hierarchy. + +Dispatch + +Multimethods dispatch by looking in a set of registered +functions. Each registered function has a signature, which defines +which object implementation classes are accepted at the corresponding +argument position. + +The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly +'object' later). As it accepts anything, it is the only way to +guarantee that the registered function will be called with exactly the +same object as was passed originally. ATTENTION: in all other cases +the argument received by the function may have been converted in some +way. It must thus not be considered to be 'id'entical to the original +argument. For example it should not be stored in a data structure, nor +be queried for type, nor be used for another multimethod dispatch -- +the only thing you should do is read and write its internal data. + +For example, 'getattr(obj, attr)' is implemented with a W_StringObject +second argument when all it needs is just the name of the attr, and +with a W_ANY when the 'attr' object could be used as a key in +obj.__dict__. + +Delegation + +Delegation is a transparent convertion mechanism between object +implementations. The convertion can give a result of a different type +(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> +str). There is a global table of delegators. We should not rely on the +delegators to be tried in any particlar order, or at all (e.g. the int +-> float delegator could be ignored when we know that no registered +function will accept a float anyway). + +Delegation is also used to emulate inheritance between built-in types +(e.g. bool -> int). This is done by delegation because there is no +reason that a particular implementation of a sub-type can be trivially +typecast to some other particular implementation of the parent type; +the process might require some work. + +Types + +Types are implemented by the class W_TypeObject. This is where +inheritance and the Method Resolution Order are defined, and where +attribute look-ups are done. + +Instances of user-defined types are implementated as W_UserObjects. A +user-defined type can inherit from built-in types (maybe more than +one, although this is incompatible with CPython). The W_UserObject +delegator converts the object into any of these "parent objects" if +needed. This is how user-defined types appear to inherit all built-in +operator implementations. + +Delegators should be able to invoke user code; this would let us +implement special methods like __int__() by calling them within a +W_UserObject -> int delegator. + +Specifics of multimethods + +Multimethods dispatch more-specific-first, left-to-right (i.e. if +there is an exact match for the first argument it will always be tried +first). + +Delegators are automatically chained (i.e. A -> B and B -> C would be +combined to allow for A -> C delegation). + +Delegators do not publish the class of the converted object in +advance, so that the W_UserObject delegator can potentially produce +any other built-in implementation. This means chaining and chain loop +detection cannot be done statically (at least without help from an +analysis tool like the translator-to-C). To break loops, we can assume +(unless a particular need arises) that delegators are looping when +they return an object of an already-seen class. + +Registration + +The register() method of multimethods adds a function to its database +of functions, with the given signature. A function that raises +FailedToImplement causes the next match to be tried. + +'delegate' is the special unary multimethod that should try to convert +its argument to something else. For greater control, it can also +return a list of 2-tuples (class, object), or an empty list for +failure to convert the argument to anything. All delegators will +potentially be tried, and recursively on each other's results to do +chaining. + +A priority ordering between delegators is used. See objspace.PRIORITY_*. + +Translation + +The code in multimethod.py is not supposed to be read by the +translator-to-C. Special optimized code will be generated instead +(typically some kind of precomputed dispatch tables). + +Delegation is special-cased too. Most delegators will be found to +return an object of a statically known class, which means that most of +the chaining and loop detection can be done in advance. + +Multimethod slicing + +Multimethods are visible to user code as (bound or unbound) methods +defined for the corresponding types. (At some point built-in functions +like len() and the operator.xxx() should really directly map to the +multimethods themselves, too.) + +To build a method from a multimethod (e.g. as in 'l.append' or +'int.__add__'), the result is actually a "slice" of the whole +multimethod, i.e. a sub-multimethod in which the registration table +has been trimmed down. (Delegation mechanisms are not restricted for +sliced multimethods.) + +Say that C is the class the new method is attached to (in the above +examples, respectively, C=type(l) and C=int). The restriction is based +on the registered class of the first argument ('self' for the new +method) in the signature. If this class corresponds to a fixed type +(as advertized by 'statictype'), and this fixed type is C or a +superclass of C, then we keep it. + +Some multimethods can also be sliced along their second argument, +e.g. for __radd__(). From hpk at codespeak.net Wed Jun 18 16:01:30 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 18 Jun 2003 16:01:30 +0200 (MEST) Subject: [pypy-svn] rev 831 - in pypy/trunk/src/pypy: . appspace/test interpreterinterpreter/test module/test objspace/std/test test tool Message-ID: <20030618140130.E65FE5C007@thoth.codespeak.net> Author: hpk Date: Wed Jun 18 16:01:28 2003 New Revision: 831 Added: pypy/trunk/src/pypy/appspace/test/autopath.py pypy/trunk/src/pypy/interpreter/autopath.py pypy/trunk/src/pypy/interpreter/test/autopath.py pypy/trunk/src/pypy/module/test/autopath.py pypy/trunk/src/pypy/objspace/std/test/autopath.py pypy/trunk/src/pypy/test_all.py pypy/trunk/src/pypy/tool/__init__.py pypy/trunk/src/pypy/tool/autopath.py pypy/trunk/src/pypy/tool/test.py Removed: pypy/trunk/src/pypy/appspace/test/testsupport.py pypy/trunk/src/pypy/interpreter/test/testsupport.py pypy/trunk/src/pypy/interpreter/testsupport.py pypy/trunk/src/pypy/interpreter/testtools.py pypy/trunk/src/pypy/module/test/testsupport.py pypy/trunk/src/pypy/objspace/std/test/testsupport.py pypy/trunk/src/pypy/test/ pypy/trunk/src/pypy/testall.py pypy/trunk/src/pypy/testcts.py pypy/trunk/src/pypy/testsupport.py pypy/trunk/src/pypy/testwice.py pypy/trunk/src/pypy/tool/test_all.py Modified: pypy/trunk/src/pypy/appspace/test/test_cmathmodule.py pypy/trunk/src/pypy/appspace/test/test_complexobject.py pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py pypy/trunk/src/pypy/appspace/test/test_exec.py pypy/trunk/src/pypy/interpreter/interactive.py pypy/trunk/src/pypy/interpreter/main.py pypy/trunk/src/pypy/interpreter/test/test_executioncontext.py pypy/trunk/src/pypy/interpreter/test/test_extmodule.py pypy/trunk/src/pypy/interpreter/test/test_interpreter.py pypy/trunk/src/pypy/interpreter/test/test_main.py pypy/trunk/src/pypy/interpreter/test/test_objspace.py pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py pypy/trunk/src/pypy/interpreter/unittest_w.py pypy/trunk/src/pypy/module/test/test_apply.py pypy/trunk/src/pypy/module/test/test_builtin.py pypy/trunk/src/pypy/module/test/test_filter.py pypy/trunk/src/pypy/module/test/test_functional.py pypy/trunk/src/pypy/module/test/test_funtional.py pypy/trunk/src/pypy/module/test/test_map.py pypy/trunk/src/pypy/module/test/test_minmax.py pypy/trunk/src/pypy/module/test/test_range.py pypy/trunk/src/pypy/module/test/test_reduce.py pypy/trunk/src/pypy/module/test/test_sysmodule.py pypy/trunk/src/pypy/module/test/test_vars.py pypy/trunk/src/pypy/module/test/test_zip.py pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py pypy/trunk/src/pypy/objspace/std/test/test_intobject.py pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py pypy/trunk/src/pypy/objspace/std/test/test_listobject.py pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Log: Refactored our Test "Framework". - got rid of duplicate code, removed all testsupport/cts/all/whatnot files. - concentrate most of the test functionality in tool/test.py - factored out automatic path manipulation in "autopath.py" whose master version lives in tool/autopath.py and can be started to update the others. - modified interactive.py and main.py to use the new "-S" "-T" objectspace selection via cmdline. Command line option parsing still needs more work, ugh. - please start "python pypy/test_all.py -h" to see some help about the options. - consult the wiki page http://codespeak.net/moin/pypy/moin.cgi/TestFramework for some documentation i am currently putting up. - please complain about the stuff i accidentally broke :-) Added: pypy/trunk/src/pypy/appspace/test/autopath.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/appspace/test/autopath.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,76 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories dont have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.abspath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + if head not in sys.path: + sys.path.insert(0, head) + return partdir, this_dir + raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path) + +def __clone(): + """ clone master version of autopath.y into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f.seek(0) + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Modified: pypy/trunk/src/pypy/appspace/test/test_cmathmodule.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/test_cmathmodule.py (original) +++ pypy/trunk/src/pypy/appspace/test/test_cmathmodule.py Wed Jun 18 16:01:28 2003 @@ -14,9 +14,10 @@ import sys import types import unittest -import testsupport +import autopath #try: +from pypy.tool import test from pypy.appspace import cmathmodule from pypy.appspace.complexobject import complex as pycomplex #except ImportError: @@ -26,7 +27,7 @@ from test_complexobject import equal, enumerate -class TestCMathModule(unittest.TestCase): +class TestCMathModule(test.TestCase): def assertAEqual(self, a, b): if not equal(a, b): @@ -68,4 +69,4 @@ if __name__ == "__main__": - unittest.main() + test.main() Modified: pypy/trunk/src/pypy/appspace/test/test_complexobject.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/test_complexobject.py (original) +++ pypy/trunk/src/pypy/appspace/test/test_complexobject.py Wed Jun 18 16:01:28 2003 @@ -10,14 +10,15 @@ sorted out. """ +import autopath import math import cmath import sys import types import unittest -import testsupport +from pypy.tool import test from pypy.appspace.complexobject import complex as pycomplex Modified: pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py (original) +++ pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py Wed Jun 18 16:01:28 2003 @@ -2,10 +2,12 @@ New for PyPy - Could be incorporated into CPython regression tests. """ +import autopath import unittest +from pypy.tool import test -class TestExceptionComp(unittest.TestCase): +class TestExceptionComp(test.TestCase): def test_string(self): string = "string" @@ -121,4 +123,4 @@ self.fail("Exception does not match self in nested tuple.") if __name__ == "__main__": - unittest.main() + test.main() Modified: pypy/trunk/src/pypy/appspace/test/test_exec.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/test_exec.py (original) +++ pypy/trunk/src/pypy/appspace/test/test_exec.py Wed Jun 18 16:01:28 2003 @@ -2,10 +2,12 @@ New for PyPy - Could be incorporated into CPython regression tests. """ +import autopath import unittest +from pypy.tool import test -class TestExecStmt(unittest.TestCase): +class TestExecStmt(test.TestCase): def test_string(self): g = {} Deleted: pypy/trunk/src/pypy/appspace/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/testsupport.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,52 +0,0 @@ -""" -Master version of testsupport.py: copy into any subdirectory of pypy -from which scripts need to be run (typically all of the 'test' subdirs) -so that any test can "import testsupport" to ensure the parent of pypy -is on the sys.path -- so that "import pypy.etc.etc." always works. - -Also, this module exposes a member 'TestCase' that is unittest.TestCase -or a subclass thereof supplying extra methods; and a function 'main' -that is unittest.main or the equivalent. - -Furthermore, this module now exposes a member 'objspace' which is -by default class pypy.objspace.trivial.TrivialObjSpace but can be -set to use another objectspace instead; this allows tests to run -under different objectspaces without needing to edit their sources. - -For this setting, use environment variable OBJSPACE and set it to -a value such as 'pypy.objspace.trivial.TrivialObjSpace' (which is -also the default if the environment variable is not found or empty -or without any dot in it). - -When run as a script, runs all tests found in files called 'test_*.py' -in the same directory. -""" -import sys -import os -import unittest - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - p = os.path.dirname(sys.argv[0]) - if not p: - p = os.curdir - head = this_path = os.path.abspath(p) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - sys.path.insert(0, head) - break - -import pypy.interpreter.unittest_w -from pypy.interpreter.testtools import * - -TestCase = pypy.interpreter.unittest_w.IntTestCase -AppTestCase = pypy.interpreter.unittest_w.AppTestCase -main = unittest.main - -if __name__ == '__main__': - runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(this_path)) Added: pypy/trunk/src/pypy/interpreter/autopath.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/interpreter/autopath.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,76 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories dont have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.abspath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + if head not in sys.path: + sys.path.insert(0, head) + return partdir, this_dir + raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path) + +def __clone(): + """ clone master version of autopath.y into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f.seek(0) + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Modified: pypy/trunk/src/pypy/interpreter/interactive.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/interactive.py (original) +++ pypy/trunk/src/pypy/interpreter/interactive.py Wed Jun 18 16:01:28 2003 @@ -1,3 +1,5 @@ +import autopath + from pypy.interpreter import executioncontext, pyframe, baseobjspace import sys import code @@ -18,7 +20,7 @@ class PyPyConsole(code.InteractiveConsole): def __init__(self, objspace): code.InteractiveConsole.__init__(self) - self.space = objspace() + self.space = objspace self.ec = executioncontext.ExecutionContext(self.space) self.w_globals = self.ec.make_standard_w_globals() self.space.setitem(self.w_globals, @@ -66,14 +68,9 @@ import readline except ImportError: pass - # object space selection - if len(sys.argv) < 2: - choice = 'trivial' # default - else: - choice = sys.argv[1] - classname = choice.capitalize() + 'ObjSpace' - module = __import__('pypy.objspace.%s' % choice, - globals(), locals(), [classname]) - ObjSpace = getattr(module, classname) - con = PyPyConsole(ObjSpace) + + from pypy.tool import test + args = test.process_options() + objspace = test.objspace() + con = PyPyConsole(objspace) con.interact() Modified: pypy/trunk/src/pypy/interpreter/main.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/main.py (original) +++ pypy/trunk/src/pypy/interpreter/main.py Wed Jun 18 16:01:28 2003 @@ -1,4 +1,5 @@ -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std import StdObjSpace from pypy.module.builtin import Builtin from pypy.interpreter import executioncontext, baseobjspace, pyframe @@ -29,23 +30,22 @@ ec.eval_frame(frame) def run_file(fname, space=None): + if __name__=='__main__': + print "Running %r with %r" % (fname, space) istring = open(fname).read() run_string(istring, fname, space) def main(argv=None): if argv is None: argv = sys.argv - if os.environ.get('OBJSPACE'): - space = testsupport.objspace() - print "Running with %r" % os.environ.get('OBJSPACE') - else: - space = None + argv = test.process_options(argv[1:]) + space = test.objspace() try: - run_file(argv[1], space) + run_file(argv[0], space) except baseobjspace.PyPyError, pypyerr: pypyerr.operationerr.print_detailed_traceback(pypyerr.space) if __name__ == '__main__': - sys.exit(main(sys.argv)) + main(sys.argv) Added: pypy/trunk/src/pypy/interpreter/test/autopath.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/interpreter/test/autopath.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,76 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories dont have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.abspath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + if head not in sys.path: + sys.path.insert(0, head) + return partdir, this_dir + raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path) + +def __clone(): + """ clone master version of autopath.y into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f.seek(0) + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Modified: pypy/trunk/src/pypy/interpreter/test/test_executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_executioncontext.py Wed Jun 18 16:01:28 2003 @@ -1,14 +1,14 @@ -import testsupport +import autopath +from pypy.tool import test from pypy.interpreter.pyframe import PyFrame from pypy.interpreter import baseobjspace, executioncontext - -class TestExecutionContext(testsupport.TestCase): +class TestExecutionContext(test.TestCase): def test_trivial1(self): # build frame - space = testsupport.objspace() + space = test.objspace() ec = executioncontext.ExecutionContext(space) compile = space.builtin.compile bytecode = space.unwrap(compile(space.wrap('def f(x): return x+1'), @@ -22,4 +22,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/interpreter/test/test_extmodule.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_extmodule.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_extmodule.py Wed Jun 18 16:01:28 2003 @@ -1,9 +1,11 @@ -import testsupport +import autopath # need pypy.module.builtin first to make other imports work (???) from pypy.module import builtin - from pypy.interpreter import extmodule +from pypy.tool import test + +import unittest class EmptyBM(extmodule.BuiltinModule): __pythonname__ = 'empty_bm' @@ -18,11 +20,10 @@ somedata = 'twentythree' somedata = extmodule.appdata(somedata) - -class TestBuiltinModule(testsupport.TestCase): +class TestBuiltinModule(test.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace() def tearDown(self): pass @@ -71,10 +72,10 @@ self.assertEqual(thedata, 'twentythree') -class TestPyBuiltinCode(testsupport.TestCase): +class TestPyBuiltinCode(test.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace() def tearDown(self): pass @@ -128,4 +129,4 @@ self.assertEqual_w(s.call_function(builtin_f, w(2), a=w(1)), w(3)) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Wed Jun 18 16:01:28 2003 @@ -1,6 +1,7 @@ -import testsupport +import autopath +from pypy.tool import test -class TestInterpreter(testsupport.TestCase): +class TestInterpreter(test.TestCase): def codetest(self, source, functionname, args): """Compile and run the given code string, and then call its function @@ -33,7 +34,7 @@ return space.unwrap(w_output) def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace() def test_exception_trivial(self): x = self.codetest(''' @@ -141,7 +142,7 @@ self.assertEquals(self.codetest(code, 'f', [9]), 1+2+3 + 5+6+7+8+900) -class AppTestInterpreter(testsupport.AppTestCase): +class AppTestInterpreter(test.AppTestCase): def test_exception(self): try: raise Exception, 1 @@ -192,7 +193,21 @@ self.assertEquals(f(), 2) def test_print(self): - print 10 + #import sys + #save = sys.stdout + #class Out: + # def __init__(self): + # self.args = [] + # def write(self, *args): + # self.args.extend(args) + #out = Out() + #try: + # sys.stdout = out + # print 10 + # self.assertEquals(out.args, ['10','\n']) + #finally: + # sys.stdout = save + print 42 def test_identity(self): def f(x): return x @@ -200,4 +215,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/interpreter/test/test_main.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_main.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_main.py Wed Jun 18 16:01:28 2003 @@ -1,7 +1,8 @@ import unittest -import testsupport +import autopath from cStringIO import StringIO +from pypy.tool import test from pypy.interpreter.baseobjspace import OperationError testcode = """\ @@ -17,7 +18,7 @@ capture = StringIO() def checkoutput(expected_output,f,*args): - space = testsupport.objspace() + space = test.objspace() w_sys = space.get_builtin_module(space.wrap("sys")) w_oldout = space.getattr(w_sys, space.wrap("stdout")) capture.reset() Modified: pypy/trunk/src/pypy/interpreter/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_objspace.py Wed Jun 18 16:01:28 2003 @@ -1,12 +1,13 @@ -import testsupport +import autopath +from pypy.tool import test # this test isn't so much to test that the objspace interface *works* # -- it's more to test that it's *there* -class TestStdObjectSpace(testsupport.TestCase): +class TestStdObjectSpace(test.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace() def tearDown(self): pass @@ -76,4 +77,4 @@ self.space.wrap(1)) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_pyframe_app.py Wed Jun 18 16:01:28 2003 @@ -1,5 +1,6 @@ -import unittest -import testsupport +import autopath + +from pypy.tool import test from pypy.interpreter.pyframe_app import decode_frame_arguments class CodeObject: @@ -10,7 +11,7 @@ self.co_flags = 4 * vflag + 8 * kflag -class Testdecode_frame_arguments(unittest.TestCase): +class Testdecode_frame_arguments(test.TestCase): def test_plain_parameters(self): self.assertEqual( @@ -88,4 +89,4 @@ (1, 2, 3, 4), {}, (), None, CodeObject(kflag=1)) if __name__ == "__main__": - unittest.main() + test.main() Deleted: pypy/trunk/src/pypy/interpreter/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/testsupport.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,52 +0,0 @@ -""" -Master version of testsupport.py: copy into any subdirectory of pypy -from which scripts need to be run (typically all of the 'test' subdirs) -so that any test can "import testsupport" to ensure the parent of pypy -is on the sys.path -- so that "import pypy.etc.etc." always works. - -Also, this module exposes a member 'TestCase' that is unittest.TestCase -or a subclass thereof supplying extra methods; and a function 'main' -that is unittest.main or the equivalent. - -Furthermore, this module now exposes a member 'objspace' which is -by default class pypy.objspace.trivial.TrivialObjSpace but can be -set to use another objectspace instead; this allows tests to run -under different objectspaces without needing to edit their sources. - -For this setting, use environment variable OBJSPACE and set it to -a value such as 'pypy.objspace.trivial.TrivialObjSpace' (which is -also the default if the environment variable is not found or empty -or without any dot in it). - -When run as a script, runs all tests found in files called 'test_*.py' -in the same directory. -""" -import sys -import os -import unittest - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - p = os.path.dirname(sys.argv[0]) - if not p: - p = os.curdir - head = this_path = os.path.abspath(p) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - sys.path.insert(0, head) - break - -import pypy.interpreter.unittest_w -from pypy.interpreter.testtools import * - -TestCase = pypy.interpreter.unittest_w.IntTestCase -AppTestCase = pypy.interpreter.unittest_w.AppTestCase -main = unittest.main - -if __name__ == '__main__': - runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(this_path)) Deleted: pypy/trunk/src/pypy/interpreter/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/testsupport.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,52 +0,0 @@ -""" -Master version of testsupport.py: copy into any subdirectory of pypy -from which scripts need to be run (typically all of the 'test' subdirs) -so that any test can "import testsupport" to ensure the parent of pypy -is on the sys.path -- so that "import pypy.etc.etc." always works. - -Also, this module exposes a member 'TestCase' that is unittest.TestCase -or a subclass thereof supplying extra methods; and a function 'main' -that is unittest.main or the equivalent. - -Furthermore, this module now exposes a member 'objspace' which is -by default class pypy.objspace.trivial.TrivialObjSpace but can be -set to use another objectspace instead; this allows tests to run -under different objectspaces without needing to edit their sources. - -For this setting, use environment variable OBJSPACE and set it to -a value such as 'pypy.objspace.trivial.TrivialObjSpace' (which is -also the default if the environment variable is not found or empty -or without any dot in it). - -When run as a script, runs all tests found in files called 'test_*.py' -in the same directory. -""" -import sys -import os -import unittest - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - p = os.path.dirname(sys.argv[0]) - if not p: - p = os.curdir - head = this_path = os.path.abspath(p) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - sys.path.insert(0, head) - break - -import pypy.interpreter.unittest_w -from pypy.interpreter.testtools import * - -TestCase = pypy.interpreter.unittest_w.IntTestCase -AppTestCase = pypy.interpreter.unittest_w.AppTestCase -main = unittest.main - -if __name__ == '__main__': - runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(this_path)) Deleted: pypy/trunk/src/pypy/interpreter/testtools.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/testtools.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,44 +0,0 @@ -import os -import unittest - -def get_tests_for_dir(directory): - files = os.listdir(directory) - testfiles = [f[:-3] for f in files - if f.startswith('test_') and f.endswith('.py')] - - ts = unittest.TestSuite() - - tl = unittest.TestLoader() - - for testfile in testfiles: - mod = __import__(testfile) - ts.addTest(tl.loadTestsFromModule(mod)) - - return ts - -def objspace(): - objspace_path = os.environ.get('OBJSPACE') - if not objspace_path or '.' not in objspace_path: - return trivobjspace() - else: - return stdobjspace() - -_trivobjspace = None - -def trivobjspace(): - global _trivobjspace - if _trivobjspace: - return _trivobjspace - from pypy.objspace.trivial import TrivialObjSpace - _trivobjspace = TrivialObjSpace() - return _trivobjspace - -_stdobjspace = None - -def stdobjspace(): - global _stdobjspace - if _stdobjspace: - return _stdobjspace - from pypy.objspace.std import StdObjSpace - _stdobjspace = StdObjSpace() - return _stdobjspace Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/unittest_w.py (original) +++ pypy/trunk/src/pypy/interpreter/unittest_w.py Wed Jun 18 16:01:28 2003 @@ -1,6 +1,7 @@ +import autopath + import sys, os import unittest -import testtools def wrap_func(space, func): # this is generally useful enough that it should probably go @@ -11,7 +12,6 @@ return space.newfunction(code, space.newdict([]), space.wrap(func.func_defaults), None) - def make_testcase_class(space, tc_w): # XXX this is all a bit insane (but it works) @@ -114,12 +114,14 @@ unittest.TestCase.__init__(self, methodName) def __call__(self, result=None): - setattr(self, self.methodName, + if type(getattr(self, self.methodName)) != WrappedFunc: + setattr(self, self.methodName, WrappedFunc(self, getattr(self, self.methodName))) return unittest.TestCase.__call__(self, result) def setUp(self): - self.space = testtools.objspace() + from pypy.tool import test + self.space = test.objspace() def app_fail(self, w_self, w_msg=None): msg = self.space.unwrap(w_msg) Added: pypy/trunk/src/pypy/module/test/autopath.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/module/test/autopath.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,76 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories dont have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.abspath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + if head not in sys.path: + sys.path.insert(0, head) + return partdir, this_dir + raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path) + +def __clone(): + """ clone master version of autopath.y into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f.seek(0) + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Modified: pypy/trunk/src/pypy/module/test/test_apply.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_apply.py (original) +++ pypy/trunk/src/pypy/module/test/test_apply.py Wed Jun 18 16:01:28 2003 @@ -1,12 +1,14 @@ -import testsupport +import autopath + from pypy.module.builtin_app import apply, min, max +from pypy.tool import test def myminmax(*arr, **dict): # trivial function which has the signature *args, **kw v = list(arr) + dict.values() return min(v), max(v) -class TestApply(testsupport.TestCase): +class TestApply(test.TestCase): def setUp(self): pass @@ -33,6 +35,6 @@ (-4, 2)) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_builtin.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_builtin.py (original) +++ pypy/trunk/src/pypy/module/test/test_builtin.py Wed Jun 18 16:01:28 2003 @@ -1,11 +1,13 @@ -import testsupport +import autopath + from pypy.module.builtin_app import cmp +from pypy.tool import test -class TestBuiltin(testsupport.TestCase): +class TestBuiltin(test.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace() def tearDown(self): pass @@ -39,7 +41,7 @@ # sufficiently simple s.call_function(w_import, w('quopri'), w_dict, w_dict, w_fromlist) -class TestCmp(testsupport.TestCase): +class TestCmp(test.TestCase): def test_cmp(self): self.failUnless(cmp(9, 9) == 0) @@ -47,5 +49,5 @@ self.failUnless(cmp(9,0) > 0) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_filter.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_filter.py (original) +++ pypy/trunk/src/pypy/module/test/test_filter.py Wed Jun 18 16:01:28 2003 @@ -1,6 +1,6 @@ -import testsupport +import autopath from pypy.module.builtin_app import filter - +from pypy.tool import test # trivial functions for testing @@ -16,7 +16,7 @@ else: return False -class TestFilter(testsupport.TestCase): +class TestFilter(test.TestCase): def test_filter_no_arguments(self): self.assertRaises(TypeError, filter) @@ -52,4 +52,4 @@ self.assertEqual(filter(larger_than_a, 'xyzabcd'), 'xyzbcd') if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_functional.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_functional.py (original) +++ pypy/trunk/src/pypy/module/test/test_functional.py Wed Jun 18 16:01:28 2003 @@ -1,5 +1,7 @@ -import testsupport +import autopath from pypy.module.builtin_app import map, filter, reduce, zip +from pypy.tool import test + # trivial functions for testing @@ -10,7 +12,7 @@ return x + y -class TestMap(testsupport.TestCase): +class TestMap(test.TestCase): def test_trivial_map_one_seq(self): self.assertEqual(map(add_two, [1, 2, 3, 4]), [3, 4, 5, 6]) @@ -65,14 +67,14 @@ b = [] self.assertEqual(map(lambda x, y: x, a, b), a) -class TestZip(testsupport.TestCase): +class TestZip(test.TestCase): def test_one_list(self): self.assertEqual(zip([1,2,3]), [(1,), (2,), (3,)]) def test_three_lists(self): self.assertEqual(zip([1,2,3], [1,2], [1,2,3]), [(1,1,1), (2,2,2)]) -class TestReduce(testsupport.TestCase): +class TestReduce(test.TestCase): def test_None(self): self.assertRaises(TypeError, reduce, lambda x, y: x+y, [1,2,3], None) @@ -84,7 +86,7 @@ self.assertEqual(reduce(lambda x, y: x-y, [10, 2, 8]), 0) self.assertEqual(reduce(lambda x, y: x-y, [2, 8], 10), 0) -class TestFilter(testsupport.TestCase): +class TestFilter(test.TestCase): def test_None(self): self.assertEqual(filter(None, ['a', 'b', 1, 0, None]), ['a', 'b', 1]) @@ -98,6 +100,6 @@ self.assertEqual(filter(lambda x: x != "a", "a small text"), " smll text") if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_funtional.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_funtional.py (original) +++ pypy/trunk/src/pypy/module/test/test_funtional.py Wed Jun 18 16:01:28 2003 @@ -1,7 +1,9 @@ -import testsupport +import autopath from pypy.module.builtin_app import map, filter, reduce, zip -class TestMap(testsupport.TestCase): +from pypy.tool import test + +class TestMap(test.TestCase): def test_map_identity1(self): a = ['1', 2, 3, 'b', None] @@ -34,14 +36,14 @@ b = [] self.assertEqual(map(lambda x, y: x, a, b), a) -class TestZip(testsupport.TestCase): +class TestZip(test.TestCase): def test_one_list(self): self.assertEqual(zip([1,2,3]), [(1,), (2,), (3,)]) def test_three_lists(self): self.assertEqual(zip([1,2,3], [1,2], [1,2,3]), [(1,1,1), (2,2,2)]) -class TestReduce(testsupport.TestCase): +class TestReduce(test.TestCase): def test_None(self): self.assertRaises(TypeError, reduce, lambda x, y: x+y, [1,2,3], None) @@ -53,7 +55,7 @@ self.assertEqual(reduce(lambda x, y: x-y, [10, 2, 8]), 0) self.assertEqual(reduce(lambda x, y: x-y, [2, 8], 10), 0) -class TestFilter(testsupport.TestCase): +class TestFilter(test.TestCase): def test_None(self): self.assertEqual(filter(None, ['a', 'b', 1, 0, None]), ['a', 'b', 1]) @@ -67,6 +69,6 @@ self.assertEqual(filter(lambda x: x != "a", "a small text"), " smll text") if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_map.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_map.py (original) +++ pypy/trunk/src/pypy/module/test/test_map.py Wed Jun 18 16:01:28 2003 @@ -1,5 +1,6 @@ -import testsupport +import autopath from pypy.module.builtin_app import map +from pypy.tool import test # trivial functions for testing @@ -14,7 +15,7 @@ y = 1000 return x + y -class TestMap(testsupport.TestCase): +class TestMap(test.TestCase): def test_map_no_arguments(self): self.assertRaises(TypeError, map) @@ -77,6 +78,6 @@ self.assertEqual(map(lambda x, y: x, a, b), a) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_minmax.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_minmax.py (original) +++ pypy/trunk/src/pypy/module/test/test_minmax.py Wed Jun 18 16:01:28 2003 @@ -1,7 +1,8 @@ -import testsupport +import autopath from pypy.module.builtin_app import min, max +from pypy.tool import test -class TestMin(testsupport.TestCase): +class TestMin(test.TestCase): def setUp(self): pass @@ -39,7 +40,7 @@ def test_min_empty(self): self.assertRaises(ValueError, min, []) -class TestMax(testsupport.TestCase): +class TestMax(test.TestCase): def setUp(self): pass @@ -78,4 +79,4 @@ self.assertRaises(ValueError, max, []) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_range.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_range.py (original) +++ pypy/trunk/src/pypy/module/test/test_range.py Wed Jun 18 16:01:28 2003 @@ -1,7 +1,8 @@ -import testsupport +import autopath from pypy.module.builtin_app import range +from pypy.tool import test -class TestRange(testsupport.TestCase): +class TestRange(test.TestCase): def setUp(self): pass @@ -74,6 +75,6 @@ """ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_reduce.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_reduce.py (original) +++ pypy/trunk/src/pypy/module/test/test_reduce.py Wed Jun 18 16:01:28 2003 @@ -1,7 +1,8 @@ -import testsupport +import autopath from pypy.module.builtin_app import reduce +from pypy.tool import test -class TestReduce(testsupport.TestCase): +class TestReduce(test.TestCase): def test_None(self): self.assertRaises(TypeError, reduce, lambda x, y: x+y, [1,2,3], None) @@ -14,6 +15,6 @@ self.assertEqual(reduce(lambda x, y: x-y, [2, 8], 10), 0) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_sysmodule.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_sysmodule.py (original) +++ pypy/trunk/src/pypy/module/test/test_sysmodule.py Wed Jun 18 16:01:28 2003 @@ -1,8 +1,9 @@ -import testsupport +import autopath +from pypy.tool import test -class SysTests(testsupport.TestCase): +class SysTests(test.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace() self.sys_w = self.space.get_builtin_module(self.space.wrap("sys")) def tearDown(self): pass @@ -12,5 +13,5 @@ self.failUnless_w(s.getattr(self.sys_w, s.wrap("stdout"))) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_vars.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_vars.py (original) +++ pypy/trunk/src/pypy/module/test/test_vars.py Wed Jun 18 16:01:28 2003 @@ -1,5 +1,6 @@ -import testsupport +import autopath from pypy.module.builtin_app import map +from pypy.tool import test # trivial objects for testing @@ -15,7 +16,7 @@ t1 = TrivialObject() t1.do_something() -class TestVars(testsupport.TestCase): +class TestVars(test.TestCase): def test_vars_no_arguments(self): self.assertEqual(vars(), locals()) @@ -29,6 +30,6 @@ self.assertNotEqual(vars(t1), t.__dict__) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/module/test/test_zip.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_zip.py (original) +++ pypy/trunk/src/pypy/module/test/test_zip.py Wed Jun 18 16:01:28 2003 @@ -1,7 +1,8 @@ -import testsupport +import autopath from pypy.module.builtin_app import zip +from pypy.tool import test -class TestZip(testsupport.TestCase): +class TestZip(test.TestCase): def test_zip_no_arguments(self): self.assertRaises(TypeError, zip) @@ -32,6 +33,6 @@ [('h', 1, 7), ('e', 2, 8), ('l', 3, 9), ('l', 4, 10)]) if __name__ == '__main__': - testsupport.main() + test.main() Deleted: pypy/trunk/src/pypy/module/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/module/test/testsupport.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,52 +0,0 @@ -""" -Master version of testsupport.py: copy into any subdirectory of pypy -from which scripts need to be run (typically all of the 'test' subdirs) -so that any test can "import testsupport" to ensure the parent of pypy -is on the sys.path -- so that "import pypy.etc.etc." always works. - -Also, this module exposes a member 'TestCase' that is unittest.TestCase -or a subclass thereof supplying extra methods; and a function 'main' -that is unittest.main or the equivalent. - -Furthermore, this module now exposes a member 'objspace' which is -by default class pypy.objspace.trivial.TrivialObjSpace but can be -set to use another objectspace instead; this allows tests to run -under different objectspaces without needing to edit their sources. - -For this setting, use environment variable OBJSPACE and set it to -a value such as 'pypy.objspace.trivial.TrivialObjSpace' (which is -also the default if the environment variable is not found or empty -or without any dot in it). - -When run as a script, runs all tests found in files called 'test_*.py' -in the same directory. -""" -import sys -import os -import unittest - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - p = os.path.dirname(sys.argv[0]) - if not p: - p = os.curdir - head = this_path = os.path.abspath(p) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - sys.path.insert(0, head) - break - -import pypy.interpreter.unittest_w -from pypy.interpreter.testtools import * - -TestCase = pypy.interpreter.unittest_w.IntTestCase -AppTestCase = pypy.interpreter.unittest_w.AppTestCase -main = unittest.main - -if __name__ == '__main__': - runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(this_path)) Added: pypy/trunk/src/pypy/objspace/std/test/autopath.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/test/autopath.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,76 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories dont have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.abspath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + if head not in sys.path: + sys.path.insert(0, head) + return partdir, this_dir + raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path) + +def __clone(): + """ clone master version of autopath.y into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f.seek(0) + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Modified: pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py Wed Jun 18 16:01:28 2003 @@ -1,13 +1,14 @@ import unittest, sys, array -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std import cpythonobject from pypy.objspace.std.objspace import OperationError -class TestW_CPythonObject(testsupport.TestCase): +class TestW_CPythonObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') # arbitrary always-wrapped object self.stuff = array.array('b', [5,-2,77]) @@ -77,4 +78,4 @@ self.assertEquals(self.space.unwrap(w_result), 11) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Wed Jun 18 16:01:28 2003 @@ -1,11 +1,12 @@ -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std.dictobject import W_DictObject -class TestW_DictObject(testsupport.TestCase): +class TestW_DictObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -80,4 +81,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_intobject.py Wed Jun 18 16:01:28 2003 @@ -1,12 +1,13 @@ import sys -import testsupport +import autopath from pypy.objspace.std import intobject as iobj from pypy.objspace.std.objspace import FailedToImplement +from pypy.tool import test -class TestW_IntObject(testsupport.TestCase): +class TestW_IntObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -286,4 +287,4 @@ self.assertEquals(self.space.unwrap(result), hex(x)) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py Wed Jun 18 16:01:28 2003 @@ -1,11 +1,12 @@ -import testsupport +import autopath from pypy.objspace.std.iterobject import W_SeqIterObject from pypy.objspace.std.objspace import NoValue +from pypy.tool import test -class TestW_IterObject(testsupport.TestCase): +class TestW_IterObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -27,4 +28,4 @@ self.assertRaises(NoValue, self.space.next, w_iter) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_listobject.py Wed Jun 18 16:01:28 2003 @@ -1,13 +1,14 @@ #from __future__ import nested_scopes -import testsupport +import autopath from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.objspace import NoValue +from pypy.tool import test -class TestW_ListObject(testsupport.TestCase): +class TestW_ListObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -119,4 +120,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_moduleobject.py Wed Jun 18 16:01:28 2003 @@ -1,11 +1,11 @@ -import testsupport +import autopath from pypy.objspace.std.moduleobject import W_ModuleObject +from pypy.tool import test - -class TestW_ModuleObject(testsupport.TestCase): +class TestW_ModuleObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -31,4 +31,4 @@ self.assertEqual_w(space.getattr(w_m, space.wrap('yy')), w_yy) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Wed Jun 18 16:01:28 2003 @@ -1,8 +1,7 @@ -import unittest -import testsupport +import autopath from pypy.objspace.std.multimethod import * - +from pypy.tool import test # default delegator @@ -85,7 +84,7 @@ w_TypeError = 'w_TypeError' -class TestMultiMethod(unittest.TestCase): +class TestMultiMethod(test.TestCase): def test_base(self): space = FakeObjSpace() @@ -133,4 +132,4 @@ if __name__ == '__main__': - unittest.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_noneobject.py Wed Jun 18 16:01:28 2003 @@ -1,10 +1,11 @@ -import testsupport +import autopath +from pypy.tool import test -class TestW_NoneObject(testsupport.TestCase): +class TestW_NoneObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace() def tearDown(self): pass @@ -21,4 +22,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_restricted_int.py Wed Jun 18 16:01:28 2003 @@ -1,8 +1,9 @@ import unittest -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std.restricted_int import * -class Test_r_int(unittest.TestCase): +class Test_r_int(test.TestCase): def setUp(self): pass @@ -129,4 +130,4 @@ self.assertEquals(res, cmp) if __name__ == '__main__': - unittest.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py Wed Jun 18 16:01:28 2003 @@ -1,9 +1,10 @@ -import testsupport +import autopath +from pypy.tool import test -class TestW_SliceObject(testsupport.TestCase): +class TestW_SliceObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -32,4 +33,4 @@ w_slice.indices, w(10)) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py Wed Jun 18 16:01:28 2003 @@ -1,9 +1,10 @@ -import testsupport +import autopath +from pypy.tool import test -class TestW_StdObjSpace(testsupport.TestCase): +class TestW_StdObjSpace(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -19,4 +20,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Wed Jun 18 16:01:28 2003 @@ -1,14 +1,14 @@ -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std import stringobject - from pypy.objspace.std.stringobject import \ string_richcompare, W_StringObject, EQ, LT, GT, NE, LE, GE -class TestW_StringObject(testsupport.TestCase): +class TestW_StringObject(test.TestCase): def setUp(self): - self.space = testsupport.objspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -115,4 +115,4 @@ self.assertEqual_w(space.getitem(w_str, w_slice), w('el')) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py Wed Jun 18 16:01:28 2003 @@ -1,13 +1,14 @@ #from __future__ import nested_scopes -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std.tupleobject import W_TupleObject from pypy.objspace.std.objspace import NoValue -class TestW_TupleObject(testsupport.TestCase): +class TestW_TupleObject(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -115,4 +116,4 @@ test1((5,7,1,4), -5, 11, 2, (5, 1)) if __name__ == '__main__': - testsupport.main() + test.main() Modified: pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Wed Jun 18 16:01:28 2003 @@ -1,10 +1,11 @@ -import testsupport +import autopath +from pypy.tool import test from pypy.objspace.std.typeobject import PyMultimethodCode -class TestPyMultimethodCode(testsupport.TestCase): +class TestPyMultimethodCode(test.TestCase): def setUp(self): - self.space = testsupport.stdobjspace() + self.space = test.objspace('std') def tearDown(self): pass @@ -55,4 +56,4 @@ if __name__ == '__main__': - testsupport.main() + test.main() Deleted: pypy/trunk/src/pypy/objspace/std/test/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/testsupport.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,52 +0,0 @@ -""" -Master version of testsupport.py: copy into any subdirectory of pypy -from which scripts need to be run (typically all of the 'test' subdirs) -so that any test can "import testsupport" to ensure the parent of pypy -is on the sys.path -- so that "import pypy.etc.etc." always works. - -Also, this module exposes a member 'TestCase' that is unittest.TestCase -or a subclass thereof supplying extra methods; and a function 'main' -that is unittest.main or the equivalent. - -Furthermore, this module now exposes a member 'objspace' which is -by default class pypy.objspace.trivial.TrivialObjSpace but can be -set to use another objectspace instead; this allows tests to run -under different objectspaces without needing to edit their sources. - -For this setting, use environment variable OBJSPACE and set it to -a value such as 'pypy.objspace.trivial.TrivialObjSpace' (which is -also the default if the environment variable is not found or empty -or without any dot in it). - -When run as a script, runs all tests found in files called 'test_*.py' -in the same directory. -""" -import sys -import os -import unittest - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - p = os.path.dirname(sys.argv[0]) - if not p: - p = os.curdir - head = this_path = os.path.abspath(p) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - sys.path.insert(0, head) - break - -import pypy.interpreter.unittest_w -from pypy.interpreter.testtools import * - -TestCase = pypy.interpreter.unittest_w.IntTestCase -AppTestCase = pypy.interpreter.unittest_w.AppTestCase -main = unittest.main - -if __name__ == '__main__': - runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(this_path)) Added: pypy/trunk/src/pypy/test_all.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/test_all.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,6 @@ +import tool.autopath +from pypy.tool import test + +if __name__ == '__main__': + test.main(tool.autopath.pypydir) + Deleted: pypy/trunk/src/pypy/testall.py ============================================================================== --- pypy/trunk/src/pypy/testall.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,56 +0,0 @@ -import os -import unittest -import sys - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - head = this_path = os.path.abspath(os.path.dirname(sys.argv[0])) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - PYPYDIR = head - if PYPYDIR not in sys.path: - sys.path.insert(0, PYPYDIR) - break - -def find_tests(root, inc_names=[], exc_names=[]): - testmods = [] - def callback(arg, dirname, names): - if os.path.basename(dirname) == 'test': - parname = os.path.basename(os.path.dirname(dirname)) - if ((not inc_names) or parname in inc_names) and parname not in exc_names: - package = dirname[len(PYPYDIR)+1:].replace(os.sep, '.') - testfiles = [f[:-3] for f in names - if f.startswith('test_') and f.endswith('.py')] - for file in testfiles: - testmods.append(package + '.' + file) - - os.path.walk(root, callback, None) - - tl = unittest.TestLoader() - - return tl.loadTestsFromNames(testmods) - -def main(argv=None): - if argv is None: - argv = sys.argv - - inc_names = [] - exc_names = [] - - for arg in argv[1:]: - if arg.startswith('--include='): - inc_names = arg[len('--include='):].split(',') - elif arg.startswith('--exclude='): - exc_names = arg[len('--exclude='):].split(',') - else: - raise Exception, "don't know arg " + arg - - runner = unittest.TextTestRunner() - runner.run(find_tests(PYPYDIR, inc_names, exc_names)) - -if __name__ == '__main__': - main() Deleted: pypy/trunk/src/pypy/testcts.py ============================================================================== --- pypy/trunk/src/pypy/testcts.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,115 +0,0 @@ -import os -import unittest -import sys - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - head = this_path = os.path.abspath(os.path.dirname(sys.argv[0])) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - PYPYDIR = head - if PYPYDIR not in sys.path: - sys.path.insert(0, PYPYDIR) - break - -def find_tests(root, inc_names=[], exc_names=[]): - testmods = [] - def callback(arg, dirname, names): - if os.path.basename(dirname) == 'test': - parname = os.path.basename(os.path.dirname(dirname)) - if ((not inc_names) or parname in inc_names) and parname not in exc_names: - package = dirname[len(PYPYDIR)+1:].replace(os.sep, '.') - testfiles = [f[:-3] for f in names - if f.startswith('test_') and f.endswith('.py')] - for file in testfiles: - testmods.append(package + '.' + file) - - os.path.walk(root, callback, None) - - tl = unittest.TestLoader() - - return tl.loadTestsFromNames(testmods) - -class MyTestResult(unittest.TestResult): - def __init__(self): - unittest.TestResult.__init__(self) - self.successes = [] - def addSuccess(self, test): - self.successes.append(test) - - -class CtsTestRunner: - def run(self, test): - import pickle - - result = MyTestResult() - sys.stdout = open('/dev/null', 'w') - sys.stderr = open('/dev/null', 'w') - test(result) - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - - ostatus = {} - if os.path.exists('testcts.pickle'): - ostatus = pickle.load(open('testcts.pickle','r')) - - status = {} - - for e in result.errors: - name = e[0].__class__.__name__ + '.' + e[0]._TestCase__testMethodName - status[name] = 'ERROR' - for f in result.failures: - name = f[0].__class__.__name__ + '.' + f[0]._TestCase__testMethodName - status[name] = 'FAILURE' - for s in result.successes: - name = s.__class__.__name__ + '.' + s._TestCase__testMethodName - status[name] = 'success' - - keys = status.keys() - keys.sort() - - for k in keys: - old = ostatus.get(k, 'success') - if k in ostatus: - del ostatus[k] - new = status[k] - if old != new: - print k, 'has transitioned from', old, 'to', new - elif new != 'success': - print k, "is still a", new - - for k in ostatus: - print k, 'was a', ostatus[k], 'was not run this time' - status[k] = ostatus[k] - - pickle.dump(status, open('testcts.pickle','w')) - - return result - -def main(argv=None): - if argv is None: - argv = sys.argv - - inc_names = [] - exc_names = [] - - os.environ['OBJSPACE'] = 'pypy.objspace.std.objspace.StdObjSpace' - - for arg in argv[1:]: - if arg.startswith('--include='): - inc_names = arg[len('--include='):].split(',') - elif arg.startswith('--exclude='): - exc_names = arg[len('--exclude='):].split(',') - else: - raise Exception, "don't know arg " + arg - - runner = CtsTestRunner() - runner.run(find_tests(PYPYDIR, inc_names, exc_names)) - - -if __name__ == '__main__': - main() Deleted: pypy/trunk/src/pypy/testsupport.py ============================================================================== --- pypy/trunk/src/pypy/testsupport.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,52 +0,0 @@ -""" -Master version of testsupport.py: copy into any subdirectory of pypy -from which scripts need to be run (typically all of the 'test' subdirs) -so that any test can "import testsupport" to ensure the parent of pypy -is on the sys.path -- so that "import pypy.etc.etc." always works. - -Also, this module exposes a member 'TestCase' that is unittest.TestCase -or a subclass thereof supplying extra methods; and a function 'main' -that is unittest.main or the equivalent. - -Furthermore, this module now exposes a member 'objspace' which is -by default class pypy.objspace.trivial.TrivialObjSpace but can be -set to use another objectspace instead; this allows tests to run -under different objectspaces without needing to edit their sources. - -For this setting, use environment variable OBJSPACE and set it to -a value such as 'pypy.objspace.trivial.TrivialObjSpace' (which is -also the default if the environment variable is not found or empty -or without any dot in it). - -When run as a script, runs all tests found in files called 'test_*.py' -in the same directory. -""" -import sys -import os -import unittest - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - p = os.path.dirname(sys.argv[0]) - if not p: - p = os.curdir - head = this_path = os.path.abspath(p) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - sys.path.insert(0, head) - break - -import pypy.interpreter.unittest_w -from pypy.interpreter.testtools import * - -TestCase = pypy.interpreter.unittest_w.IntTestCase -AppTestCase = pypy.interpreter.unittest_w.AppTestCase -main = unittest.main - -if __name__ == '__main__': - runner = unittest.TextTestRunner() - runner.run(get_tests_for_dir(this_path)) Deleted: pypy/trunk/src/pypy/testwice.py ============================================================================== --- pypy/trunk/src/pypy/testwice.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,67 +0,0 @@ -import os -import unittest -import sys - -try: - head = this_path = os.path.abspath(__file__) -except NameError: - head = this_path = os.path.abspath(os.path.dirname(sys.argv[0])) -while 1: - head, tail = os.path.split(head) - if not tail: - raise EnvironmentError, "pypy not among parents of %r!" % this_path - elif tail.lower()=='pypy': - PYPYDIR = head - if PYPYDIR not in sys.path: - sys.path.insert(0, PYPYDIR) - break - -def is_flexible(dirname, modname): - filecont = open('%s/%s.py'%(dirname,modname)).read() - return filecont.find('testsupport.objspace') >= 0 - -def find_tests(root, inc_names=[], exc_names=[]): - testmods = [] - testwice = [] - def callback(arg, dirname, names): - if os.path.basename(dirname) == 'test': - parname = os.path.basename(os.path.dirname(dirname)) - if ((not inc_names) or parname in inc_names) and parname not in exc_names: - package = dirname[len(PYPYDIR)+1:].replace(os.sep, '.') - testfiles = [f[:-3] for f in names - if f.startswith('test_') and f.endswith('.py')] - for file in testfiles: - testmods.append(package + '.' + file) - if is_flexible(dirname, file): - testwice.append(package + '.' + file) - - os.path.walk(root, callback, None) - - tl = unittest.TestLoader() - - return tl.loadTestsFromNames(testmods), tl.loadTestsFromNames(testwice) - -def main(argv=None): - if argv is None: - argv = sys.argv - - inc_names = [] - exc_names = [] - - for arg in argv[1:]: - if arg.startswith('--include='): - inc_names = arg[len('--include='):].split(',') - elif arg.startswith('--exclude='): - exc_names = arg[len('--exclude='):].split(',') - else: - raise Exception, "don't know arg " + arg - - runner = unittest.TextTestRunner() - alltests, flexible = find_tests(PYPYDIR, inc_names, exc_names) - os.environ['OBJSPACE'] = '' - runner.run(alltests) - os.environ['OBJSPACE'] = 'pypy.objspace.std.objspace.StdObjSpace' - runner.run(flexible) - -if __name__ == '__main__': - main() Added: pypy/trunk/src/pypy/tool/__init__.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/tool/__init__.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1 @@ +#empty Added: pypy/trunk/src/pypy/tool/autopath.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/tool/autopath.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,76 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories dont have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.abspath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + if head not in sys.path: + sys.path.insert(0, head) + return partdir, this_dir + raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path) + +def __clone(): + """ clone master version of autopath.y into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f.seek(0) + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Added: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/tool/test.py Wed Jun 18 16:01:28 2003 @@ -0,0 +1,283 @@ +import autopath +import os, sys, unittest, re, warnings, unittest +from unittest import TestCase, TestLoader + +import pypy.interpreter.unittest_w + +IntTestCase = pypy.interpreter.unittest_w.IntTestCase +AppTestCase = pypy.interpreter.unittest_w.AppTestCase +TestCase = IntTestCase + +class MyTestSuite(unittest.TestSuite): + def __call__(self, result): + """ execute the tests, invokes underlyning unittest.__call__""" + + # XXX here is probably not the best place + # to check for test/objspace mismatch + count = self.countTestCases() + if not count: + return result + + fm = getattr(self, 'frommodule','') + if fm and fm.startswith('pypy.objspace.std') and \ + Options.spacename != 'std': + sys.stderr.write("\n%s skip for objspace %r" % ( + fm, Options.spacename)) + return result + + if fm and Options.verbose==0: + sys.stderr.write('\n%s [%d]' %(fm, count)) + result = unittest.TestSuite.__call__(self, result) + return result + + def addTest(self, test, frommodule=None): + if test.countTestCases()>0: + test.frommodule = frommodule + unittest.TestSuite.addTest(self, test) + + def __nonzero__(self): + return self.countTestCases()>0 + + +# register MyTestSuite to unittest +unittest.TestLoader.suiteClass = MyTestSuite + +class MyTestResult(unittest.TestResult): + def __init__(self): + unittest.TestResult.__init__(self) + self.successes = [] + def addSuccess(self, test): + self.successes.append(test) + +class CtsTestRunner: + def run(self, test): + import pickle + + result = MyTestResult() + sys.stdout = open('/dev/null', 'w') + sys.stderr = open('/dev/null', 'w') + test(result) + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + + ostatus = {} + if os.path.exists('testcts.pickle'): + ostatus = pickle.load(open('testcts.pickle','r')) + + status = {} + + for e in result.errors: + name = e[0].__class__.__name__ + '.' + e[0]._TestCase__testMethodName + status[name] = 'ERROR' + for f in result.failures: + name = f[0].__class__.__name__ + '.' + f[0]._TestCase__testMethodName + status[name] = 'FAILURE' + for s in result.successes: + name = s.__class__.__name__ + '.' + s._TestCase__testMethodName + status[name] = 'success' + + keys = status.keys() + keys.sort() + + for k in keys: + old = ostatus.get(k, 'success') + if k in ostatus: + del ostatus[k] + new = status[k] + if old != new: + print k, 'has transitioned from', old, 'to', new + elif new != 'success': + print k, "is still a", new + + for k in ostatus: + print k, 'was a', ostatus[k], 'was not run this time' + status[k] = ostatus[k] + + pickle.dump(status, open('testcts.pickle','w')) + + return result + +def testsuite_from_main(): + """ return test modules from __main__ + + """ + loader = unittest.TestLoader() + m = __import__('__main__') + return loader.loadTestsFromModule(m) + +def testsuite_from_dir(root, filterfunc=None, recursive=0, loader=None): + """ return test modules that optionally match filterfunc. + + all files matching the glob-pattern "test_*.py" are considered. + additionally their fully qualified python module path has + to be accepted by filterfunc (if it is not None). + """ + if Options.verbose>2: + print >>sys.stderr, "scanning for test files in", root + + if loader is None: + loader = unittest.TestLoader() + + root = os.path.abspath(root) + + suite = unittest.TestLoader.suiteClass() + for fn in os.listdir(root): + if fn.startswith('.'): + continue + fullfn = os.path.join(root, fn) + if os.path.isfile(fullfn) and \ + fn.startswith('test_') and \ + fn.endswith('.py'): + modpath = fullfn[len(autopath.pypydir)+1:-3] + modpath = 'pypy.' + modpath.replace(os.sep, '.') + if not filterfunc or filterfunc(modpath): + subsuite = loader.loadTestsFromName(modpath) + suite.addTest(subsuite, modpath) + elif recursive and os.path.isdir(fullfn): + subsuite = testsuite_from_dir(fullfn, filterfunc, 1, loader) + if subsuite: + suite._tests.extend(subsuite._tests) + return suite + +def objspace(name='', _spacecache={}): + """ return singleton ObjSpace instance. + + this is configured via the environment variable OBJSPACE + """ + name = name or Options.spacename or os.environ.get('OBJSPACE', 'trivial') + if name == 'std': + from pypy.objspace.std import Space + elif name == 'trivial': + from pypy.objspace.trivial import Space + else: + raise ValueError, "no objectspace named %s" % repr(name) + + try: + return _spacecache[name] + except KeyError: + return _spacecache.setdefault(name, Space()) + +class Options: + """ Options set by command line """ + verbose = 0 + spacename = '' + showwarning = 0 + allspaces = [] + testreldir = 0 + runcts = 0 + +class RegexFilterFunc: + """ stateful function to filter included/excluded strings via + a Regular Expression. + + An 'excluded' regular expressions has a '%' prependend. + """ + + def __init__(self, *regex): + self.exclude = [] + self.include = [] + for x in regex: + if x[:1]=='%': + self.exclude.append(re.compile(x[1:]).search) + else: + self.include.append(re.compile(x).search) + + def __call__(self, arg): + for exclude in self.exclude: + if exclude(arg): + return + if not self.include: + return arg + for include in self.include: + if include(arg): + return arg + +def print_usage(): + print >>sys.stderr, """\ +%s [-chrvST] [regex1] [regex2] [...] + + -c run CtsTestRunner (catches stdout and prints report after testing) + -h this help message + -r gather only tests relative to current dir + -v increase verbosity level (including unittest-verbosity) + -w enable warnings from warnings framework (default is off) + -S run in standard object space + -T run in trivial object space (default) + + The regular expressions regex1, regex2 ... are matched + against the full python path of a test module. A leading + '%%' before a regex means that the matching result is to + be inverted. +""" % sys.argv[0] + raise SystemExit(1) + +def process_options(argv=[]): + """ invoke this if you want to process test-switches from sys.argv""" + + if not argv: + argv[:] = sys.argv[1:] + + try: + import getopt + opts, args = getopt.getopt(argv, "chrvST") + except getopt.error, msg: + print msg + print "Try `python %s -h' for help" % sys.argv[0] + sys.exit(2) + + for k,v in opts: + if k == '-h': + print_usage() + elif k == '-c': + Options.runcts = 1 + elif k == '-r': + Options.testreldir = 1 + elif k == '-w': + Options.showwarning = 1 + elif k == '-h': + print_usage() + elif k == '-v': + Options.verbose += 1 + elif k == '-S': + Options.spacename = 'std' + Options.allspaces.append('std') + elif k == '-T': + Options.spacename = 'trivial' + Options.allspaces.append('trivial') + + return args + +def run_tests(suite): + for spacename in Options.allspaces or ['']: + run_tests_on_space(suite, spacename) + +def run_tests_on_space(suite, spacename=''): + """ run the suite on the given space """ + if Options.runcts: + runner = CtsTestRunner() # verbosity=Options.verbose+1) + else: + runner = unittest.TextTestRunner(verbosity=Options.verbose+1) + + if spacename: + Options.spacename = spacename + + warnings.defaultaction = Options.showwarning and 'default' or 'ignore' + print >>sys.stderr, "running tests via", repr(objspace()) + runner.run(suite) + +def main(root=None): + """ run this to test everything in the __main__ or + in the given root-directory (recursive)""" + args = process_options() + filterfunc = RegexFilterFunc(*args) + if Options.testreldir: + root = os.path.abspath('.') + if root is None: + suite = testsuite_from_main() + else: + suite = testsuite_from_dir(root, filterfunc, 1) + run_tests(suite) + +if __name__ == '__main__': + # test all of pypy + main(autopath.pypydir) Deleted: pypy/trunk/src/pypy/tool/test_all.py ============================================================================== --- pypy/trunk/src/pypy/tool/test_all.py Wed Jun 18 16:01:28 2003 +++ (empty file) @@ -1,75 +0,0 @@ -#!/usr/bin/python - -import sys,os,glob,inspect, unittest -from os.path import join as joinfn -from os.path import basename, dirname, abspath -sepline = '='*70 - - -def eval_dict_from(fn): - os.chdir(dirname(fn)) - d = {} - try: - execfile(fn, d) - except IOError: - pass - return d - -class exec_testfile: - def __init__(self, modfn, testfn): - self.testdict = eval_dict_from(testfn) - self.moddict = eval_dict_from(modfn) - - for name, obj in self.testdict.items(): - if inspect.isclass(obj) and issubclass(obj, unittest.TestCase) and \ - name.startswith('Test'): - self.exec_testclass(name, obj) - - def exec_testclass(self, name, obj): - if name[4:] not in self.moddict.keys(): - print repr(name), "does not correspond to a class" - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(obj, 'test')) - print "running unittest", name - unittest.TextTestRunner().run(suite) - print "finished" - - -def filetests(path): - """tests files on the given path""" - testpath = joinfn(path, 'test') - testfnames = glob.glob(testpath+os.sep+'test_*.py') - fnames = glob.glob(path+os.sep+'*.py') - - for testfn in testfnames: - print sepline - modfn = joinfn(path, basename(testfn)[5:]) - - if modfn not in fnames: - print "testfile", basename(testfn), "has no", basename(modfn) - else: - fnames.remove(modfn) - exec_testfile(modfn, testfn) - #for fn in fnames: - # print fn, "has no corresponding test?" - -def drive_tests(base): - ctests = filetests(joinfn(base, 'interpreter')) - -if __name__=='__main__': - path = dirname(abspath(sys.argv[0])) - drive, path = os.path.splitdrive(path) - path = path.split(os.sep) - - if 'pypy' not in path: - raise SystemExit, "Need to be somewhere in pypy-tree" - - while path.pop() != 'pypy': - pass - - path.insert(0, '/') - path.append('pypy') - path = drive + joinfn('/', *path) - print path, dirname(path) - sys.path.insert(0, dirname(path)) - drive_tests(path) From arigo at codespeak.net Wed Jun 18 16:18:52 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 18 Jun 2003 16:18:52 +0200 (MEST) Subject: [pypy-svn] rev 832 - in pypy/trunk/src: goals pypy pypy/appspace pypy/appspace/test pypy/interpreter pypy/interpreter/test pypy/module/test pypy/objspace/std pypy/objspace/std/test pypy/tool Message-ID: <20030618141852.C0D575C00A@thoth.codespeak.net> Author: arigo Date: Wed Jun 18 16:18:52 2003 New Revision: 832 Modified: pypy/trunk/src/goals/dis-pregoal.py (props changed) pypy/trunk/src/goals/foodbill.py (props changed) pypy/trunk/src/pypy/appspace/test/autopath.py (props changed) pypy/trunk/src/pypy/appspace/types.py (props changed) pypy/trunk/src/pypy/interpreter/autopath.py (props changed) pypy/trunk/src/pypy/interpreter/test/autopath.py (props changed) pypy/trunk/src/pypy/interpreter/threadlocals.py (props changed) pypy/trunk/src/pypy/module/test/autopath.py (props changed) pypy/trunk/src/pypy/objspace/std/slicetype.py (props changed) pypy/trunk/src/pypy/objspace/std/test/autopath.py (props changed) pypy/trunk/src/pypy/test_all.py (props changed) pypy/trunk/src/pypy/tool/__init__.py (props changed) pypy/trunk/src/pypy/tool/autopath.py (props changed) pypy/trunk/src/pypy/tool/test.py (props changed) Log: fixeol From gvanrossum at codespeak.net Thu Jun 19 03:19:31 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Thu, 19 Jun 2003 03:19:31 +0200 (MEST) Subject: [pypy-svn] rev 833 - pypy/trunk/src/pypy Message-ID: <20030619011931.3D9795A544@thoth.codespeak.net> Author: gvanrossum Date: Thu Jun 19 03:19:30 2003 New Revision: 833 Modified: pypy/trunk/src/pypy/__init__.py Log: Test commit to check my permissions. Modified: pypy/trunk/src/pypy/__init__.py ============================================================================== --- pypy/trunk/src/pypy/__init__.py (original) +++ pypy/trunk/src/pypy/__init__.py Thu Jun 19 03:19:30 2003 @@ -1 +1 @@ -# empty +# empty (to make this a package) From gvanrossum at codespeak.net Thu Jun 19 03:22:17 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Thu, 19 Jun 2003 03:22:17 +0200 (MEST) Subject: [pypy-svn] rev 834 - pypy/trunk/src/pypy Message-ID: <20030619012217.BEAD35A544@thoth.codespeak.net> Author: gvanrossum Date: Thu Jun 19 03:22:17 2003 New Revision: 834 Modified: pypy/trunk/src/pypy/__init__.py Log: Undo last change. Modified: pypy/trunk/src/pypy/__init__.py ============================================================================== --- pypy/trunk/src/pypy/__init__.py (original) +++ pypy/trunk/src/pypy/__init__.py Thu Jun 19 03:22:17 2003 @@ -1 +1 @@ -# empty (to make this a package) +# empty From rocco at codespeak.net Fri Jun 20 05:02:56 2003 From: rocco at codespeak.net (rocco at codespeak.net) Date: Fri, 20 Jun 2003 05:02:56 +0200 (MEST) Subject: [pypy-svn] rev 839 - in pypy/trunk/src/pypy: appspace/test interpreter Message-ID: <20030620030256.CB23E5A266@thoth.codespeak.net> Author: rocco Date: Fri Jun 20 05:02:56 2003 New Revision: 839 Modified: pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py pypy/trunk/src/pypy/interpreter/baseobjspace.py Log: Update test_exceptcomp.py to use new app-level testing conventions and fix exception matching in nested tuples. Modified: pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py (original) +++ pypy/trunk/src/pypy/appspace/test/test_exceptcomp.py Fri Jun 20 05:02:56 2003 @@ -3,35 +3,37 @@ New for PyPy - Could be incorporated into CPython regression tests. """ import autopath - -import unittest from pypy.tool import test -class TestExceptionComp(test.TestCase): +class TestExceptionComp(test.AppTestCase): - def test_string(self): - string = "string" - try: - raise string - except string: - pass - except: - self.fail("Identical string exceptions do not match.") + def setUp(self): + self.space = test.objspace() - def test_stringfail(self): - string1 = "string1" - string1_ = "string" + "1" - assert string1 is not string1_ - try: - raise string1 - except "string2": - self.fail("Different string exceptions match.") - except string1_: - self.fail("Non Identical string exceptions match.") - except string1: - pass - except: - self.fail("Unknown value for variable raise.") +### XXX - String exceptions depreciated? +## def test_string(self): +## string = "string" +## try: +## raise string +## except string: +## pass +## except: +## self.fail("Identical string exceptions do not match.") +## +## def test_stringfail(self): +## string1 = "string1" +## string1_ = "string" + "1" +## assert string1 is not string1_ +## try: +## raise string1 +## except "string2": +## self.fail("Different string exceptions match.") +## except string1_: +## self.fail("Non Identical string exceptions match.") +## except string1: +## pass +## except: +## self.fail("Unknown value for variable raise.") def test_exception(self): @@ -122,5 +124,15 @@ except: self.fail("Exception does not match self in nested tuple.") + def test_deeptuples(self): + try: + raise IOError + except (FloatingPointError,(OSError, + (SyntaxError,IOError,ZeroDivisionError)), + (MemoryError, NotImplementedError)): + pass + except: + self.fail("Exception does not match self in deeply nested tuple.") + if __name__ == "__main__": test.main() Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Fri Jun 20 05:02:56 2003 @@ -116,28 +116,22 @@ def exception_match(self, w_exc_type, w_check_class): """Checks if the given exception type matches 'w_check_class'.""" - #Match identical items. - w_rv = self.is_(w_exc_type, w_check_class) - if self.is_true(w_rv): - return w_rv - #Match subclasses. - try: - w_rv = self.issubtype(w_exc_type, w_check_class) - except: pass - else: - if self.is_true(w_rv): - return w_rv - #Match tuples containing identical or parent classes - try: - exclst = self.unpackiterable(w_check_class) - except: - #w_check_class is not iterable - return self.w_False - #w_check_class is iterable - for w_item in exclst: + check_list = [w_check_class] + while check_list: + w_item = check_list.pop() + #Test within iterables (i.e. tuples) + try: + exclst = self.unpackiterable(w_item) + check_list.extend(exclst) + except: + #w_check_class is not iterable + pass + #w_item should now be an Exception (or string?) + #Match identical items. w_rv = self.is_(w_exc_type, w_item) if self.is_true(w_rv): return w_rv + #Match subclasses. try: w_rv = self.issubtype(w_exc_type, w_item) except: pass From rocco at codespeak.net Fri Jun 20 03:14:11 2003 From: rocco at codespeak.net (rocco at codespeak.net) Date: Fri, 20 Jun 2003 03:14:11 +0200 (MEST) Subject: [pypy-svn] rev 838 - in pypy/trunk/src/pypy: appspace/test interpreter Message-ID: <20030620011411.713CD5A25F@thoth.codespeak.net> Author: rocco Date: Fri Jun 20 03:14:10 2003 New Revision: 838 Modified: pypy/trunk/src/pypy/appspace/test/test_exec.py pypy/trunk/src/pypy/interpreter/opcode.py pypy/trunk/src/pypy/interpreter/opcode_app.py Log: Change test_exec to new style of app level tests, update EXEC_STMT for new calling style. Modified: pypy/trunk/src/pypy/appspace/test/test_exec.py ============================================================================== --- pypy/trunk/src/pypy/appspace/test/test_exec.py (original) +++ pypy/trunk/src/pypy/appspace/test/test_exec.py Fri Jun 20 03:14:10 2003 @@ -3,11 +3,12 @@ New for PyPy - Could be incorporated into CPython regression tests. """ import autopath - -import unittest from pypy.tool import test -class TestExecStmt(test.TestCase): +class TestExecStmt(test.AppTestCase): + + def setUp(self): + self.space = test.objspace() def test_string(self): g = {} @@ -26,10 +27,14 @@ self.failUnless(g.has_key('__builtins__')) def test_invalidglobal(self): - self.failUnlessRaises(TypeError,"exec 'pass' in 1") + def f(): + exec 'pass' in 1 + self.failUnlessRaises(TypeError,f) def test_invalidlocal(self): - self.failUnlessRaises(TypeError,"exec 'pass' in {}, 2") + def f(): + exec 'pass' in {}, 2 + self.failUnlessRaises(TypeError,f) def test_codeobject(self): co = compile("a = 3", '', 'exec') @@ -63,7 +68,9 @@ self.failUnlessEqual(g['a'], 3) def test_exceptionfallthrough(self): - self.failUnlessRaises(TypeError,"exec 'raise TypeError' in {}") + def f(): + exec 'raise TypeError' in {} + self.failUnlessRaises(TypeError,f) if __name__ == "__main__": - unittest.main() + test.main() Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Fri Jun 20 03:14:10 2003 @@ -290,9 +290,8 @@ w_prog = f.space.getitem(w_tuple,f.space.wrap(0)) w_globals = f.space.getitem(w_tuple,f.space.wrap(1)) w_locals = f.space.getitem(w_tuple,f.space.wrap(2)) - newframe = pyframe.PyFrame(f.space,f.space.unwrap(w_prog),w_globals,w_locals) - ec = f.space.getexecutioncontext() - ec.eval_frame(newframe) #discard return value + + w_prog.eval_code(f.space, w_globals, w_locals) def POP_BLOCK(f): block = f.blockstack.pop() Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode_app.py Fri Jun 20 03:14:10 2003 @@ -151,7 +151,7 @@ """ import types if (globals is None and locals is None and - isinstance(prog, builtins.tuple) and + isinstance(prog, builtins['tuple']) and (len(prog) == 2 or len(prog) == 3)): globals = prog[1] if len(prog) == 3: @@ -169,7 +169,7 @@ globals['__builtins__'] = builtins if not isinstance(locals, types.DictType): raise TypeError("exec: arg 3 must be a dictionary or None") - #HACK to check for code object + # XXX - HACK to check for code object co = compile('1','','eval') if isinstance(prog, type(co)): return (prog, globals, locals) From mwh at codespeak.net Fri Jun 20 13:41:38 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 20 Jun 2003 13:41:38 +0200 (MEST) Subject: [pypy-svn] rev 841 - in pypy/trunk/src/pypy: interpreter tool Message-ID: <20030620114138.D6D425A2B7@thoth.codespeak.net> Author: mwh Date: Fri Jun 20 13:41:38 2003 New Revision: 841 Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py pypy/trunk/src/pypy/tool/test.py Log: rejig appspace tests in aid of getting better error messages. Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/unittest_w.py (original) +++ pypy/trunk/src/pypy/interpreter/unittest_w.py Fri Jun 20 13:41:38 2003 @@ -18,12 +18,13 @@ from pypy.interpreter.extmodule import make_builtin_func w = space.wrap d = space.newdict([]) + space.setitem(d, w('failureException'), space.w_AssertionError) + for name in dir(AppTestCase): - if name.startswith('assert') or name.startswith('fail'): - if hasattr(tc_w, 'app_' + name): - builtin_func = make_builtin_func(space, getattr(tc_w, "app_" + name), - boundmethod=True) - space.setitem(d, w(name), builtin_func) + if ( name.startswith('assert') or name.startswith('fail') + and name != 'failureException'): + w_func = wrap_func(space, getattr(tc_w, name).im_func) + space.setitem(d, w(name), w_func) w_tc = space.call_function(space.w_type, w('TestCase'), space.newtuple([]), @@ -49,19 +50,7 @@ setattr(s, w_tc_attr, w_tc) w_f = wrap_func(s, self.testMethod.im_func) - try: - s.call_function(w_f, w_tc) - except executioncontext.OperationError, oe: - oe.print_application_traceback(s) - import __builtin__ - w_res = s.gethelper(pyframe.appfile).call( - "normalize_exception", [oe.w_type, oe.w_value]) - w_value = s.getitem(w_res, s.wrap(1)) - exc_name = s.getattr(s.getattr(w_value, w('__class__')), - w('__name__')) - exc_type = getattr(__builtin__, s.unwrap(exc_name)) - # it's a tad annoying we can't fake the traceback - raise exc_type(*s.unwrap(s.getattr(w_value, w('args')))) + s.call_function(w_f, w_tc) class IntTestCase(unittest.TestCase): @@ -118,40 +107,7 @@ setattr(self, self.methodName, WrappedFunc(self, getattr(self, self.methodName))) return unittest.TestCase.__call__(self, result) - + def setUp(self): from pypy.tool import test self.space = test.objspace() - - def app_fail(self, w_self, w_msg=None): - msg = self.space.unwrap(w_msg) - self.fail(msg) - - def app_failIf(self, w_self, w_expr, w_msg=None): - msg = self.space.unwrap(w_msg) - self.failIf_w(w_expr) - - def app_failUnless(self, w_self, w_expr, w_msg=None): - msg = self.space.unwrap(w_msg) - self.failUnless_w(w_expr) - - def app_failUnlessRaises(self, w_self, w_exc_class, - w_callable, *args_w, **kw_w): - self.assertWRaises_w(w_exc_class, w_callable, *args_w, **kw_w) - - def app_failUnlessEqual(self, w_self, w_first, w_second, w_msg=None): - msg = self.space.unwrap(w_msg) - self.assertEqual_w(w_first, w_second, msg) - - def app_failIfEqual(self, w_self, w_first, w_second, w_msg=None): - msg = self.space.unwrap(w_msg) - self.assertNotEqual_w(w_first, w_second, msg) - - app_assertEqual = app_assertEquals = app_failUnlessEqual - - app_assertNotEqual = app_assertNotEquals = app_failIfEqual - - app_assertRaises = app_failUnlessRaises - - app_assert_ = app_failUnless - Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Fri Jun 20 13:41:38 2003 @@ -1,5 +1,5 @@ import autopath -import os, sys, unittest, re, warnings, unittest +import os, sys, unittest, re, warnings, unittest, traceback from unittest import TestCase, TestLoader import pypy.interpreter.unittest_w @@ -46,19 +46,61 @@ def __init__(self): unittest.TestResult.__init__(self) self.successes = [] + def addError(self, test, err): + # XXX not nice: + from pypy.interpreter.baseobjspace import OperationError + if isinstance(err[1], OperationError): + if err[1].match(test.space, test.space.w_AssertionError): + self.addFailure(test, err) + return + unittest.TestResult.addError(self, test, err) def addSuccess(self, test): self.successes.append(test) +class MyTextTestResult(unittest._TextTestResult): + def addFailure(self, test, err): + unittest._TextTestResult.addFailure(self, test, err) + def munge(self, list, test, err): + import StringIO + from pypy.interpreter.baseobjspace import OperationError + text1 = list.pop()[1] + if isinstance(err[1], OperationError): + sio = StringIO.StringIO() + err[1].print_application_traceback(test.space, sio) + text2 = sio.getvalue() + + list.append((test, text1 + "\nand at app-level:\n\n" + text2)) + else: + list.append((test, text1)) + + def addError(self, test, err): + from pypy.interpreter.baseobjspace import OperationError + if isinstance(err[1], OperationError): + if err[1].match(test.space, test.space.w_AssertionError): + self.addFailure(test, err) + return + unittest._TextTestResult.addError(self, test, err) + self.munge(self.errors, test, err) + + def addFailure(self, test, err): + unittest._TextTestResult.addFailure(self, test, err) + self.munge(self.failures, test, err) + class CtsTestRunner: def run(self, test): import pickle + output = sys.stdout result = MyTestResult() - sys.stdout = open('/dev/null', 'w') - sys.stderr = open('/dev/null', 'w') - test(result) - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + sso = sys.stdout + sse = sys.stderr + try: + sys.stdout = open('/dev/null', 'w') + sys.stderr = open('/dev/null', 'w') + test(result) + finally: + sys.stdout = sso + sys.stderr = sse ostatus = {} if os.path.exists('testcts.pickle'): @@ -67,10 +109,12 @@ status = {} for e in result.errors: - name = e[0].__class__.__name__ + '.' + e[0]._TestCase__testMethodName + name = e[0].__class__.__name__ + '.' + \ + e[0]._TestCase__testMethodName status[name] = 'ERROR' for f in result.failures: - name = f[0].__class__.__name__ + '.' + f[0]._TestCase__testMethodName + name = f[0].__class__.__name__ + '.' + \ + f[0]._TestCase__testMethodName status[name] = 'FAILURE' for s in result.successes: name = s.__class__.__name__ + '.' + s._TestCase__testMethodName @@ -85,18 +129,23 @@ del ostatus[k] new = status[k] if old != new: - print k, 'has transitioned from', old, 'to', new + print >>output, k, 'has transitioned from', old, 'to', new elif new != 'success': - print k, "is still a", new + print >>output, k, "is still a", new for k in ostatus: - print k, 'was a', ostatus[k], 'was not run this time' + print >>output, k, 'was a', ostatus[k], 'was not run this time' status[k] = ostatus[k] pickle.dump(status, open('testcts.pickle','w')) return result +class MyTextTestRunner(unittest.TextTestRunner): + def _makeResult(self): + return MyTextTestResult(self.stream, self.descriptions, self.verbosity) + + def testsuite_from_main(): """ return test modules from __main__ @@ -197,6 +246,7 @@ %s [-chrvST] [regex1] [regex2] [...] -c run CtsTestRunner (catches stdout and prints report after testing) + [unix only, for now] -h this help message -r gather only tests relative to current dir -v increase verbosity level (including unittest-verbosity) @@ -256,7 +306,7 @@ if Options.runcts: runner = CtsTestRunner() # verbosity=Options.verbose+1) else: - runner = unittest.TextTestRunner(verbosity=Options.verbose+1) + runner = MyTextTestRunner(verbosity=Options.verbose+1) if spacename: Options.spacename = spacename From mwh at codespeak.net Fri Jun 20 14:48:31 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 20 Jun 2003 14:48:31 +0200 (MEST) Subject: [pypy-svn] rev 842 - in pypy/trunk/src/pypy: interpreter module objspace/std Message-ID: <20030620124831.E4CDD5A266@thoth.codespeak.net> Author: mwh Date: Fri Jun 20 14:48:29 2003 New Revision: 842 Modified: pypy/trunk/src/pypy/interpreter/opcode.py pypy/trunk/src/pypy/interpreter/opcode_app.py pypy/trunk/src/pypy/module/builtin.py pypy/trunk/src/pypy/module/builtin_app.py pypy/trunk/src/pypy/objspace/std/cpythonobject.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/dicttype.py Log: Make appspace/test/test_exec.py pass. This involved a veritable boatload of fixes: Hacked opcode_app.py:exec_statement to only use the level of types yoga we currently support. Define some methods on issubtype to avoid blowing up quite so often (Armin probably won't like this :-). Add has_key() to dicts. unwrap the code object before execing it in EXEC_STMT (we need to think how sensible this is as a general policy, but we need to do it for now). Deal with the "wrapped defaults" problem for BuiltinModule.compile (we need to think about this, too). Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Fri Jun 20 14:48:29 2003 @@ -291,7 +291,7 @@ w_globals = f.space.getitem(w_tuple,f.space.wrap(1)) w_locals = f.space.getitem(w_tuple,f.space.wrap(2)) - w_prog.eval_code(f.space, w_globals, w_locals) + f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals) def POP_BLOCK(f): block = f.blockstack.pop() Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode_app.py Fri Jun 20 14:48:29 2003 @@ -169,18 +169,20 @@ globals['__builtins__'] = builtins if not isinstance(locals, types.DictType): raise TypeError("exec: arg 3 must be a dictionary or None") - # XXX - HACK to check for code object - co = compile('1','','eval') - if isinstance(prog, type(co)): +## # XXX - HACK to check for code object +## co = compile('1','','eval') +## print prog + if isinstance(prog, types.CodeType): return (prog, globals, locals) - if not (isinstance(prog, types.StringTypes) or - isinstance(prog, types.FileType)): + if not isinstance(prog, types.StringTypes): +## if not (isinstance(prog, types.StringTypes) or +## isinstance(prog, types.FileType)): raise TypeError("exec: arg 1 must be a string, file, or code object") - if isinstance(prog, types.FileType): - flags = 0 - ## XXX add in parent flag merging - co = compile(prog.read(),prog.name,'exec',flags,1) - return (co,globals,locals) +## if isinstance(prog, types.FileType): +## flags = 0 +## ## XXX add in parent flag merging +## co = compile(prog.read(),prog.name,'exec',flags,1) +## return (co,globals,locals) else: # prog is a string flags = 0 ## XXX add in parent flag merging Modified: pypy/trunk/src/pypy/module/builtin.py ============================================================================== --- pypy/trunk/src/pypy/module/builtin.py (original) +++ pypy/trunk/src/pypy/module/builtin.py Fri Jun 20 14:48:29 2003 @@ -78,11 +78,16 @@ supplied_flags = 0 else: supplied_flags = space.unwrap(w_supplied_flags) + if supplied_flags is None: + supplied_flags = 0 if w_dont_inherit is None: dont_inherit = 0 else: dont_inherit = space.unwrap(w_dont_inherit) + if dont_inherit is None: + dont_inherit = 0 + #print (str, filename, startstr, supplied_flags, dont_inherit) c = _b.compile(str, filename, startstr, supplied_flags, dont_inherit) res = pycode.PyByteCode() res._from_code(c) Modified: pypy/trunk/src/pypy/module/builtin_app.py ============================================================================== --- pypy/trunk/src/pypy/module/builtin_app.py (original) +++ pypy/trunk/src/pypy/module/builtin_app.py Fri Jun 20 14:48:29 2003 @@ -117,9 +117,9 @@ return 0 else: try: - return issubclass(objcls, klass_or_tuple) + return issubclass(objcls, klass_or_tuple) except TypeError: - raise TypeError, "isinstance() arg 2 must be a class or type" + raise TypeError, "isinstance() arg 2 must be a class or type" def range(x, y=None, step=1): """ returns a list of integers in arithmetic position from start (defaults Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py Fri Jun 20 14:48:29 2003 @@ -74,7 +74,7 @@ MethodImplementation = { 'id': id, 'type': type, - 'issubtype': issubclass, +# 'issubtype': issubclass, 'repr': repr, 'str': str, 'len': len, @@ -243,4 +243,11 @@ wrap_exception(space) return space.wrap(result) +def issubtype__CPython_ANY(space, w_obj, w_other): + return space.newbool(0) + +def issubtype__CPython_CPython(space, w_obj, w_other): + return space.newbool(issubclass(space.unwrap(w_obj), + space.unwrap(w_other))) + register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Fri Jun 20 14:48:29 2003 @@ -85,4 +85,8 @@ def get__ANY_ANY_ANY(space, w_descr, w_inst, w_cls): return w_descr +def issubtype__ANY_ANY(space, w_one, w_two): + # XXX -- mwh + return space.newbool(0) + register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Fri Jun 20 14:48:29 2003 @@ -79,6 +79,7 @@ def getitem__Dict_ANY(space, w_dict, w_lookup): data = w_dict.non_empties() + # XXX shouldn't this use hashing? -- mwh for w_key, cell in data: if space.is_true(space.eq(w_lookup, w_key)): return cell.get() @@ -161,4 +162,14 @@ for w_key,cell in w_self.non_empties()]) +def dict_has_key__Dict_ANY(space, w_self, w_lookup): + data = w_self.non_empties() + # XXX hashing? -- mwh + for w_key, cell in data: + if space.is_true(space.eq(w_lookup, w_key)): + return space.newbool(1) + else: + return space.newbool(0) + + register_all(vars(), W_DictType) Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Fri Jun 20 14:48:29 2003 @@ -6,7 +6,8 @@ typename = 'dict' - dict_copy = MultiMethod('copy', 1) - dict_items = MultiMethod('items', 1) - dict_keys = MultiMethod('keys', 1) - dict_values = MultiMethod('values', 1) + dict_copy = MultiMethod('copy', 1) + dict_items = MultiMethod('items', 1) + dict_keys = MultiMethod('keys', 1) + dict_values = MultiMethod('values', 1) + dict_has_key = MultiMethod('has_key', 2) From hpk at codespeak.net Sat Jun 21 11:30:27 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 11:30:27 +0200 (MEST) Subject: [pypy-svn] rev 843 - pypy/trunk/doc Message-ID: <20030621093027.7ED885AC55@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 11:30:25 2003 New Revision: 843 Added: pypy/trunk/doc/sprint-planning.txt Log: add a draft version of current sprint planning Added: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 11:30:25 2003 @@ -0,0 +1,40 @@ +LouvainLaNeuveSprint planning + +- enhance StdObjSpace, define goals achieve them + http://codespeak.net/svn/pypy/trunk/src/goals/ + + - Being able to run main.py dis.dis(dis.dis) + - Fix XXX-marked things :-) + - Unbound methods. + - support the objects we see falling back to CPython. + - more builtins. + - more things from sys. + - dict object/type + - Hash table based implementation of dictionaries? + - list object/type + - string object/type + +- do more tests + +- improve "main.py" tool and rename it to "py.py" :-) + with a subset of the options of "python". This + should allow executing commands (-c), going + interactive (-i) and executing files (argv[1]) + + - Fix the way an OBJECTSPACE is selected. + - main.py doesn't handle exceptions very well. + +- move design documentation from wiki to subversion + (doc/design) to make it locally editable (instead + of html-textfields) and keep everyone up-to-date + maybe rearrange the doc-directory to be into src/pypy + +- implement AnnotationObjSpace and the beginnings + of a C code generator + + - getting the translator to understand RPython, handling the + constructions it can and delegating the things it doesn't + understand to CPython (Mimicking Python2C) + +- discuss funding and future organization issues + From arigo at codespeak.net Sat Jun 21 14:36:59 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 21 Jun 2003 14:36:59 +0200 (MEST) Subject: [pypy-svn] rev 844 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621123659.271275A415@thoth.codespeak.net> Author: arigo Date: Sat Jun 21 14:36:58 2003 New Revision: 844 Modified: pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Log: saner delegation-to-parent-classes Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Sat Jun 21 14:36:58 2003 @@ -3,24 +3,6 @@ from pypy.objspace.std.objspace import * -# The default delegation mecanism is to allow any W_XxxObject class -# to be regarded as an instance of any of its parent classes. - -def class_to_parent_classes(space, w_obj): - converted = [] - W_Cls = w_obj.__class__ - while W_Cls is not W_Object: - assert len(W_Cls.__bases__) == 1, ( - "multimethod call with non wrapped argument: %r" % w_obj) - W_Cls, = W_Cls.__bases__ - converted.append((W_Cls, w_obj)) - return converted - -class_to_parent_classes.priority = PRIORITY_PARENT_IMPL -StdObjSpace.delegate.register(class_to_parent_classes, Ellipsis) -# 'Ellipsis' should not be used in other calls to register() - - # These are operations that must fall back to some default behavior, # but that should not appear explicitly at application-level. # There is no default object.__xxx__() method for these. Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Sat Jun 21 14:36:58 2003 @@ -126,15 +126,23 @@ MultiMethod.__init__(self, 'delegate', 1, []) def postprocessresult(self, allowedtypes, result): - # add the Ellipsis catch-all delegator(s) - for function in self.dispatch_table[Ellipsis,]: - for t in allowedtypes[0]: - result.append(((t,), function)) + by_priority = {} # classify delegators by priority + # add delegation from a class to its parent classes + arg1types, = allowedtypes + parenttypes = [] + for t in arg1types: + parenttypes += list(t.__bases__) + if parenttypes: + def delegate_to_parent_classes(space, a, parenttypes=parenttypes): + return [(t, a) for t in parenttypes] + # hard-wire it at priority 0 + by_priority[0] = [((t,), delegate_to_parent_classes) + for t in arg1types] + # sort the results in priority order, and insert None marks # between jumps in the priority values. Higher priority values # first. - by_priority = {} # classify delegators by priority for signature, function in result: assert hasattr(function, 'priority'), ( "delegator function must have a priority") @@ -189,6 +197,7 @@ class BoundMultiMethod: + ASSERT_BASE_TYPE = None def __init__(self, space, multimethod): self.space = space @@ -221,6 +230,12 @@ arity = self.multimethod.arity extraargs = args[arity:] + if self.ASSERT_BASE_TYPE: + for a in args[:arity]: + assert isinstance(a, self.ASSERT_BASE_TYPE), ( + "multimethod '%s' call with non wrapped argument: %r" % + (self.multimethod.operatorsymbol, a)) + # look for an exact match first firstfailure = None types = tuple([(a.__class__,) for a in args]) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sat Jun 21 14:36:58 2003 @@ -16,14 +16,14 @@ W_ANY = W_Object # synonyms for use in .register() -MultiMethod.ASSERT_BASE_TYPE = W_Object +BoundMultiMethod.ASSERT_BASE_TYPE = W_Object MultiMethod.BASE_TYPE_OBJECT = W_AbstractTypeObject # delegation priorities -PRIORITY_SAME_TYPE = 4 # converting between several impls of the same type -PRIORITY_PARENT_TYPE = 3 # converting to a base type (e.g. bool -> int) -PRIORITY_PARENT_IMPL = 2 # this one is always done implicitely in default.py -PRIORITY_CHANGE_TYPE = 1 # changing type altogether (e.g. int -> float) +PRIORITY_SAME_TYPE = 2 # converting between several impls of the same type +PRIORITY_PARENT_TYPE = 1 # converting to a base type (e.g. bool -> int) +PRIORITY_PARENT_IMPL = 0 # hard-wired in multimethod.py +PRIORITY_CHANGE_TYPE = -1 # changing type altogether (e.g. int -> float) def registerimplementation(implcls): # this function should ultimately register the implementation class somewhere Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Sat Jun 21 14:36:58 2003 @@ -3,17 +3,7 @@ from pypy.objspace.std.multimethod import * from pypy.tool import test -# default delegator - -def class_to_parent_classes(space, w_obj): - converted = [] - W_Cls = w_obj.__class__ - while len(W_Cls.__bases__) == 1: - W_Cls, = W_Cls.__bases__ - converted.append((W_Cls, w_obj)) - return converted - -class_to_parent_classes.priority = 1 +BoundMultiMethod.ASSERT_BASE_TYPE = None class X: @@ -77,7 +67,6 @@ delegate = DelegateMultiMethod() delegate.register(from_y_to_x, Y) delegate.register(from_x_to_str_sometimes, X) - delegate.register(class_to_parent_classes, Ellipsis) def wrap(self, x): return '' % (x,) From hpk at codespeak.net Sat Jun 21 14:42:53 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 14:42:53 +0200 (MEST) Subject: [pypy-svn] rev 845 - pypy/trunk/doc Message-ID: <20030621124253.EA8855A415@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 14:42:53 2003 New Revision: 845 Modified: pypy/trunk/doc/sprint-planning.txt Log: updated sprint planning Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 14:42:53 2003 @@ -1,40 +1,72 @@ LouvainLaNeuveSprint planning -- enhance StdObjSpace, define goals achieve them +--> join this screen: ssh codespeak.net "and" screen -x hpk/hpk + +eternal goals: +- do more tests (eternal goal) +- Fix XXX-marked things + +- enhance StdObjSpace, define goals and achieve them http://codespeak.net/svn/pypy/trunk/src/goals/ - Being able to run main.py dis.dis(dis.dis) - - Fix XXX-marked things :-) - Unbound methods. - support the objects we see falling back to CPython. - more builtins. - more things from sys. - dict object/type - Hash table based implementation of dictionaries? - - list object/type - - string object/type + - list object/type + - check all other type implementation and document their state: -- do more tests + christian, tomek, holger, alex, guenter, + boolobject + cpythonobject + instmethobject + longobject + sliceobject + userobject + dictobject + intobject + moduleobject + stringobject + floatobject + iterobject + noneobject + tupleobject + + - write a small tool that checks a type's methods of + CPython against PyPy + (Jacob, Laura) - improve "main.py" tool and rename it to "py.py" :-) with a subset of the options of "python". This should allow executing commands (-c), going interactive (-i) and executing files (argv[1]) - - Fix the way an OBJECTSPACE is selected. + - Fix the way an OBJECTSPACE is selected. ? - main.py doesn't handle exceptions very well. + (michael) + - move design documentation from wiki to subversion (doc/design) to make it locally editable (instead of html-textfields) and keep everyone up-to-date maybe rearrange the doc-directory to be into src/pypy + (Anna, Laura) + +- go through the wiki and clean up "stale" or old pages + - implement AnnotationObjSpace and the beginnings - of a C code generator + of a C code generator. the basic idea is "abstract + interpretation".... - getting the translator to understand RPython, handling the constructions it can and delegating the things it doesn't understand to CPython (Mimicking Python2C) + (Armin, Guido) + - discuss funding and future organization issues From hpk at codespeak.net Sat Jun 21 14:54:51 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 14:54:51 +0200 (MEST) Subject: [pypy-svn] rev 846 - pypy/trunk/doc Message-ID: <20030621125451.0E0E65A415@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 14:54:50 2003 New Revision: 846 Modified: pypy/trunk/doc/sprint-planning.txt Log: more detailed object list Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 14:54:50 2003 @@ -20,6 +20,7 @@ - check all other type implementation and document their state: christian, tomek, holger, alex, guenter, + boolobject cpythonobject instmethobject @@ -27,9 +28,11 @@ sliceobject userobject dictobject + intobject moduleobject stringobject + listobject floatobject iterobject noneobject From tismer at codespeak.net Sat Jun 21 15:23:14 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 15:23:14 +0200 (MEST) Subject: [pypy-svn] rev 847 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621132314.AC6F75AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 15:23:14 2003 New Revision: 847 Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py pypy/trunk/src/pypy/objspace/std/booltype.py Log: reviewed, added test and tested, seems complete. Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Sat Jun 21 15:23:14 2003 @@ -1,3 +1,11 @@ +""" +Reviewed 03-06-21 +There are no new methods here, since everything is inherited +from int, except: + +__repr__ tested, OK +""" + from pypy.objspace.std.objspace import * from booltype import W_BoolType import intobject @@ -6,9 +14,9 @@ class W_BoolObject(W_Object): statictype = W_BoolType - def __init__(w_self, space, boolval):# please pass in a real bool, not an int + def __init__(w_self, space, boolval): W_Object.__init__(w_self, space) - w_self.boolval = boolval + w_self.boolval = not not boolval def __nonzero__(w_self): raise Exception, "you cannot do that, you must use space.is_true()" Modified: pypy/trunk/src/pypy/objspace/std/booltype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/booltype.py (original) +++ pypy/trunk/src/pypy/objspace/std/booltype.py Sat Jun 21 15:23:14 2003 @@ -1,3 +1,7 @@ +""" +Reviewed 03-06-21 +""" + from pypy.objspace.std.objspace import * from typeobject import W_TypeObject from inttype import W_IntType From tismer at codespeak.net Sat Jun 21 15:23:37 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 15:23:37 +0200 (MEST) Subject: [pypy-svn] rev 848 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030621132337.587F65AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 15:23:36 2003 New Revision: 848 Added: pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py Log: reviewed, added test and tested, seems complete. Added: pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py Sat Jun 21 15:23:36 2003 @@ -0,0 +1,28 @@ +import autopath +from pypy.tool import test + + +class TestW_BoolObject(test.TestCase): + + def setUp(self): + self.space = test.objspace() + self.true = self.space.w_True + self.false = self.space.w_False + self.wrap = self.space.wrap + + def tearDown(self): + pass + + def test_repr(self): + self.assertEqual_w(self.space.repr(self.true), self.wrap("True")) + self.assertEqual_w(self.space.repr(self.false), self.wrap("False")) + + def test_true(self): + self.failUnless_w(self.true) + + def test_false(self): + self.failIf_w(self.false) + + +if __name__ == '__main__': + test.main() From tismer at codespeak.net Sat Jun 21 15:25:05 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 15:25:05 +0200 (MEST) Subject: [pypy-svn] rev 849 - pypy/trunk/doc Message-ID: <20030621132505.585D25AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 15:25:05 2003 New Revision: 849 Modified: pypy/trunk/doc/sprint-planning.txt Log: bool done Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 15:25:05 2003 @@ -21,7 +21,7 @@ christian, tomek, holger, alex, guenter, - boolobject + boolobject done cpythonobject instmethobject longobject From hpk at codespeak.net Sat Jun 21 16:20:37 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 16:20:37 +0200 (MEST) Subject: [pypy-svn] rev 850 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030621142037.7EE1C5AAA7@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 16:20:37 2003 New Revision: 850 Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: added some tests at application level Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sat Jun 21 16:20:37 2003 @@ -114,5 +114,20 @@ w_slice = space.newslice(w(1), w_None, w(2)) self.assertEqual_w(space.getitem(w_str, w_slice), w('el')) +class TestStringObject(test.AppTestCase): + def test_split(self): + self.assertEquals("".split(), []) + self.assertEquals("a".split(), ['a']) + self.assertEquals("a b c".split(), ['a','b','c']) + + def test_split_splitchar(self): + self.assertEquals("/a/b/c".split('/'), ['','a','b','c']) + + def test_ljust(self): + self.assertEquals("abc".ljust(5), "abc ") + + def _notimpl_test_split_maxsplit(self): + self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) + if __name__ == '__main__': test.main() From hpk at codespeak.net Sat Jun 21 16:21:40 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 16:21:40 +0200 (MEST) Subject: [pypy-svn] rev 851 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621142140.3C69C5AAA7@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 16:21:39 2003 New Revision: 851 Modified: pypy/trunk/src/pypy/objspace/std/moduleobject.py Log: added some code review information at top-docstring Modified: pypy/trunk/src/pypy/objspace/std/moduleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/moduleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/moduleobject.py Sat Jun 21 16:21:39 2003 @@ -1,3 +1,12 @@ +""" +state of W_ModuleObject + +- old style registration + +getattr ok,tested +setattr ok,tested +delattr ok,tested +""" from pypy.objspace.std.objspace import * from moduletype import W_ModuleType from dictobject import W_DictObject @@ -14,10 +23,8 @@ (w_key_doc, space.w_None)] w_self.w_dict = W_DictObject(w_self.space, items) - registerimplementation(W_ModuleObject) - def getattr_module_any(space, w_module, w_attr): if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): return w_module.w_dict From tismer at codespeak.net Sat Jun 21 16:25:08 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 16:25:08 +0200 (MEST) Subject: [pypy-svn] rev 852 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621142508.517945AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 16:25:07 2003 New Revision: 852 Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py Log: reviewed, added test and tested, seems complete. Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py Sat Jun 21 16:25:07 2003 @@ -1,3 +1,14 @@ +""" +Reviewed 03-06-21 +This is an extremely general object, so the tests are +a carefully choosen sample, rather than a complete coverage. +Exception wrapping is tested and ok. +Inplace operators are untested, but quite obvious by inspection. +Some operators and functions (both unary and binary) are tested. +Inspection of table MethodImplementations is necessary and +sufficient to ensure completeness and correctness of this module. +""" + from pypy.objspace.std.objspace import * from stringobject import W_StringObject import sys, operator, types Modified: pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_cpythonobject.py Sat Jun 21 16:25:07 2003 @@ -63,19 +63,29 @@ w_result = getattr(self.space, op)(w1, w2) self.assertEquals(self.space.unwrap(w_result), expected) - def test_hash(self): - # i don't understand this test -- mwh + def test_unhashable(self): w1 = self.space.wrap(self.stuff) - try: - self.space.hash(w1) + self.assertRaises(OperationError, self.space.hash, w1) + try: self.space.hash(w1) except OperationError, e: - self.assertEquals(e.w_type.cpyobj, TypeError) + self.assertEquals(e.w_type.cpyobj, TypeError) + def test_hashable(self): + uw = 3+4j + w1 = self.space.wrap(uw) + hash_result = self.space.hash(w1) + self.assertEquals(self.space.unwrap(hash_result), hash(uw)) + def test_call(self): w1 = self.space.wrap(len) w_result = self.space.call(w1, self.space.wrap(("hello world",)), self.space.wrap({})) self.assertEquals(self.space.unwrap(w_result), 11) + def test_next(self): + # create something with a next + nx = self.space.wrap(iter(self.stuff)) + self.assertEqual_w(self.space.wrap(5), self.space.next(nx)) + if __name__ == '__main__': test.main() From tismer at codespeak.net Sat Jun 21 16:26:46 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 16:26:46 +0200 (MEST) Subject: [pypy-svn] rev 853 - pypy/trunk/doc Message-ID: <20030621142646.588C95AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 16:26:46 2003 New Revision: 853 Modified: pypy/trunk/doc/sprint-planning.txt Log: cpython done Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 16:26:46 2003 @@ -22,7 +22,7 @@ christian, tomek, holger, alex, guenter, boolobject done - cpythonobject + cpythonobject done instmethobject longobject sliceobject From tismer at codespeak.net Sat Jun 21 16:51:45 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 16:51:45 +0200 (MEST) Subject: [pypy-svn] rev 854 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621145145.E42825AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 16:51:45 2003 New Revision: 854 Added: pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py Modified: pypy/trunk/src/pypy/objspace/std/instmethtype.py Log: reviewed, added test and tested, incomplete (see docstring). Modified: pypy/trunk/src/pypy/objspace/std/instmethtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethtype.py Sat Jun 21 16:51:45 2003 @@ -1,3 +1,7 @@ +""" +Reviewed 03-06-21 +""" + from pypy.objspace.std.objspace import * from typeobject import W_TypeObject Added: pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py Sat Jun 21 16:51:45 2003 @@ -0,0 +1,17 @@ +import autopath +from pypy.tool import test + +class TestInstMethObject(test.AppTestCase): + def test_callBound(self): + boundMethod = [1,2,3].__len__ + self.assertEquals(boundMethod(), 3) + self.assertRaises(TypeError, boundMethod, 333) + def notworking_test_callUnbound(self): + unboundMethod = list.__len__ + self.assertEquals(unboundMethod([1,2,3]), 3) + self.assertRaises(TypeError, unboundMethod) + self.assertRaises(TypeError, unboundMethod, 333) + self.assertRaises(TypeError, unboundMethod, [1,2,3], 333) + +if __name__ == '__main__': + test.main() From tismer at codespeak.net Sat Jun 21 16:52:06 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 16:52:06 +0200 (MEST) Subject: [pypy-svn] rev 855 - pypy/trunk/doc Message-ID: <20030621145206.8DC475AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 16:52:06 2003 New Revision: 855 Modified: pypy/trunk/doc/sprint-planning.txt Log: instmeth done Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 16:52:06 2003 @@ -23,7 +23,7 @@ boolobject done cpythonobject done - instmethobject + instmethobject done longobject sliceobject userobject From tismer at codespeak.net Sat Jun 21 16:52:36 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 16:52:36 +0200 (MEST) Subject: [pypy-svn] rev 856 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621145236.034C15AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 16:52:35 2003 New Revision: 856 Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py Log: reviewed, added test and tested, incomplete (see docstring). Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Sat Jun 21 16:52:35 2003 @@ -1,3 +1,18 @@ +""" +Reviewed 03-06-21 +This object should implement both bound and unbound methods. +Currently, the bound methods work: +__call__ tested, OK. + +Unbound methods do not work yet (test is broken) at least in +application space. Changing this module to make them work +would be easy: test in call__InstMeth_ANY_ANY if w_instmeth +is None; if so, insert nothing in the arguments, but rather +perform a typetest on the first argument. However, this would +not be testable until getattr on a typeobject will return an +unbound-method, which, so far, it doesn't yet. +""" + from __future__ import nested_scopes from pypy.objspace.std.objspace import * from instmethtype import W_InstMethType @@ -14,20 +29,6 @@ registerimplementation(W_InstMethObject) - -#def function_unwrap(space, w_function): -# # XXX this is probably a temporary hack -# def proxy_function(*args, **kw): -# w_arguments = space.wrap(args) -# w_keywords = space.wrap(kw) -# w_result = func_call(space, w_function, w_arguments, w_keywords) -# return space.unwrap(w_result) -# # XXX no closure implemented -# return proxy_function -# -#StdObjSpace.unwrap.register(function_unwrap, W_FuncObject) - - def call__InstMeth_ANY_ANY(space, w_instmeth, w_arguments, w_keywords): w_args = space.add(space.newtuple([w_instmeth.w_im_self]), w_arguments) From arigo at codespeak.net Sat Jun 21 17:00:34 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 21 Jun 2003 17:00:34 +0200 (MEST) Subject: [pypy-svn] rev 857 - in pypy/trunk/src/pypy/objspace/ann: . test Message-ID: <20030621150034.15D845AAA7@thoth.codespeak.net> Author: arigo Date: Sat Jun 21 17:00:33 2003 New Revision: 857 Added: pypy/trunk/src/pypy/objspace/ann/ (props changed) pypy/trunk/src/pypy/objspace/ann/__init__.py (contents, props changed) pypy/trunk/src/pypy/objspace/ann/objspace.py (contents, props changed) pypy/trunk/src/pypy/objspace/ann/test/ (props changed) pypy/trunk/src/pypy/objspace/ann/test/autopath.py - copied unchanged from rev 845, pypy/trunk/src/pypy/interpreter/test/autopath.py pypy/trunk/src/pypy/objspace/ann/test/test_simple.py (contents, props changed) Log: first passing test for AnnotationObjSpace Added: pypy/trunk/src/pypy/objspace/ann/__init__.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/ann/__init__.py Sat Jun 21 17:00:33 2003 @@ -0,0 +1,2 @@ +from objspace import AnnotationObjSpace +Space = AnnotationObjSpace Added: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sat Jun 21 17:00:33 2003 @@ -0,0 +1,87 @@ +from __future__ import nested_scopes +import operator +from pypy.interpreter.baseobjspace import * + + +class W_Object: + pass + +class W_Anything(W_Object): + pass + +class W_Constant(W_Object): + def __init__(self, value): + self.value = value + def __repr__(self): + return '' % self.value + + +class AnnException(Exception): + pass + + +class AnnotationObjSpace(ObjSpace): + + def initialize(self): + self.w_None = self.wrap(None) + self.w_True = self.wrap(True) + self.w_False = self.wrap(False) + self.w_NotImplemented = self.wrap(NotImplemented) + self.w_Ellipsis = self.wrap(Ellipsis) + import __builtin__, types + for n, c in __builtin__.__dict__.iteritems(): + if isinstance(c, (types.TypeType, Exception)): + setattr(self, 'w_' + c.__name__, self.wrap(c)) + self.w_builtins = self.wrap(__builtin__) + + def wrap(self, obj): + return W_Constant(obj) + + def unwrap(self, w_obj): + if isinstance(w_obj, W_Constant): + return w_obj.value + else: + raise AnnException, "Cannot unwrap %r" % w_obj + + def newtuple(self, args_w): + return W_Anything() + + def newdict(self, items_w): + for w_key, w_value in items_w: + if (not isinstance(w_key, W_Constant) or + not isinstance(w_value, W_Constant)): + break + else: + d = {} + for w_key, w_value in items_w: + d[self.unwrap(w_key)] = self.unwrap(w_value) + return self.wrap(d) + + return W_Anything() + + def newmodule(self, w_name): + return W_Anything() + + def newfunction(self, *stuff): + return W_Anything() + + + +def make_op(name, symbol, arity, specialnames): + + def generic_operator(space, *args_w): + assert len(args_w) == arity, "got a wrong number of arguments" + for w_arg in args_w: + if not isinstance(w_arg, W_Constant): + break + else: + # all arguments are constants, call the operator now + op = getattr(operator, name) + return op(*[space.unwrap(w_arg) for w_arg in args_w]) + + return W_Anything() + + setattr(AnnotationObjSpace, name, generic_operator) + +for line in ObjSpace.MethodTable: + make_op(*line) Added: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sat Jun 21 17:00:33 2003 @@ -0,0 +1,34 @@ +import autopath +from pypy.tool import test +from pypy.objspace.ann.objspace import W_Object, W_Anything, AnnotationObjSpace +from pypy.interpreter import baseobjspace, executioncontext, pyframe + +class TestAnnotationObjSpace(test.TestCase): + + def codetest(self, source, functionname, args_w): + """Compile and run the given code string, and then call its function + named by 'functionname' with a list of wrapped arguments 'args_w'. + It returns the wrapped result.""" + + glob = {} + exec source in glob + + space = self.space + w_args = space.newtuple(args_w) + w_func = space.wrap(glob[functionname]) + w_kwds = space.newdict([]) + return space.call(w_func, w_args, w_kwds) + + def setUp(self): + self.space = AnnotationObjSpace() + + def test_simple1(self): + x = self.codetest(''' +def f(i): + return i+1 +''', 'f', [W_Anything()]) + self.assert_(isinstance(x, W_Anything)) + + +if __name__ == '__main__': + test.main() From tismer at codespeak.net Sat Jun 21 17:17:09 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 17:17:09 +0200 (MEST) Subject: [pypy-svn] rev 858 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621151709.572505AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 17:17:08 2003 New Revision: 858 Modified: pypy/trunk/src/pypy/objspace/std/longobject.py pypy/trunk/src/pypy/objspace/std/longobject_app.py pypy/trunk/src/pypy/objspace/std/objspace.py Log: reviewed, an early attempt that had never been completed and should be removed. Modified: pypy/trunk/src/pypy/objspace/std/longobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/longobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/longobject.py Sat Jun 21 17:17:08 2003 @@ -1,3 +1,11 @@ +""" +Reviewed 03-06-21 +This isn't used at all, nor tested, and is totally cheating. +There isn't even any corresponding longtype. Should perhaps +be just removed. +""" + + from pypy.objspace.std.objspace import * Modified: pypy/trunk/src/pypy/objspace/std/longobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/longobject_app.py (original) +++ pypy/trunk/src/pypy/objspace/std/longobject_app.py Sat Jun 21 17:17:08 2003 @@ -1,3 +1,11 @@ +""" +Reviewed 03-06-21 +This isn't used at all, nor tested, and is totally cheating. +It even has a syntax error...! +There isn't even any corresponding longtype. Should perhaps +be just removed. +""" + def long_getattr(i, attr): if attr == "__class__": return int Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sat Jun 21 17:17:08 2003 @@ -1,3 +1,9 @@ +""" +without intending to test objectspace, we discovered +some unforeseen wrapping of PyByteCode. +XXX further analysis needed. +""" + import pypy.interpreter.appfile from pypy.interpreter.baseobjspace import * from multimethod import * @@ -211,6 +217,8 @@ wrappeditems = [self.wrap(item) for item in x] import listobject return listobject.W_ListObject(self, wrappeditems) + # print "wrapping %r (%s)" % (x, type(x)) + # XXX unexpected wrapping of PyByteCode import cpythonobject return cpythonobject.W_CPythonObject(self, x) From mwh at codespeak.net Sat Jun 21 17:17:29 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 17:17:29 +0200 (MEST) Subject: [pypy-svn] rev 859 - pypy/trunk/src/pypy/tool Message-ID: <20030621151729.14B8B5AAA7@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 17:17:28 2003 New Revision: 859 Added: pypy/trunk/src/pypy/tool/optik.py Modified: pypy/trunk/src/pypy/tool/test.py Log: convert tool/test.py to use optik for option processing add optik.py (brutally & probably suboptimally converted from optik 1.4.1) Added: pypy/trunk/src/pypy/tool/optik.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/tool/optik.py Sat Jun 21 17:17:28 2003 @@ -0,0 +1,1667 @@ +"""optik + +A powerful, extensible, and easy-to-use command-line parser for Python. + +By Greg Ward + +See http://optik.sourceforge.net/ +""" + +"""optik.errors + +Exception classes used by Optik. +""" + +# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. +# See the README.txt distributed with Optik for licensing terms. + +# created 2001/10/17 GPW (from optik.py) + +import sys +import types, os +import string, re + +class OptikError (Exception): + def __init__ (self, msg): + self.msg = msg + + def __str__ (self): + return self.msg + + +class OptionError (OptikError): + """ + Raised if an Option instance is created with invalid or + inconsistent arguments. + """ + + def __init__ (self, msg, option): + self.msg = msg + self.option_id = str(option) + + def __str__ (self): + if self.option_id: + return "option %s: %s" % (self.option_id, self.msg) + else: + return self.msg + +class OptionConflictError (OptionError): + """ + Raised if conflicting options are added to an OptionParser. + """ + +class OptionValueError (OptikError): + """ + Raised if an invalid option value is encountered on the command + line. + """ + +class BadOptionError (OptikError): + """ + Raised if an invalid or ambiguous option is seen on the command-line. + """ + + +class HelpFormatter: + + """ + Abstract base class for formatting option help. OptionParser + instances should use one of the HelpFormatter subclasses for + formatting help; by default IndentedHelpFormatter is used. + + Instance attributes: + indent_increment : int + the number of columns to indent per nesting level + max_help_position : int + the maximum starting column for option help text + help_position : int + the calculated starting column for option help text; + initially the same as the maximum + width : int + total number of columns for output + level : int + current indentation level + current_indent : int + current indentation level (in columns) + help_width : int + number of columns available for option help text (calculated) + """ + + def __init__ (self, + indent_increment, + max_help_position, + width, + short_first): + self.indent_increment = indent_increment + self.help_position = self.max_help_position = max_help_position + self.width = width + self.current_indent = 0 + self.level = 0 + self.help_width = width - max_help_position + self.short_first = short_first + + def indent (self): + self.current_indent += self.indent_increment + self.level += 1 + + def dedent (self): + self.current_indent -= self.indent_increment + assert self.current_indent >= 0, "Indent decreased below 0." + self.level -= 1 + + def format_usage (self, usage): + raise NotImplementedError, "subclasses must implement" + + def format_heading (self, heading): + raise NotImplementedError, "subclasses must implement" + + def format_description (self, description): + desc_width = self.width - self.current_indent + indent = " "*self.current_indent + return fill(description, desc_width, + initial_indent=indent, + subsequent_indent=indent) + + def format_option (self, option): + # The help for each option consists of two parts: + # * the opt strings and metavars + # eg. ("-x", or "-fFILENAME, --file=FILENAME") + # * the user-supplied help string + # eg. ("turn on expert mode", "read data from FILENAME") + # + # If possible, we write both of these on the same line: + # -x turn on expert mode + # + # But if the opt string list is too long, we put the help + # string on a second line, indented to the same column it would + # start in if it fit on the first line. + # -fFILENAME, --file=FILENAME + # read data from FILENAME + result = [] + opts = option.option_strings + opt_width = self.help_position - self.current_indent - 2 + if len(opts) > opt_width: + opts = "%*s%s\n" % (self.current_indent, "", opts) + indent_first = self.help_position + else: # start help on same line as opts + opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts) + indent_first = 0 + result.append(opts) + if option.help: + help_lines = wrap(option.help, self.help_width) + result.append("%*s%s\n" % (indent_first, "", help_lines[0])) + result.extend(["%*s%s\n" % (self.help_position, "", line) + for line in help_lines[1:]]) + elif opts[-1] != "\n": + result.append("\n") + return "".join(result) + + def store_option_strings (self, parser): + self.indent() + max_len = 0 + for opt in parser.option_list: + strings = self.format_option_strings(opt) + opt.option_strings = strings + max_len = max(max_len, len(strings) + self.current_indent) + self.indent() + for group in parser.option_groups: + for opt in group.option_list: + strings = self.format_option_strings(opt) + opt.option_strings = strings + max_len = max(max_len, len(strings) + self.current_indent) + self.dedent() + self.dedent() + self.help_position = min(max_len + 2, self.max_help_position) + + def format_option_strings (self, option): + """Return a comma-separated list of option strings & metavariables.""" + if option.takes_value(): + metavar = option.metavar or option.dest.upper() + short_opts = [sopt + metavar for sopt in option._short_opts] + long_opts = [lopt + "=" + metavar for lopt in option._long_opts] + else: + short_opts = option._short_opts + long_opts = option._long_opts + + if self.short_first: + opts = short_opts + long_opts + else: + opts = long_opts + short_opts + + return ", ".join(opts) + +class IndentedHelpFormatter (HelpFormatter): + """Format help with indented section bodies. + """ + + def __init__ (self, + indent_increment=2, + max_help_position=24, + width=80, + short_first=1): + HelpFormatter.__init__( + self, indent_increment, max_help_position, width, short_first) + + def format_usage (self, usage): + return "usage: %s\n" % usage + + def format_heading (self, heading): + return "%*s%s:\n" % (self.current_indent, "", heading) + + +class TitledHelpFormatter (HelpFormatter): + """Format help with underlined section headers. + """ + + def __init__ (self, + indent_increment=0, + max_help_position=24, + width=80, + short_first=0): + HelpFormatter.__init__ ( + self, indent_increment, max_help_position, width, short_first) + + def format_usage (self, usage): + return "%s %s\n" % (self.format_heading("Usage"), usage) + + def format_heading (self, heading): + return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading)) +"""optik.option + +Defines the Option class and some standard value-checking functions. +""" + +# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. +# See the README.txt distributed with Optik for licensing terms. + +# created 2001/10/17, GPW (from optik.py) + + +# Do the right thing with boolean values for all known Python versions. +try: + True, False +except NameError: + (True, False) = (1, 0) + +_builtin_cvt = { "int" : (int, "integer"), + "long" : (long, "long integer"), + "float" : (float, "floating-point"), + "complex" : (complex, "complex") } + +def check_builtin (option, opt, value): + (cvt, what) = _builtin_cvt[option.type] + try: + return cvt(value) + except ValueError: + raise OptionValueError( + #"%s: invalid %s argument %r" % (opt, what, value)) + "option %s: invalid %s value: %r" % (opt, what, value)) + +def check_choice(option, opt, value): + if value in option.choices: + return value + else: + choices = ", ".join(map(repr, option.choices)) + raise OptionValueError( + "option %s: invalid choice: %r (choose from %s)" + % (opt, value, choices)) + +# Not supplying a default is different from a default of None, +# so we need an explicit "not supplied" value. +NO_DEFAULT = "NO"+"DEFAULT" + + +class Option: + """ + Instance attributes: + _short_opts : [string] + _long_opts : [string] + + action : string + type : string + dest : string + default : any + nargs : int + const : any + choices : [string] + callback : function + callback_args : (any*) + callback_kwargs : { string : any } + help : string + metavar : string + """ + + # The list of instance attributes that may be set through + # keyword args to the constructor. + ATTRS = ['action', + 'type', + 'dest', + 'default', + 'nargs', + 'const', + 'choices', + 'callback', + 'callback_args', + 'callback_kwargs', + 'help', + 'metavar'] + + # The set of actions allowed by option parsers. Explicitly listed + # here so the constructor can validate its arguments. + ACTIONS = ("store", + "store_const", + "store_true", + "store_false", + "append", + "count", + "callback", + "help", + "version") + + # The set of actions that involve storing a value somewhere; + # also listed just for constructor argument validation. (If + # the action is one of these, there must be a destination.) + STORE_ACTIONS = ("store", + "store_const", + "store_true", + "store_false", + "append", + "count") + + # The set of actions for which it makes sense to supply a value + # type, ie. where we expect an argument to this option. + TYPED_ACTIONS = ("store", + "append", + "callback") + + # The set of known types for option parsers. Again, listed here for + # constructor argument validation. + TYPES = ("string", "int", "long", "float", "complex", "choice") + + # Dictionary of argument checking functions, which convert and + # validate option arguments according to the option type. + # + # Signature of checking functions is: + # check(option : Option, opt : string, value : string) -> any + # where + # option is the Option instance calling the checker + # opt is the actual option seen on the command-line + # (eg. "-a", "--file") + # value is the option argument seen on the command-line + # + # The return value should be in the appropriate Python type + # for option.type -- eg. an integer if option.type == "int". + # + # If no checker is defined for a type, arguments will be + # unchecked and remain strings. + TYPE_CHECKER = { "int" : check_builtin, + "long" : check_builtin, + "float" : check_builtin, + "complex" : check_builtin, + "choice" : check_choice, + } + + + # CHECK_METHODS is a list of unbound method objects; they are called + # by the constructor, in order, after all attributes are + # initialized. The list is created and filled in later, after all + # the methods are actually defined. (I just put it here because I + # like to define and document all class attributes in the same + # place.) Subclasses that add another _check_*() method should + # define their own CHECK_METHODS list that adds their check method + # to those from this class. + CHECK_METHODS = None + + + # -- Constructor/initialization methods ---------------------------- + + def __init__ (self, *opts, **attrs): + # Set _short_opts, _long_opts attrs from 'opts' tuple. + # Have to be set now, in case no option strings are supplied. + self._short_opts = [] + self._long_opts = [] + opts = self._check_opt_strings(opts) + self._set_opt_strings(opts) + + # Set all other attrs (action, type, etc.) from 'attrs' dict + self._set_attrs(attrs) + + # Check all the attributes we just set. There are lots of + # complicated interdependencies, but luckily they can be farmed + # out to the _check_*() methods listed in CHECK_METHODS -- which + # could be handy for subclasses! The one thing these all share + # is that they raise OptionError if they discover a problem. + for checker in self.CHECK_METHODS: + checker(self) + + def _check_opt_strings (self, opts): + # Filter out None because early versions of Optik had exactly + # one short option and one long option, either of which + # could be None. + opts = filter(None, opts) + if not opts: + raise TypeError("at least one option string must be supplied") + return opts + + def _set_opt_strings (self, opts): + for opt in opts: + if len(opt) < 2: + raise OptionError( + "invalid option string %r: " + "must be at least two characters long" % opt, self) + elif len(opt) == 2: + if not (opt[0] == "-" and opt[1] != "-"): + raise OptionError( + "invalid short option string %r: " + "must be of the form -x, (x any non-dash char)" % opt, + self) + self._short_opts.append(opt) + else: + if not (opt[0:2] == "--" and opt[2] != "-"): + raise OptionError( + "invalid long option string %r: " + "must start with --, followed by non-dash" % opt, + self) + self._long_opts.append(opt) + + def _set_attrs (self, attrs): + for attr in self.ATTRS: + if attrs.has_key(attr): + setattr(self, attr, attrs[attr]) + del attrs[attr] + else: + if attr == 'default': + setattr(self, attr, NO_DEFAULT) + else: + setattr(self, attr, None) + if attrs: + raise OptionError( + "invalid keyword arguments: %s" % ", ".join(attrs.keys()), + self) + + + # -- Constructor validation methods -------------------------------- + + def _check_action (self): + if self.action is None: + self.action = "store" + elif self.action not in self.ACTIONS: + raise OptionError("invalid action: %r" % self.action, self) + + def _check_type (self): + if self.type is None: + # XXX should factor out another class attr here: list of + # actions that *require* a type + if self.action in ("store", "append"): + if self.choices is not None: + # The "choices" attribute implies "choice" type. + self.type = "choice" + else: + # No type given? "string" is the most sensible default. + self.type = "string" + else: + if self.type not in self.TYPES: + raise OptionError("invalid option type: %r" % self.type, self) + if self.action not in self.TYPED_ACTIONS: + raise OptionError( + "must not supply a type for action %r" % self.action, self) + + def _check_choice(self): + if self.type == "choice": + if self.choices is None: + raise OptionError( + "must supply a list of choices for type 'choice'", self) + elif type(self.choices) not in (types.TupleType, types.ListType): + raise OptionError( + "choices must be a list of strings ('%s' supplied)" + % str(type(self.choices)).split("'")[1], self) + elif self.choices is not None: + raise OptionError( + "must not supply choices for type %r" % self.type, self) + + def _check_dest (self): + if self.action in self.STORE_ACTIONS and self.dest is None: + # No destination given, and we need one for this action. + # Glean a destination from the first long option string, + # or from the first short option string if no long options. + if self._long_opts: + # eg. "--foo-bar" -> "foo_bar" + self.dest = self._long_opts[0][2:].replace('-', '_') + else: + self.dest = self._short_opts[0][1] + + def _check_const (self): + if self.action != "store_const" and self.const is not None: + raise OptionError( + "'const' must not be supplied for action %r" % self.action, + self) + + def _check_nargs (self): + if self.action in self.TYPED_ACTIONS: + if self.nargs is None: + self.nargs = 1 + elif self.nargs is not None: + raise OptionError( + "'nargs' must not be supplied for action %r" % self.action, + self) + + def _check_callback (self): + if self.action == "callback": + if not callable(self.callback): + raise OptionError( + "callback not callable: %r" % self.callback, self) + if (self.callback_args is not None and + type(self.callback_args) is not types.TupleType): + raise OptionError( + "callback_args, if supplied, must be a tuple: not %r" + % self.callback_args, self) + if (self.callback_kwargs is not None and + type(self.callback_kwargs) is not types.DictType): + raise OptionError( + "callback_kwargs, if supplied, must be a dict: not %r" + % self.callback_kwargs, self) + else: + if self.callback is not None: + raise OptionError( + "callback supplied (%r) for non-callback option" + % self.callback, self) + if self.callback_args is not None: + raise OptionError( + "callback_args supplied for non-callback option", self) + if self.callback_kwargs is not None: + raise OptionError( + "callback_kwargs supplied for non-callback option", self) + + + CHECK_METHODS = [_check_action, + _check_type, + _check_choice, + _check_dest, + _check_const, + _check_nargs, + _check_callback] + + + # -- Miscellaneous methods ----------------------------------------- + + def __str__ (self): + return "/".join(self._short_opts + self._long_opts) + + def takes_value (self): + return self.type is not None + + + # -- Processing methods -------------------------------------------- + + def check_value (self, opt, value): + checker = self.TYPE_CHECKER.get(self.type) + if checker is None: + return value + else: + return checker(self, opt, value) + + def process (self, opt, value, values, parser): + + # First, convert the value(s) to the right type. Howl if any + # value(s) are bogus. + if value is not None: + if self.nargs == 1: + value = self.check_value(opt, value) + else: + value = tuple([self.check_value(opt, v) for v in value]) + + # And then take whatever action is expected of us. + # This is a separate method to make life easier for + # subclasses to add new actions. + return self.take_action( + self.action, self.dest, opt, value, values, parser) + + def take_action (self, action, dest, opt, value, values, parser): + if action == "store": + setattr(values, dest, value) + elif action == "store_const": + setattr(values, dest, self.const) + elif action == "store_true": + setattr(values, dest, True) + elif action == "store_false": + setattr(values, dest, False) + elif action == "append": + values.ensure_value(dest, []).append(value) + elif action == "count": + setattr(values, dest, values.ensure_value(dest, 0) + 1) + elif action == "callback": + args = self.callback_args or () + kwargs = self.callback_kwargs or {} + self.callback(self, opt, value, parser, *args, **kwargs) + elif action == "help": + parser.print_help() + sys.exit(0) + elif action == "version": + parser.print_version() + sys.exit(0) + else: + raise RuntimeError, "unknown action %r" % self.action + + return 1 + +# class Option +"""optik.option_parser + +Provides the OptionParser and Values classes. +""" + +# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. +# See the README.txt distributed with Optik for licensing terms. + +# created 2001/10/17, GPW (from optik.py) + + + +def get_prog_name (): + return os.path.basename(sys.argv[0]) + + +SUPPRESS_HELP = "SUPPRESS"+"HELP" +SUPPRESS_USAGE = "SUPPRESS"+"USAGE" + +STD_HELP_OPTION = Option("-h", "--help", + action="help", + help="show this help message and exit") +STD_VERSION_OPTION = Option("--version", + action="version", + help="show program's version number and exit") + + +class Values: + + def __init__ (self, defaults=None): + if defaults: + for (attr, val) in defaults.items(): + setattr(self, attr, val) + + def __repr__ (self): + return ("<%s at 0x%x: %r>" + % (self.__class__.__name__, id(self), self.__dict__)) + + def _update_careful (self, dict): + """ + Update the option values from an arbitrary dictionary, but only + use keys from dict that already have a corresponding attribute + in self. Any keys in dict without a corresponding attribute + are silently ignored. + """ + for attr in dir(self): + if dict.has_key(attr): + dval = dict[attr] + if dval is not None: + setattr(self, attr, dval) + + def _update_loose (self, dict): + """ + Update the option values from an arbitrary dictionary, + using all keys from the dictionary regardless of whether + they have a corresponding attribute in self or not. + """ + self.__dict__.update(dict) + + def _update (self, dict, mode): + if mode == "careful": + self._update_careful(dict) + elif mode == "loose": + self._update_loose(dict) + else: + raise ValueError, "invalid update mode: %r" % mode + + def read_module (self, modname, mode="careful"): + __import__(modname) + mod = sys.modules[modname] + self._update(vars(mod), mode) + + def read_file (self, filename, mode="careful"): + vars = {} + execfile(filename, vars) + self._update(vars, mode) + + def ensure_value (self, attr, value): + if not hasattr(self, attr) or getattr(self, attr) is None: + setattr(self, attr, value) + return getattr(self, attr) + + +class OptionContainer: + + """ + Abstract base class. + + Class attributes: + standard_option_list : [Option] + list of standard options that will be accepted by all instances + of this parser class (intended to be overridden by subclasses). + + Instance attributes: + option_list : [Option] + the list of Option objects contained by this OptionContainer + _short_opt : { string : Option } + dictionary mapping short option strings, eg. "-f" or "-X", + to the Option instances that implement them. If an Option + has multiple short option strings, it will appears in this + dictionary multiple times. [1] + _long_opt : { string : Option } + dictionary mapping long option strings, eg. "--file" or + "--exclude", to the Option instances that implement them. + Again, a given Option can occur multiple times in this + dictionary. [1] + defaults : { string : any } + dictionary mapping option destination names to default + values for each destination [1] + + [1] These mappings are common to (shared by) all components of the + controlling OptionParser, where they are initially created. + + """ + + def __init__ (self, option_class, conflict_handler, description): + # Initialize the option list and related data structures. + # This method must be provided by subclasses, and it must + # initialize at least the following instance attributes: + # option_list, _short_opt, _long_opt, defaults. + self._create_option_list() + + self.option_class = option_class + self.set_conflict_handler(conflict_handler) + self.set_description(description) + + def _create_option_mappings (self): + # For use by OptionParser constructor -- create the master + # option mappings used by this OptionParser and all + # OptionGroups that it owns. + self._short_opt = {} # single letter -> Option instance + self._long_opt = {} # long option -> Option instance + self.defaults = {} # maps option dest -> default value + + + def _share_option_mappings (self, parser): + # For use by OptionGroup constructor -- use shared option + # mappings from the OptionParser that owns this OptionGroup. + self._short_opt = parser._short_opt + self._long_opt = parser._long_opt + self.defaults = parser.defaults + + def set_conflict_handler (self, handler): + if handler not in ("ignore", "error", "resolve"): + raise ValueError, "invalid conflict_resolution value %r" % handler + self.conflict_handler = handler + + def set_description (self, description): + self.description = description + + + # -- Option-adding methods ----------------------------------------- + + def _check_conflict (self, option): + conflict_opts = [] + for opt in option._short_opts: + if self._short_opt.has_key(opt): + conflict_opts.append((opt, self._short_opt[opt])) + for opt in option._long_opts: + if self._long_opt.has_key(opt): + conflict_opts.append((opt, self._long_opt[opt])) + + if conflict_opts: + handler = self.conflict_handler + if handler == "ignore": # behaviour for Optik 1.0, 1.1 + pass + elif handler == "error": # new in 1.2 + raise OptionConflictError( + "conflicting option string(s): %s" + % ", ".join([co[0] for co in conflict_opts]), + option) + elif handler == "resolve": # new in 1.2 + for (opt, c_option) in conflict_opts: + if opt.startswith("--"): + c_option._long_opts.remove(opt) + del self._long_opt[opt] + else: + c_option._short_opts.remove(opt) + del self._short_opt[opt] + if not (c_option._short_opts or c_option._long_opts): + c_option.container.option_list.remove(c_option) + + def add_option (self, *args, **kwargs): + """add_option(Option) + add_option(opt_str, ..., kwarg=val, ...) + """ + if type(args[0]) is types.StringType: + option = self.option_class(*args, **kwargs) + elif len(args) == 1 and not kwargs: + option = args[0] + if not isinstance(option, Option): + raise TypeError, "not an Option instance: %r" % option + else: + raise TypeError, "invalid arguments" + + self._check_conflict(option) + + self.option_list.append(option) + option.container = self + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + if option.dest is not None: # option has a dest, we need a default + if option.default is not NO_DEFAULT: + self.defaults[option.dest] = option.default + elif not self.defaults.has_key(option.dest): + self.defaults[option.dest] = None + + return option + + def add_options (self, option_list): + for option in option_list: + self.add_option(option) + + # -- Option query/removal methods ---------------------------------- + + def get_option (self, opt_str): + return (self._short_opt.get(opt_str) or + self._long_opt.get(opt_str)) + + def has_option (self, opt_str): + return (self._short_opt.has_key(opt_str) or + self._long_opt.has_key(opt_str)) + + def remove_option (self, opt_str): + option = self._short_opt.get(opt_str) + if option is None: + option = self._long_opt.get(opt_str) + if option is None: + raise ValueError("no such option %r" % opt_str) + + for opt in option._short_opts: + del self._short_opt[opt] + for opt in option._long_opts: + del self._long_opt[opt] + option.container.option_list.remove(option) + + + # -- Help-formatting methods --------------------------------------- + + def format_option_help (self, formatter): + if not self.option_list: + return "" + result = [] + for option in self.option_list: + if not option.help is SUPPRESS_HELP: + result.append(formatter.format_option(option)) + return "".join(result) + + def format_description (self, formatter): + if self.description: + return formatter.format_description(self.description) + else: + return "" + + def format_help (self, formatter): + if self.description: + desc = self.format_description(formatter) + "\n" + else: + desc = "" + return desc + self.format_option_help(formatter) + + +class OptionGroup (OptionContainer): + + def __init__ (self, parser, title, description=None): + self.parser = parser + OptionContainer.__init__( + self, parser.option_class, parser.conflict_handler, description) + self.title = title + + def _create_option_list (self): + self.option_list = [] + self._share_option_mappings(self.parser) + + def set_title (self, title): + self.title = title + + # -- Help-formatting methods --------------------------------------- + + def format_help (self, formatter): + result = formatter.format_heading(self.title) + formatter.indent() + result += OptionContainer.format_help(self, formatter) + formatter.dedent() + return result + + +class OptionParser (OptionContainer): + + """ + Class attributes: + standard_option_list : [Option] + list of standard options that will be accepted by all instances + of this parser class (intended to be overridden by subclasses). + + Instance attributes: + usage : string + a usage string for your program. Before it is displayed + to the user, "%prog" will be expanded to the name of + your program (self.prog or os.path.basename(sys.argv[0])). + prog : string + the name of the current program (to override + os.path.basename(sys.argv[0])). + + allow_interspersed_args : boolean = true + if true, positional arguments may be interspersed with options. + Assuming -a and -b each take a single argument, the command-line + -ablah foo bar -bboo baz + will be interpreted the same as + -ablah -bboo -- foo bar baz + If this flag were false, that command line would be interpreted as + -ablah -- foo bar -bboo baz + -- ie. we stop processing options as soon as we see the first + non-option argument. (This is the tradition followed by + Python's getopt module, Perl's Getopt::Std, and other argument- + parsing libraries, but it is generally annoying to users.) + + rargs : [string] + the argument list currently being parsed. Only set when + parse_args() is active, and continually trimmed down as + we consume arguments. Mainly there for the benefit of + callback options. + largs : [string] + the list of leftover arguments that we have skipped while + parsing options. If allow_interspersed_args is false, this + list is always empty. + values : Values + the set of option values currently being accumulated. Only + set when parse_args() is active. Also mainly for callbacks. + + Because of the 'rargs', 'largs', and 'values' attributes, + OptionParser is not thread-safe. If, for some perverse reason, you + need to parse command-line arguments simultaneously in different + threads, use different OptionParser instances. + + """ + + standard_option_list = [] + + def __init__ (self, + usage=None, + option_list=None, + option_class=Option, + version=None, + conflict_handler="error", + description=None, + formatter=None, + add_help_option=1, + prog=None): + OptionContainer.__init__( + self, option_class, conflict_handler, description) + self.set_usage(usage) + self.prog = prog + self.version = version + self.allow_interspersed_args = 1 + if formatter is None: + formatter = IndentedHelpFormatter() + self.formatter = formatter + + # Populate the option list; initial sources are the + # standard_option_list class attribute, the 'option_list' + # argument, and the STD_VERSION_OPTION (if 'version' supplied) + # and STD_HELP_OPTION globals. + self._populate_option_list(option_list, + add_help=add_help_option) + + self._init_parsing_state() + + # -- Private methods ----------------------------------------------- + # (used by our or OptionContainer's constructor) + + def _create_option_list (self): + self.option_list = [] + self.option_groups = [] + self._create_option_mappings() + + def _populate_option_list (self, option_list, add_help=1): + if self.standard_option_list: + self.add_options(self.standard_option_list) + if option_list: + self.add_options(option_list) + if self.version: + self.add_option(STD_VERSION_OPTION) + if add_help: + self.add_option(STD_HELP_OPTION) + + def _init_parsing_state (self): + # These are set in parse_args() for the convenience of callbacks. + self.rargs = None + self.largs = None + self.values = None + + + # -- Simple modifier methods --------------------------------------- + + def set_usage (self, usage): + if usage is None: + self.usage = "%prog [options]" + elif usage is SUPPRESS_USAGE: + self.usage = None + elif usage.startswith("usage: "): + # for backwards compatibility with Optik 1.3 and earlier + self.usage = usage[7:] + else: + self.usage = usage + + def enable_interspersed_args (self): + self.allow_interspersed_args = 1 + + def disable_interspersed_args (self): + self.allow_interspersed_args = 0 + + def set_default (self, dest, value): + self.defaults[dest] = value + + def set_defaults (self, **kwargs): + self.defaults.update(kwargs) + + def get_default_values (self): + return Values(self.defaults) + + + # -- OptionGroup methods ------------------------------------------- + + def add_option_group (self, *args, **kwargs): + # XXX lots of overlap with OptionContainer.add_option() + if type(args[0]) is types.StringType: + group = OptionGroup(self, *args, **kwargs) + elif len(args) == 1 and not kwargs: + group = args[0] + if not isinstance(group, OptionGroup): + raise TypeError, "not an OptionGroup instance: %r" % group + if group.parser is not self: + raise ValueError, "invalid OptionGroup (wrong parser)" + else: + raise TypeError, "invalid arguments" + + self.option_groups.append(group) + return group + + def get_option_group (self, opt_str): + option = (self._short_opt.get(opt_str) or + self._long_opt.get(opt_str)) + if option and option.container is not self: + return option.container + return None + + + # -- Option-parsing methods ---------------------------------------- + + def _get_args (self, args): + if args is None: + return sys.argv[1:] + else: + return args[:] # don't modify caller's list + + def parse_args (self, args=None, values=None): + """ + parse_args(args : [string] = sys.argv[1:], + values : Values = None) + -> (values : Values, args : [string]) + + Parse the command-line options found in 'args' (default: + sys.argv[1:]). Any errors result in a call to 'error()', which + by default prints the usage message to stderr and calls + sys.exit() with an error message. On success returns a pair + (values, args) where 'values' is an Values instance (with all + your option values) and 'args' is the list of arguments left + over after parsing options. + """ + rargs = self._get_args(args) + if values is None: + values = self.get_default_values() + + # Store the halves of the argument list as attributes for the + # convenience of callbacks: + # rargs + # the rest of the command-line (the "r" stands for + # "remaining" or "right-hand") + # largs + # the leftover arguments -- ie. what's left after removing + # options and their arguments (the "l" stands for "leftover" + # or "left-hand") + self.rargs = rargs + self.largs = largs = [] + self.values = values + + try: + stop = self._process_args(largs, rargs, values) + except (BadOptionError, OptionValueError), err: + self.error(err.msg) + + args = largs + rargs + return self.check_values(values, args) + + def check_values (self, values, args): + """ + check_values(values : Values, args : [string]) + -> (values : Values, args : [string]) + + Check that the supplied option values and leftover arguments are + valid. Returns the option values and leftover arguments + (possibly adjusted, possibly completely new -- whatever you + like). Default implementation just returns the passed-in + values; subclasses may override as desired. + """ + return (values, args) + + def _process_args (self, largs, rargs, values): + """_process_args(largs : [string], + rargs : [string], + values : Values) + + Process command-line arguments and populate 'values', consuming + options and arguments from 'rargs'. If 'allow_interspersed_args' is + false, stop at the first non-option argument. If true, accumulate any + interspersed non-option arguments in 'largs'. + """ + while rargs: + arg = rargs[0] + # We handle bare "--" explicitly, and bare "-" is handled by the + # standard arg handler since the short arg case ensures that the + # len of the opt string is greater than 1. + if arg == "--": + del rargs[0] + return + elif arg[0:2] == "--": + # process a single long option (possibly with value(s)) + self._process_long_opt(rargs, values) + elif arg[:1] == "-" and len(arg) > 1: + # process a cluster of short options (possibly with + # value(s) for the last one only) + self._process_short_opts(rargs, values) + elif self.allow_interspersed_args: + largs.append(arg) + del rargs[0] + else: + return # stop now, leave this arg in rargs + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt (self, opt): + """_match_long_opt(opt : string) -> string + + Determine which long option string 'opt' matches, ie. which one + it is an unambiguous abbrevation for. Raises BadOptionError if + 'opt' doesn't unambiguously match any long option string. + """ + return _match_abbrev(opt, self._long_opt) + + def _process_long_opt (self, rargs, values): + arg = rargs.pop(0) + + # Value explicitly attached to arg? Pretend it's the next + # argument. + if "=" in arg: + (opt, next_arg) = arg.split("=", 1) + rargs.insert(0, next_arg) + had_explicit_value = 1 + else: + opt = arg + had_explicit_value = 0 + + opt = self._match_long_opt(opt) + option = self._long_opt[opt] + if option.takes_value(): + nargs = option.nargs + if len(rargs) < nargs: + if nargs == 1: + self.error("%s option requires a value" % opt) + else: + self.error("%s option requires %d values" + % (opt, nargs)) + elif nargs == 1: + value = rargs.pop(0) + else: + value = tuple(rargs[0:nargs]) + del rargs[0:nargs] + + elif had_explicit_value: + self.error("%s option does not take a value" % opt) + + else: + value = None + + option.process(opt, value, values, self) + + def _process_short_opts (self, rargs, values): + arg = rargs.pop(0) + stop = 0 + i = 1 + for ch in arg[1:]: + opt = "-" + ch + option = self._short_opt.get(opt) + i += 1 # we have consumed a character + + if not option: + self.error("no such option: %s" % opt) + if option.takes_value(): + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + rargs.insert(0, arg[i:]) + stop = 1 + + nargs = option.nargs + if len(rargs) < nargs: + if nargs == 1: + self.error("%s option requires a value" % opt) + else: + self.error("%s option requires %s values" + % (opt, nargs)) + elif nargs == 1: + value = rargs.pop(0) + else: + value = tuple(rargs[0:nargs]) + del rargs[0:nargs] + + else: # option doesn't take a value + value = None + + option.process(opt, value, values, self) + + if stop: + break + + + # -- Feedback methods ---------------------------------------------- + + def error (self, msg): + """error(msg : string) + + Print a usage message incorporating 'msg' to stderr and exit. + If you override this in a subclass, it should not return -- it + should either exit or raise an exception. + """ + self.print_usage(sys.stderr) + sys.exit("%s: error: %s" % (get_prog_name(), msg)) + + def get_usage (self): + if self.usage: + return self.formatter.format_usage( + self.usage.replace("%prog", get_prog_name())) + else: + return "" + + def print_usage (self, file=None): + """print_usage(file : file = stdout) + + Print the usage message for the current program (self.usage) to + 'file' (default stdout). Any occurence of the string "%prog" in + self.usage is replaced with the name of the current program + (basename of sys.argv[0]). Does nothing if self.usage is empty + or not defined. + """ + if self.usage: + print >>file, self.get_usage() + + def get_version (self): + if self.version: + return self.version.replace("%prog", get_prog_name()) + else: + return "" + + def print_version (self, file=None): + """print_version(file : file = stdout) + + Print the version message for this program (self.version) to + 'file' (default stdout). As with print_usage(), any occurence + of "%prog" in self.version is replaced by the current program's + name. Does nothing if self.version is empty or undefined. + """ + if self.version: + print >>file, self.get_version() + + def format_option_help (self, formatter=None): + if formatter is None: + formatter = self.formatter + formatter.store_option_strings(self) + result = [] + result.append(formatter.format_heading("options")) + formatter.indent() + if self.option_list: + result.append(OptionContainer.format_option_help(self, formatter)) + result.append("\n") + for group in self.option_groups: + result.append(group.format_help(formatter)) + result.append("\n") + formatter.dedent() + # Drop the last "\n", or the header if no options or option groups: + return "".join(result[:-1]) + + def format_help (self, formatter=None): + if formatter is None: + formatter = self.formatter + result = [] + if self.usage: + result.append(self.get_usage() + "\n") + if self.description: + result.append(self.format_description(formatter) + "\n") + result.append(self.format_option_help(formatter)) + return "".join(result) + + def print_help (self, file=None): + """print_help(file : file = stdout) + + Print an extended help message, listing all options and any + help text provided with them, to 'file' (default stdout). + """ + if file is None: + file = sys.stdout + file.write(self.format_help()) + +# class OptionParser + + +def _match_abbrev (s, wordmap): + """_match_abbrev(s : string, wordmap : {string : Option}) -> string + + Return the string key in 'wordmap' for which 's' is an unambiguous + abbreviation. If 's' is found to be ambiguous or doesn't match any of + 'words', raise BadOptionError. + """ + # Is there an exact match? + if wordmap.has_key(s): + return s + else: + # Isolate all words with s as a prefix. + possibilities = [word for word in wordmap.keys() + if word.startswith(s)] + # No exact match, so there had better be just one possibility. + if len(possibilities) == 1: + return possibilities[0] + elif not possibilities: + raise BadOptionError("no such option: %s" % s) + else: + # More than one possible completion: ambiguous prefix. + raise BadOptionError("ambiguous option: %s (%s?)" + % (s, ", ".join(possibilities))) +"""Text wrapping and filling. +""" + +# Copyright (C) 1999-2001 Gregory P. Ward. +# Copyright (C) 2002, 2003 Python Software Foundation. +# Written by Greg Ward + + +# Do the right thing with boolean values for all known Python versions. +try: + True, False +except NameError: + (True, False) = (1, 0) + +class TextWrapper: + """ + Object for wrapping/filling text. The public interface consists of + the wrap() and fill() methods; the other methods are just there for + subclasses to override in order to tweak the default behaviour. + If you want to completely replace the main wrapping algorithm, + you'll probably have to override _wrap_chunks(). + + Several instance attributes control various aspects of wrapping: + width (default: 70) + the maximum width of wrapped lines (unless break_long_words + is false) + initial_indent (default: "") + string that will be prepended to the first line of wrapped + output. Counts towards the line's width. + subsequent_indent (default: "") + string that will be prepended to all lines save the first + of wrapped output; also counts towards each line's width. + expand_tabs (default: true) + Expand tabs in input text to spaces before further processing. + Each tab will become 1 .. 8 spaces, depending on its position in + its line. If false, each tab is treated as a single character. + replace_whitespace (default: true) + Replace all whitespace characters in the input text by spaces + after tab expansion. Note that if expand_tabs is false and + replace_whitespace is true, every tab will be converted to a + single space! + fix_sentence_endings (default: false) + Ensure that sentence-ending punctuation is always followed + by two spaces. Off by default becaus the algorithm is + (unavoidably) imperfect. + break_long_words (default: true) + Break words longer than 'width'. If false, those words will not + be broken, and some lines might be longer than 'width'. + """ + + whitespace_trans = string.maketrans(string.whitespace, + ' ' * len(string.whitespace)) + + # This funky little regex is just the trick for splitting + # text up into word-wrappable chunks. E.g. + # "Hello there -- you goof-ball, use the -b option!" + # splits into + # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! + # (after stripping out empty strings). + wordsep_re = re.compile(r'(\s+|' # any whitespace + r'-*\w{2,}-(?=\w{2,})|' # hyphenated words + r'(?<=\S)-{2,}(?=\w))') # em-dash + + # XXX will there be a locale-or-charset-aware version of + # string.lowercase in 2.3? + sentence_end_re = re.compile(r'[%s]' # lowercase letter + r'[\.\!\?]' # sentence-ending punct. + r'[\"\']?' # optional end-of-quote + % string.lowercase) + + + def __init__ (self, + width=70, + initial_indent="", + subsequent_indent="", + expand_tabs=True, + replace_whitespace=True, + fix_sentence_endings=False, + break_long_words=True): + self.width = width + self.initial_indent = initial_indent + self.subsequent_indent = subsequent_indent + self.expand_tabs = expand_tabs + self.replace_whitespace = replace_whitespace + self.fix_sentence_endings = fix_sentence_endings + self.break_long_words = break_long_words + + + # -- Private methods ----------------------------------------------- + # (possibly useful for subclasses to override) + + def _munge_whitespace(self, text): + """_munge_whitespace(text : string) -> string + + Munge whitespace in text: expand tabs and convert all other + whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" + becomes " foo bar baz". + """ + if self.expand_tabs: + text = text.expandtabs() + if self.replace_whitespace: + text = text.translate(self.whitespace_trans) + return text + + + def _split(self, text): + """_split(text : string) -> [string] + + Split the text to wrap into indivisible chunks. Chunks are + not quite the same as words; see wrap_chunks() for full + details. As an example, the text + Look, goof-ball -- use the -b option! + breaks into the following chunks: + 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', + 'use', ' ', 'the', ' ', '-b', ' ', 'option!' + """ + chunks = self.wordsep_re.split(text) + chunks = filter(None, chunks) + return chunks + + def _fix_sentence_endings(self, chunks): + """_fix_sentence_endings(chunks : [string]) + + Correct for sentence endings buried in 'chunks'. Eg. when the + original text contains "... foo.\nBar ...", munge_whitespace() + and split() will convert that to [..., "foo.", " ", "Bar", ...] + which has one too few spaces; this method simply changes the one + space to two. + """ + i = 0 + pat = self.sentence_end_re + while i < len(chunks)-1: + if chunks[i+1] == " " and pat.search(chunks[i]): + chunks[i+1] = " " + i += 2 + else: + i += 1 + + def _handle_long_word(self, chunks, cur_line, cur_len, width): + """_handle_long_word(chunks : [string], + cur_line : [string], + cur_len : int, width : int) + + Handle a chunk of text (most likely a word, not whitespace) that + is too long to fit in any line. + """ + space_left = width - cur_len + + # If we're allowed to break long words, then do so: put as much + # of the next chunk onto the current line as will fit. + if self.break_long_words: + cur_line.append(chunks[0][0:space_left]) + chunks[0] = chunks[0][space_left:] + + # Otherwise, we have to preserve the long word intact. Only add + # it to the current line if there's nothing already there -- + # that minimizes how much we violate the width constraint. + elif not cur_line: + cur_line.append(chunks.pop(0)) + + # If we're not allowed to break long words, and there's already + # text on the current line, do nothing. Next time through the + # main loop of _wrap_chunks(), we'll wind up here again, but + # cur_len will be zero, so the next line will be entirely + # devoted to the long word that we can't handle right now. + + def _wrap_chunks(self, chunks): + """_wrap_chunks(chunks : [string]) -> [string] + + Wrap a sequence of text chunks and return a list of lines of + length 'self.width' or less. (If 'break_long_words' is false, + some lines may be longer than this.) Chunks correspond roughly + to words and the whitespace between them: each chunk is + indivisible (modulo 'break_long_words'), but a line break can + come between any two chunks. Chunks should not have internal + whitespace; ie. a chunk is either all whitespace or a "word". + Whitespace chunks will be removed from the beginning and end of + lines, but apart from that whitespace is preserved. + """ + lines = [] + + while chunks: + + # Start the list of chunks that will make up the current line. + # cur_len is just the length of all the chunks in cur_line. + cur_line = [] + cur_len = 0 + + # Figure out which static string will prefix this line. + if lines: + indent = self.subsequent_indent + else: + indent = self.initial_indent + + # Maximum width for this line. + width = self.width - len(indent) + + # First chunk on line is whitespace -- drop it. + if chunks[0].strip() == '': + del chunks[0] + + while chunks: + l = len(chunks[0]) + + # Can at least squeeze this chunk onto the current line. + if cur_len + l <= width: + cur_line.append(chunks.pop(0)) + cur_len += l + + # Nope, this line is full. + else: + break + + # The current line is full, and the next chunk is too big to + # fit on *any* line (not just this one). + if chunks and len(chunks[0]) > width: + self._handle_long_word(chunks, cur_line, cur_len, width) + + # If the last chunk on this line is all whitespace, drop it. + if cur_line and cur_line[-1].strip() == '': + del cur_line[-1] + + # Convert current line back to a string and store it in list + # of all lines (return value). + if cur_line: + lines.append(indent + ''.join(cur_line)) + + return lines + + + # -- Public interface ---------------------------------------------- + + def wrap(self, text): + """wrap(text : string) -> [string] + + Reformat the single paragraph in 'text' so it fits in lines of + no more than 'self.width' columns, and return a list of wrapped + lines. Tabs in 'text' are expanded with string.expandtabs(), + and all other whitespace characters (including newline) are + converted to space. + """ + text = self._munge_whitespace(text) + indent = self.initial_indent + if len(text) + len(indent) <= self.width: + return [indent + text] + chunks = self._split(text) + if self.fix_sentence_endings: + self._fix_sentence_endings(chunks) + return self._wrap_chunks(chunks) + + def fill(self, text): + """fill(text : string) -> string + + Reformat the single paragraph in 'text' to fit in lines of no + more than 'self.width' columns, and return a new string + containing the entire wrapped paragraph. + """ + return "\n".join(self.wrap(text)) + + +# -- Convenience interface --------------------------------------------- + +def wrap(text, width=70, **kwargs): + """Wrap a single paragraph of text, returning a list of wrapped lines. + + Reformat the single paragraph in 'text' so it fits in lines of no + more than 'width' columns, and return a list of wrapped lines. By + default, tabs in 'text' are expanded with string.expandtabs(), and + all other whitespace characters (including newline) are converted to + space. See TextWrapper class for available keyword args to customize + wrapping behaviour. + """ + w = TextWrapper(width=width, **kwargs) + return w.wrap(text) + +def fill(text, width=70, **kwargs): + """Fill a single paragraph of text, returning a new string. + + Reformat the single paragraph in 'text' to fit in lines of no more + than 'width' columns, and return a new string containing the entire + wrapped paragraph. As with wrap(), tabs are expanded and other + whitespace characters converted to space. See TextWrapper class for + available keyword args to customize wrapping behaviour. + """ + w = TextWrapper(width=width, **kwargs) + return w.fill(text) + +# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. +# See the README.txt distributed with Optik for licensing terms. + +__version__ = "1.4.1" + + + + +# Some day, there might be many Option classes. As of Optik 1.3, the +# preferred way to instantiate Options is indirectly, via make_option(), +# which will become a factory function when there are many Option +# classes. +make_option = Option Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Sat Jun 21 17:17:28 2003 @@ -3,6 +3,8 @@ from unittest import TestCase, TestLoader import pypy.interpreter.unittest_w +from pypy.tool.optik import make_option +from pypy.tool import optik IntTestCase = pypy.interpreter.unittest_w.IntTestCase AppTestCase = pypy.interpreter.unittest_w.AppTestCase @@ -211,7 +213,7 @@ verbose = 0 spacename = '' showwarning = 0 - allspaces = [] + spaces = [] testreldir = 0 runcts = 0 @@ -241,64 +243,48 @@ if include(arg): return arg -def print_usage(): - print >>sys.stderr, """\ -%s [-chrvST] [regex1] [regex2] [...] - - -c run CtsTestRunner (catches stdout and prints report after testing) - [unix only, for now] - -h this help message - -r gather only tests relative to current dir - -v increase verbosity level (including unittest-verbosity) - -w enable warnings from warnings framework (default is off) - -S run in standard object space - -T run in trivial object space (default) - - The regular expressions regex1, regex2 ... are matched - against the full python path of a test module. A leading - '%%' before a regex means that the matching result is to - be inverted. -""" % sys.argv[0] - raise SystemExit(1) +def get_standard_options(): + options = [] -def process_options(argv=[]): - """ invoke this if you want to process test-switches from sys.argv""" + def objspace_callback(option, opt, value, parser, space): + parser.values.spaces.append(space) - if not argv: - argv[:] = sys.argv[1:] - - try: - import getopt - opts, args = getopt.getopt(argv, "chrvST") - except getopt.error, msg: - print msg - print "Try `python %s -h' for help" % sys.argv[0] - sys.exit(2) - - for k,v in opts: - if k == '-h': - print_usage() - elif k == '-c': - Options.runcts = 1 - elif k == '-r': - Options.testreldir = 1 - elif k == '-w': - Options.showwarning = 1 - elif k == '-h': - print_usage() - elif k == '-v': - Options.verbose += 1 - elif k == '-S': - Options.spacename = 'std' - Options.allspaces.append('std') - elif k == '-T': - Options.spacename = 'trivial' - Options.allspaces.append('trivial') - + options.append(make_option( + '-S', action="callback", + callback=objspace_callback, callback_args=("std",), + help="run in std object space")) + options.append(make_option( + '-T', action="callback", + callback=objspace_callback, callback_args=("trivial",), + help="run in trivial object space")) + options.append(make_option( + '-v', action="count", dest="verbose")) + options.append(make_option( + '-w', action="store_true", dest="showwarning")) + + return options + +def get_test_options(): + options = get_standard_options() + options.append(make_option( + '-r', action="store_true", dest="testreldir", + help="gather only tests relative to current dir")) + options.append(make_option( + '-c', action="store_true", dest="runcts", + help="run CtsTestRunner (catches stdout and prints report " + "after testing) [unix only, for now]")) + return options + +def process_options(optionlist, argv=None): + op = optik.OptionParser() + op.add_options(optionlist) + options, args = op.parse_args(argv, Options) + if not options.spaces: + options.spaces = ['trivial'] return args def run_tests(suite): - for spacename in Options.allspaces or ['']: + for spacename in Options.spaces or ['']: run_tests_on_space(suite, spacename) def run_tests_on_space(suite, spacename=''): @@ -318,7 +304,8 @@ def main(root=None): """ run this to test everything in the __main__ or in the given root-directory (recursive)""" - args = process_options() + args = process_options(get_test_options()) + filterfunc = RegexFilterFunc(*args) if Options.testreldir: root = os.path.abspath('.') From tismer at codespeak.net Sat Jun 21 17:20:30 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 17:20:30 +0200 (MEST) Subject: [pypy-svn] rev 860 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621152030.3187F5AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 17:20:29 2003 New Revision: 860 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: commented about some unnormality. (please ignore last ci message) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sat Jun 21 17:20:29 2003 @@ -218,7 +218,7 @@ import listobject return listobject.W_ListObject(self, wrappeditems) # print "wrapping %r (%s)" % (x, type(x)) - # XXX unexpected wrapping of PyByteCode + # XXX unexpected wrapping of PyByteCode import cpythonobject return cpythonobject.W_CPythonObject(self, x) From tismer at codespeak.net Sat Jun 21 17:21:02 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 17:21:02 +0200 (MEST) Subject: [pypy-svn] rev 861 - pypy/trunk/doc Message-ID: <20030621152102.30A7D5AAA7@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 17:21:01 2003 New Revision: 861 Modified: pypy/trunk/doc/sprint-planning.txt Log: long done Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 17:21:01 2003 @@ -24,7 +24,7 @@ boolobject done cpythonobject done instmethobject done - longobject + longobject done sliceobject userobject dictobject From tomek at codespeak.net Sat Jun 21 17:21:08 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Sat, 21 Jun 2003 17:21:08 +0200 (MEST) Subject: [pypy-svn] rev 862 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621152108.A79355AAA7@thoth.codespeak.net> Author: tomek Date: Sat Jun 21 17:21:08 2003 New Revision: 862 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: Split got the third param - maxsplit. I wrote also the tests for it. Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sat Jun 21 17:21:08 2003 @@ -9,7 +9,6 @@ from rarray import CharArrayFromStr, CharArraySize - applicationfile = StdObjSpace.AppFile(__name__) class W_StringObject(W_Object): @@ -87,10 +86,13 @@ def str_istitle(space, w_self): pass -def str_split__String_None(space, w_self, w_none): +def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1): res = [] inword = 0 value = w_self._value.value() + maxsplit = space.unwrap(w_maxsplit) + pos = 0 + for ch in value: if ch.isspace(): if inword: @@ -99,43 +101,72 @@ if inword: res[-1] += ch else: + if maxsplit > -1: + if maxsplit == 0: + res.append(value[pos:]) + break + maxsplit = maxsplit - 1 res.append(ch) inword = 1 + pos = pos + 1 + for i in range(len(res)): res[i] = W_StringObject(space, res[i]) return W_ListObject(space, res) -def str_split__String_String(space, w_self, w_by): +def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): res = [] start = 0 value = w_self._value.value() by = w_by._value.value() - while 1: + bylen = space.unwrap(space.len(w_by)) + maxsplit = space.unwrap(w_maxsplit) + + #if maxsplit is default, then you have no limit + #of the length of the resulting array + if maxsplit == -1: + splitcount = 1 + else: + splitcount = maxsplit + + while splitcount: next = value.find(by, start) if next < 0: res.append(value[start:]) + start = w_self._value.len + 1 break res.append(value[start:next]) - start = next + len(by) + start = next + bylen + #decrese the counter only then, when + #we don't have default maxsplit + if maxsplit > -1: + splitcount = splitcount - 1 + + if start < w_self._value.len: + res.append(value[start:]) + for i in range(len(res)): res[i] = W_StringObject(w_self.space, res[i]) return W_ListObject(w_self.space, res) - def str_join__String_ANY(space, w_self, w_list): list = space.unpackiterable(w_list) if list: firstelem = 1 listlen = 0 - reslen = 0 + reslen = 0 + #compute the length of the resulting string for w_item in list: reslen = reslen + w_item._value.len listlen = listlen + 1 reslen = reslen + (listlen - 1) * w_self._value.len + + #allocate the string buffer res = CharArraySize(reslen) pos = 0 + #fill in the string buffer for w_item in list: if firstelem: res.setsubstring(pos, w_item._value.value()) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sat Jun 21 17:21:08 2003 @@ -7,7 +7,7 @@ typename = 'str' str_join = MultiMethod('join', 2) - str_split = MultiMethod('split', 2, defaults=(None,)) + str_split = MultiMethod('split', 3, defaults=(None,-1)) str_isdigit = MultiMethod('isdigit', 1) str_isalpha = MultiMethod('isalpha', 1) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sat Jun 21 17:21:08 2003 @@ -118,6 +118,7 @@ def test_split(self): self.assertEquals("".split(), []) self.assertEquals("a".split(), ['a']) + self.assertEquals(" a ".split(), ['a']) self.assertEquals("a b c".split(), ['a','b','c']) def test_split_splitchar(self): @@ -126,8 +127,13 @@ def test_ljust(self): self.assertEquals("abc".ljust(5), "abc ") - def _notimpl_test_split_maxsplit(self): + def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) + self.assertEquals(" a ".split(None, 0), ['a ']) + self.assertEquals(" a ".split(None, 1), ['a']) + self.assertEquals(" a a ".split(" ", 0), [' a a ']) + self.assertEquals(" a a ".split(" ", 1), ['', 'a a ']) + if __name__ == '__main__': test.main() From gvanrossum at codespeak.net Sat Jun 21 17:56:57 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sat, 21 Jun 2003 17:56:57 +0200 (MEST) Subject: [pypy-svn] rev 863 - in pypy/trunk/src/pypy/objspace/ann: . test Message-ID: <20030621155657.DC09B5AAA7@thoth.codespeak.net> Author: gvanrossum Date: Sat Jun 21 17:56:57 2003 New Revision: 863 Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Log: Make a better test and make it work. Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sat Jun 21 17:56:57 2003 @@ -1,6 +1,9 @@ -from __future__ import nested_scopes +import sys import operator -from pypy.interpreter.baseobjspace import * + +from pypy.interpreter.baseobjspace \ + import ObjSpace, OperationError, NoValue, PyPyError +from pypy.interpreter.pycode import PyByteCode class W_Object: @@ -40,11 +43,16 @@ def unwrap(self, w_obj): if isinstance(w_obj, W_Constant): return w_obj.value - else: + elif isinstance(w_obj, W_Object): raise AnnException, "Cannot unwrap %r" % w_obj + else: + raise TypeError, "not wrapped: %s" % repr(w_obj) def newtuple(self, args_w): - return W_Anything() + for w_arg in args_w: + if not isinstance(w_arg, W_Constant): + return W_Anything() + return self.wrap(tuple(map(self.unwrap, args_w))) def newdict(self, items_w): for w_key, w_value in items_w: @@ -65,10 +73,57 @@ def newfunction(self, *stuff): return W_Anything() + def call(self, w_func, w_args, w_kwds): + func = self.unwrap(w_func) # Would be bad it it was W_Anything + code = func.func_code + bytecode = PyByteCode() + bytecode._from_code(code) + w_locals = bytecode.build_arguments(self, + w_args, + w_kwds, + self.wrap(func.func_defaults), + self.wrap(())) + w_result = bytecode.eval_code(self, + self.wrap(func.func_globals), + w_locals) + return w_result + + def getattr(self, w_obj, w_name): + try: + obj = self.unwrap(w_obj) + name = self.unwrap(w_name) + except AnnException: + return W_Anything() + else: + try: + return self.wrap(getattr(obj, name)) + except: + return self.reraise() + + def len(self, w_obj): + try: + obj = self.unwrap(w_obj) + except AnnException: + return W_Anything() + else: + return self.wrap(len(obj)) + def is_true(self, w_obj): + obj = self.unwrap(w_obj) + return bool(obj) + + def reraise(self): + t, v = sys.exc_info()[:2] + raise OperationError(self.wrap(t), self.wrap(v)) def make_op(name, symbol, arity, specialnames): - + + if not hasattr(operator, name): + return # Can't do it + + if hasattr(AnnotationObjSpace, name): + return # Shouldn't do it + def generic_operator(space, *args_w): assert len(args_w) == arity, "got a wrong number of arguments" for w_arg in args_w: @@ -77,10 +132,12 @@ else: # all arguments are constants, call the operator now op = getattr(operator, name) - return op(*[space.unwrap(w_arg) for w_arg in args_w]) + args = [space.unwrap(w_arg) for w_arg in args_w] + result = op(*args) + return space.wrap(result) return W_Anything() - + setattr(AnnotationObjSpace, name, generic_operator) for line in ObjSpace.MethodTable: Modified: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_simple.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sat Jun 21 17:56:57 2003 @@ -22,13 +22,20 @@ def setUp(self): self.space = AnnotationObjSpace() - def test_simple1(self): + def dont_test_simple1(self): x = self.codetest(''' def f(i): return i+1 ''', 'f', [W_Anything()]) self.assert_(isinstance(x, W_Anything)) + def test_simple2(self): + x = self.codetest(''' +def f(i): + return i+1 +''', 'f', [self.space.wrap(5)]) + self.assertEquals(self.space.unwrap(x), 6) + if __name__ == '__main__': test.main() From anna at codespeak.net Sat Jun 21 18:02:09 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sat, 21 Jun 2003 18:02:09 +0200 (MEST) Subject: [pypy-svn] rev 864 - pypy/trunk/doc Message-ID: <20030621160209.266A85AAA7@thoth.codespeak.net> Author: anna Date: Sat Jun 21 18:02:08 2003 New Revision: 864 Added: pypy/trunk/doc/ObjSpc.txt Log: add ObjSpc.txt Added: pypy/trunk/doc/ObjSpc.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/ObjSpc.txt Sat Jun 21 18:02:08 2003 @@ -0,0 +1,39 @@ +===================== +PyPython ObjectSpace +===================== + +See ObjectSpaceInterface_ for a draft version of the interface specification to ObjectSpace objects. +------------------------------------------------------------------------------------------------------ + +In a Python-like language, a running interpreter has three main parts: + ++ the compiler, which represents the static optimization of the source code into an intermediate format, the bytecode; ++ the object library, implementing the various types of objects and their semantics; ++ the main loop, which suffles data around and calls the operations defined in the object library according to the bytecode. + +The main loop generally assumes little about the semantics of the objects: they are essentially black boxes (PyObject pointers). The interpreter stack and the variables only contain such black boxes. Every operation is done via calls to the object library, like PyNumber_Add(). + +In PyPy, the three parts are clearly separated and can be replaced independently. I will discuss below the reasons I think it is very useful to have, in particular, the object library be replaced. We call object space such an object library. The standard object space is the object space that works just like Python's, that is, the object space whose black boxes are real Python objects that work as expected. We will call wrapped objects the black boxes of an object space. + +Here are four examples of object spaces: + +- TrivialObjectSpace_ +- StandardObjectSpace_ +- AbstractObjectSpace_ +- TranslateObjectSpace_ + +(We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.) + +I believe that the above examples should give a hint at why we might really want object spaces that behave differently: this is called abstact interpretation in the litterature. But there are also more funny ways to use object spaces, for example: + ++ running with several object spaces at once, to clearly separate the data into domains ++ proxy object spaces, which forward all requests over a network to a "Python object server" ++ and more... there have been numerous ideas in pypy-dev. + +------------ + +.. _ObjectSpaceInterface: ObSpIntfc.html +.. _TrivialObjectSpace: TrivObSp.html +.. _StandardObjectSpace: StObSp.html +.. _AbstractObjectSpace: AbObSp.html +.. _TranslateObjectSpace: TranObSp.html From hpk at codespeak.net Sat Jun 21 18:02:22 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 18:02:22 +0200 (MEST) Subject: [pypy-svn] rev 865 - pypy/trunk/doc Message-ID: <20030621160222.7C5B85AAA7@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 18:02:22 2003 New Revision: 865 Modified: pypy/trunk/doc/sprint-planning.txt Log: added module state Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 18:02:22 2003 @@ -30,7 +30,7 @@ dictobject intobject - moduleobject + moduleobject done stringobject listobject floatobject From anna at codespeak.net Sat Jun 21 18:03:11 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sat, 21 Jun 2003 18:03:11 +0200 (MEST) Subject: [pypy-svn] rev 866 - pypy/trunk/doc Message-ID: <20030621160311.4860A5AAA7@thoth.codespeak.net> Author: anna Date: Sat Jun 21 18:03:11 2003 New Revision: 866 Added: pypy/trunk/doc/ObSpIntfc.txt Log: add ObSpIntfc.txt Added: pypy/trunk/doc/ObSpIntfc.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/ObSpIntfc.txt Sat Jun 21 18:03:11 2003 @@ -0,0 +1,111 @@ +================================ +PyPython ObjectSpaceInterface +================================ + +Note this is only a draft version of the ObjectSpace_ interface. The reality of the interface depends on the particular implementation you are using. Consult the code for details. + +class ObjSpace +================= + +Data Members +----------------- + ++ ObjSpace.MethodTable: + List of tuples (method name, symbol, number of arguments) for the regular part of the interface. (Tuples are interpreter level.) + ++ self.w_builtins ++ self.w_modules ++ self.appfile_helpers ++ self.w_None: The ObjectSpace's None ++ self.w_True: The ObjectSpace's True ++ self.w_False: The ObjectSpace's False + +Administrative Functions +---------------------------- + +**initialize():** + Function which initializes w_builtins and the other w_constants + +**getexecutioncontext():** + Return current active execution context. + +**gethelper(applicationfile):** + Get helper for applicationfile. + +Operations on Objects in ObjectSpace +----------------------------------------- + +These functions both take and return "wrapped" objects. + +*The following functions implement the same operations as those in CPython:* + +``id, type, issubtype, iter, repr, str, len, hash,`` + +``getattr, setattr, delattr, getitem, setitem, delitem,`` + +``pos, neg, not_, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,`` + +``lt, le, eq, ne, gt, ge, contains,`` + +``inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor`` + +**next(w):** + Call the next function for iterator w. + +**call(callable, args, kwds):** + Call a function with the given args and keywords + +**is_(w_x, w_y):** + Implements 'w_x is w_y'. + +**exception_match(w_exc_type, w_check_class):** + Checks if the given exception type matches 'w_check_class'. Used in matching the actual exception raised with the list of those to catch in an except clause. Returns a bool. + +Creation of Application Level objects +--------------------------------------- + +**wrap(x):** + Return ObjectSpace equivalent of x + +**newbool(b):** + Creates a Bool Object from an interpreter level object. + +**newtuple([..]):** + Take an interpreter level list of wrapped objects. + +**newlist([..]):** + Takes an interpreter level list of wrapped objects. + +**newdict([..]):** + Takes an interpreter level list of interpreter level pairs of wrapped key:wrapped value entries. + +**newslice(w_start, w_end, w_step):** + Makes a new slice object. + +**newfunction(w_code, w_globals, w_defaultarguments, w_closure=None):** + Creates a new function object + +**newstring(asciilist):** + Creates a string from a list of integers. + +**newmodule(w_name):** + Creates a new module with a given name. + +Conversions from Application Level to Interpreter Level +---------------------------------------------------------- + +**unwrap(w_x):** + Return Interpreter Level equivalent of w_x + +**is_true(w_x):** + Return a interpreter level bool (True or False). + +**unpackiterable(w_iterable, expected_length=None):** + Unpack an iterable object into a real (interpreter level) list. Raise a real ValueError if the expected_length is wrong. + +**unpacktuple(w_tuple, expected_length=None):** + Same as unpackiterable(), but only for tuples. + +--------------------------- + +.. _ObjectSpace: ObjSpcDoc.html From anna at codespeak.net Sat Jun 21 18:03:45 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sat, 21 Jun 2003 18:03:45 +0200 (MEST) Subject: [pypy-svn] rev 867 - pypy/trunk/doc Message-ID: <20030621160345.DEF815AAA7@thoth.codespeak.net> Author: anna Date: Sat Jun 21 18:03:45 2003 New Revision: 867 Added: pypy/trunk/doc/MultiMeth.txt Log: add MultiMeth.txt Added: pypy/trunk/doc/MultiMeth.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/MultiMeth.txt Sat Jun 21 18:03:45 2003 @@ -0,0 +1,143 @@ +======================== +PyPython MultiMethod +======================== + +Notes on Multimethods +------------------------ + +Interpreter-level classes correspond to implementations of application-level +types. Several implementations can be given for the same type (e.g. several +ways to code strings or dictionaries), and conversely the same implementation +can cover several types (e.g. all instances of user-defined types currently +share the same implementation). + +The hierarchy among the classes used for the implementations is convenient +for implementation purposes. It is not related to any application-level type +hierarchy. + +Dispatch +------------------- + +Multimethods dispatch by looking in a set of registered functions. Each +registered function has a signature, which defines which object implementation +classes are accepted at the corresponding argument position. + +The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' +later). As it accepts anything, it is the only way to guarantee that the +registered function will be called with exactly the same object as was +passed originally. ATTENTION: in all other cases the argument received by +the function may have been converted in some way. It must thus not be +considered to be 'id'entical to the original argument. For example it should +not be stored in a data structure, nor be queried for type, nor be used for +another multimethod dispatch -- the only thing you should do is read and +write its internal data. + +For example, 'getattr(obj, attr)' is implemented with a ``W_StringObject`` second +argument when all it needs is just the name of the attr, and with a W_ANY +when the 'attr' object could be used as a key in ``obj.__dict__``. + + +Delegation +--------------- + +Delegation is a transparent convertion mechanism between object +implementations. The convertion can give a result of a different type +(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). +There is a global table of delegators. We should not rely on the delegators +to be tried in any particlar order, or at all (e.g. the int -> float delegator +could be ignored when we know that no registered function will accept a float +anyway). + +Delegation is also used to emulate inheritance between built-in types +(e.g. bool -> int). This is done by delegation because there is no reason +that a particular implementation of a sub-type can be trivially typecast +to some other particular implementation of the parent type; the process might +require some work. + + +Types +--------- + +Types are implemented by the class W_TypeObject. This is where inheritance +and the Method Resolution Order are defined, and where attribute look-ups +are done. + +Instances of user-defined types are implementated as W_UserObjects. +A user-defined type can inherit from built-in types (maybe more than one, +although this is incompatible with CPython). The W_UserObject delegator +converts the object into any of these "parent objects" if needed. This is +how user-defined types appear to inherit all built-in operator +implementations. + +Delegators should be able to invoke user code; this would let us +implement special methods like __int__() by calling them within a +W_UserObject -> int delegator. + +Specifics of multimethods +--------------------------- + +Multimethods dispatch more-specific-first, left-to-right (i.e. if there is +an exact match for the first argument it will always be tried first). + +Delegators are automatically chained (i.e. A -> B and B -> C would be +combined to allow for A -> C delegation). + +Delegators do not publish the class of the converted object in advance, +so that the W_UserObject delegator can potentially produce any other +built-in implementation. This means chaining and chain loop detection cannot +be done statically (at least without help from an analysis tool like the +translator-to-C). To break loops, we can assume (unless a particular need +arises) that delegators are looping when they return an object of an +already-seen class. + +Registration +-------------------- + +The register() method of multimethods adds a function to its database of +functions, with the given signature. A function that raises +!FailedToImplement causes the next match to be tried. + +'delegate' is the special unary multimethod that should try to convert +its argument to something else. For greater control, it can also return +a list of 2-tuples (class, object), or an empty list for failure to convert +the argument to anything. All delegators will potentially be tried, and +recursively on each other's results to do chaining. + +A priority ordering between delegators is used. See ``objspace.PRIORITY_*``. + + +Translation +----------------------- + +The code in multimethod.py is not supposed to be read by the +translator-to-C. Special optimized code will be generated instead +(typically some kind of precomputed dispatch tables). + +Delegation is special-cased too. Most delegators will be found +to return an object of a statically known class, which means that +most of the chaining and loop detection can be done in advance. + + +Multimethod slicing +------------------------ + +Multimethods are visible to user code as (bound or unbound) methods +defined for the corresponding types. (At some point built-in functions +like len() and the operator.xxx() should really directly map to the +multimethods themselves, too.) + +To build a method from a multimethod (e.g. as in 'l.append' or +'int.__add__'), the result is actually a "slice" of the whole +multimethod, i.e. a sub-multimethod in which the registration table has +been trimmed down. (Delegation mechanisms are not restricted for sliced +multimethods.) + +Say that C is the class the new method is attached to (in the above +examples, respectively, C=type(l) and C=int). The restriction is +based on the registered class of the first argument ('self' for the +new method) in the signature. If this class corresponds to a fixed +type (as advertized by 'statictype'), and this fixed type is C or a +superclass of C, then we keep it. + +Some multimethods can also be sliced along their second argument, +e.g. for __radd__(). From hpk at codespeak.net Sat Jun 21 18:06:12 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 18:06:12 +0200 (MEST) Subject: [pypy-svn] rev 868 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621160612.714DD5AAA7@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 18:06:12 2003 New Revision: 868 Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py Log: added some docstrings (+ status info) Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/noneobject.py Sat Jun 21 18:06:12 2003 @@ -1,14 +1,16 @@ +""" + None Object implementation + + ok and tested +""" + from pypy.objspace.std.objspace import * from nonetype import W_NoneType - class W_NoneObject(W_Object): statictype = W_NoneType - - registerimplementation(W_NoneObject) - def unwrap__None(space, w_none): return None @@ -18,6 +20,5 @@ def repr__None(space, w_none): return space.wrap('None') - register_all(vars()) From mwh at codespeak.net Sat Jun 21 18:07:14 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 18:07:14 +0200 (MEST) Subject: [pypy-svn] rev 869 - in pypy/trunk/src/pypy: interpreter tool Message-ID: <20030621160714.185705AAA7@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 18:07:13 2003 New Revision: 869 Added: pypy/trunk/src/pypy/tool/option.py Modified: pypy/trunk/src/pypy/interpreter/interactive.py pypy/trunk/src/pypy/tool/test.py Log: make interactive.py work again (oops) this is a bit of a band-aid, interactive.py should disappear soon-ish Modified: pypy/trunk/src/pypy/interpreter/interactive.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/interactive.py (original) +++ pypy/trunk/src/pypy/interpreter/interactive.py Sat Jun 21 18:07:13 2003 @@ -69,8 +69,10 @@ except ImportError: pass + from pypy.tool import option from pypy.tool import test - args = test.process_options() - objspace = test.objspace() + args = option.process_options(option.get_standard_options(), + None, option.Options) + objspace = test.objspace(option.Options.spaces[-1]) con = PyPyConsole(objspace) con.interact() Added: pypy/trunk/src/pypy/tool/option.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/tool/option.py Sat Jun 21 18:07:13 2003 @@ -0,0 +1,37 @@ +from pypy.tool import optik +make_option = optik.make_option + +class Options: + verbose = 0 + spacename = '' + showwarning = 0 + spaces = [] + +def get_standard_options(): + options = [] + + def objspace_callback(option, opt, value, parser, space): + parser.values.spaces.append(space) + + options.append(make_option( + '-S', action="callback", + callback=objspace_callback, callback_args=("std",), + help="run in std object space")) + options.append(make_option( + '-T', action="callback", + callback=objspace_callback, callback_args=("trivial",), + help="run in trivial object space")) + options.append(make_option( + '-v', action="count", dest="verbose")) + options.append(make_option( + '-w', action="store_true", dest="showwarning")) + + return options + +def process_options(optionlist, argv=None, v=None): + op = optik.OptionParser() + op.add_options(optionlist) + options, args = op.parse_args(argv, v) + if not options.spaces: + options.spaces = ['trivial'] + return args Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Sat Jun 21 18:07:13 2003 @@ -4,7 +4,7 @@ import pypy.interpreter.unittest_w from pypy.tool.optik import make_option -from pypy.tool import optik +from pypy.tool import optik, option IntTestCase = pypy.interpreter.unittest_w.IntTestCase AppTestCase = pypy.interpreter.unittest_w.AppTestCase @@ -208,12 +208,7 @@ except KeyError: return _spacecache.setdefault(name, Space()) -class Options: - """ Options set by command line """ - verbose = 0 - spacename = '' - showwarning = 0 - spaces = [] +class Options(option.Options): testreldir = 0 runcts = 0 @@ -243,29 +238,8 @@ if include(arg): return arg -def get_standard_options(): - options = [] - - def objspace_callback(option, opt, value, parser, space): - parser.values.spaces.append(space) - - options.append(make_option( - '-S', action="callback", - callback=objspace_callback, callback_args=("std",), - help="run in std object space")) - options.append(make_option( - '-T', action="callback", - callback=objspace_callback, callback_args=("trivial",), - help="run in trivial object space")) - options.append(make_option( - '-v', action="count", dest="verbose")) - options.append(make_option( - '-w', action="store_true", dest="showwarning")) - - return options - def get_test_options(): - options = get_standard_options() + options = option.get_standard_options() options.append(make_option( '-r', action="store_true", dest="testreldir", help="gather only tests relative to current dir")) @@ -275,14 +249,6 @@ "after testing) [unix only, for now]")) return options -def process_options(optionlist, argv=None): - op = optik.OptionParser() - op.add_options(optionlist) - options, args = op.parse_args(argv, Options) - if not options.spaces: - options.spaces = ['trivial'] - return args - def run_tests(suite): for spacename in Options.spaces or ['']: run_tests_on_space(suite, spacename) @@ -304,7 +270,7 @@ def main(root=None): """ run this to test everything in the __main__ or in the given root-directory (recursive)""" - args = process_options(get_test_options()) + args = option.process_options(get_test_options(), None, Options) filterfunc = RegexFilterFunc(*args) if Options.testreldir: From mwh at codespeak.net Sat Jun 21 18:42:25 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 18:42:25 +0200 (MEST) Subject: [pypy-svn] rev 870 - in pypy/trunk/src/pypy: interpreter tool Message-ID: <20030621164225.BFA0D5A415@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 18:42:25 2003 New Revision: 870 Added: pypy/trunk/src/pypy/interpreter/py.py Modified: pypy/trunk/src/pypy/interpreter/interactive.py pypy/trunk/src/pypy/interpreter/main.py pypy/trunk/src/pypy/tool/option.py (contents, props changed) pypy/trunk/src/pypy/tool/test.py Log: the getting-where-you-want-by-flailing approach :-) more knocking about of command line parsing add py.py which is far from complete, but works a little bit Modified: pypy/trunk/src/pypy/interpreter/interactive.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/interactive.py (original) +++ pypy/trunk/src/pypy/interpreter/interactive.py Sat Jun 21 18:42:25 2003 @@ -72,7 +72,7 @@ from pypy.tool import option from pypy.tool import test args = option.process_options(option.get_standard_options(), - None, option.Options) - objspace = test.objspace(option.Options.spaces[-1]) + option.Options) + objspace = option.objspace() con = PyPyConsole(objspace) con.interact() Modified: pypy/trunk/src/pypy/interpreter/main.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/main.py (original) +++ pypy/trunk/src/pypy/interpreter/main.py Sat Jun 21 18:42:25 2003 @@ -1,5 +1,5 @@ import autopath -from pypy.tool import test +from pypy.tool import test, option from pypy.objspace.std import StdObjSpace from pypy.module.builtin import Builtin from pypy.interpreter import executioncontext, baseobjspace, pyframe @@ -39,8 +39,9 @@ if argv is None: argv = sys.argv - argv = test.process_options(argv[1:]) - space = test.objspace() + argv = option.process_options(option.get_standard_options(), + option.Options) + space = option.objspace() try: run_file(argv[0], space) except baseobjspace.PyPyError, pypyerr: Added: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/interpreter/py.py Sat Jun 21 18:42:25 2003 @@ -0,0 +1,31 @@ +import autopath +from pypy.tool import option +from pypy.tool.optik import make_option +from pypy.interpreter import main, interactive, baseobjspace +import sys + +class Options(option.Options): + interactive = 0 + +def get_main_options(): + options = option.get_standard_options() + options.append(make_option( + '-i', action="store_true", dest="interactive")) + return options + +def main_(argv=None): + args = option.process_options(get_main_options(), Options, argv[1:]) + space = option.objspace() + if args: + try: + main.run_file(args[0], space) + except baseobjspace.PyPyError, pypyerr: + pypyerr.operationerr.print_detailed_traceback(pypyerr.space) + else: + con = interactive.PyPyConsole(space) + con.interact() + + + +if __name__ == '__main__': + main_(sys.argv) Modified: pypy/trunk/src/pypy/tool/option.py ============================================================================== --- pypy/trunk/src/pypy/tool/option.py (original) +++ pypy/trunk/src/pypy/tool/option.py Sat Jun 21 18:42:25 2003 @@ -1,9 +1,9 @@ +import os from pypy.tool import optik make_option = optik.make_option class Options: verbose = 0 - spacename = '' showwarning = 0 spaces = [] @@ -28,10 +28,28 @@ return options -def process_options(optionlist, argv=None, v=None): +def process_options(optionlist, input_options, argv=None): op = optik.OptionParser() op.add_options(optionlist) - options, args = op.parse_args(argv, v) - if not options.spaces: - options.spaces = ['trivial'] + options, args = op.parse_args(argv, input_options) + if not input_options.spaces: + input_options.spaces.append(os.environ.get('OBJSPACE', 'trivial')) return args + +def objspace(name='', _spacecache={}): + """ return singleton ObjSpace instance. + + this is configured via the environment variable OBJSPACE + """ + name = name or Options.spaces[-1] + if name == 'std': + from pypy.objspace.std import Space + elif name == 'trivial': + from pypy.objspace.trivial import Space + else: + raise ValueError, "no objectspace named %s" % repr(name) + + try: + return _spacecache[name] + except KeyError: + return _spacecache.setdefault(name, Space()) Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Sat Jun 21 18:42:25 2003 @@ -5,6 +5,7 @@ import pypy.interpreter.unittest_w from pypy.tool.optik import make_option from pypy.tool import optik, option +from pypy.tool.option import objspace IntTestCase = pypy.interpreter.unittest_w.IntTestCase AppTestCase = pypy.interpreter.unittest_w.AppTestCase @@ -190,27 +191,10 @@ suite._tests.extend(subsuite._tests) return suite -def objspace(name='', _spacecache={}): - """ return singleton ObjSpace instance. - - this is configured via the environment variable OBJSPACE - """ - name = name or Options.spacename or os.environ.get('OBJSPACE', 'trivial') - if name == 'std': - from pypy.objspace.std import Space - elif name == 'trivial': - from pypy.objspace.trivial import Space - else: - raise ValueError, "no objectspace named %s" % repr(name) - - try: - return _spacecache[name] - except KeyError: - return _spacecache.setdefault(name, Space()) - class Options(option.Options): testreldir = 0 runcts = 0 + spacename = '' class RegexFilterFunc: """ stateful function to filter included/excluded strings via @@ -270,7 +254,7 @@ def main(root=None): """ run this to test everything in the __main__ or in the given root-directory (recursive)""" - args = option.process_options(get_test_options(), None, Options) + args = option.process_options(get_test_options(), Options) filterfunc = RegexFilterFunc(*args) if Options.testreldir: From gvanrossum at codespeak.net Sat Jun 21 18:43:57 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sat, 21 Jun 2003 18:43:57 +0200 (MEST) Subject: [pypy-svn] rev 871 - in pypy/trunk/src/pypy/objspace/ann: . test Message-ID: <20030621164357.A3BB05A415@thoth.codespeak.net> Author: gvanrossum Date: Sat Jun 21 18:43:57 2003 New Revision: 871 Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Log: Make two more things working: known-key tuples or dicts, and ints of unknown value. Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sat Jun 21 18:43:57 2003 @@ -6,18 +6,29 @@ from pypy.interpreter.pycode import PyByteCode -class W_Object: +class W_Object(object): pass class W_Anything(W_Object): pass +class W_Integer(W_Object): + pass + class W_Constant(W_Object): def __init__(self, value): self.value = value def __repr__(self): return '' % self.value +class W_KnownKeysContainer(W_Object): + def __init__(self, args_w): + self.args_w = args_w + def __len__(self): + return len(self.args_w) + def __getitem__(self, i): + return self.args_w[i] + class AnnException(Exception): pass @@ -37,6 +48,8 @@ setattr(self, 'w_' + c.__name__, self.wrap(c)) self.w_builtins = self.wrap(__builtin__) + # Service methods + def wrap(self, obj): return W_Constant(obj) @@ -47,24 +60,36 @@ raise AnnException, "Cannot unwrap %r" % w_obj else: raise TypeError, "not wrapped: %s" % repr(w_obj) + + def is_true(self, w_obj): + if isinstance(w_obj, W_KnownKeysContainer): + return bool(len(w_obj)) + obj = self.unwrap(w_obj) + return bool(obj) + + def reraise(self): + t, v = sys.exc_info()[:2] + raise OperationError(self.wrap(t), self.wrap(v)) + + # Specialized creators def newtuple(self, args_w): for w_arg in args_w: if not isinstance(w_arg, W_Constant): - return W_Anything() + return W_KnownKeysContainer(args_w) return self.wrap(tuple(map(self.unwrap, args_w))) def newdict(self, items_w): + values_w = {} for w_key, w_value in items_w: - if (not isinstance(w_key, W_Constant) or - not isinstance(w_value, W_Constant)): + try: + key = self.unwrap(w_key) + except AnnException: break + else: + values_w[key] = w_value else: - d = {} - for w_key, w_value in items_w: - d[self.unwrap(w_key)] = self.unwrap(w_value) - return self.wrap(d) - + return W_KnownKeysContainer(values_w) return W_Anything() def newmodule(self, w_name): @@ -73,6 +98,30 @@ def newfunction(self, *stuff): return W_Anything() + # Methods implementing Python operations + # (Many missing ones are added by make_op() below) + + def add(self, w_left, w_right): + try: + left = self.unwrap(w_left) + right = self.unwrap(w_right) + except AnnException: + pass + else: + return self.wrap(left + right) + if self.is_int(w_left) and self.is_int(w_right): + return W_Integer() + else: + return W_Anything() + + def is_int(self, w_obj): + if isinstance(w_obj, W_Integer): + return True + if isinstance(w_obj, W_Constant): + return isinstance(w_obj.value, int) + else: + return False + def call(self, w_func, w_args, w_kwds): func = self.unwrap(w_func) # Would be bad it it was W_Anything code = func.func_code @@ -101,6 +150,8 @@ return self.reraise() def len(self, w_obj): + if isinstance(w_obj, W_KnownKeysContainer): + return self.wrap(len(w_obj)) try: obj = self.unwrap(w_obj) except AnnException: @@ -108,13 +159,22 @@ else: return self.wrap(len(obj)) - def is_true(self, w_obj): - obj = self.unwrap(w_obj) - return bool(obj) - - def reraise(self): - t, v = sys.exc_info()[:2] - raise OperationError(self.wrap(t), self.wrap(v)) + def getitem(self, w_obj, w_key): + try: + key = self.unwrap(w_key) + except AnnException: + return W_Anything() + try: + obj = self.unwrap(w_obj) + except AnnException: + if isinstance(w_obj, W_KnownKeysContainer): + return w_obj[key] + else: + return W_Anything() + try: + return self.wrap(obj[key]) + except: + self.reraise() def make_op(name, symbol, arity, specialnames): Modified: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_simple.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sat Jun 21 18:43:57 2003 @@ -1,6 +1,7 @@ import autopath from pypy.tool import test -from pypy.objspace.ann.objspace import W_Object, W_Anything, AnnotationObjSpace +from pypy.objspace.ann.objspace import W_Object, W_Anything, W_Integer +from pypy.objspace.ann.objspace import AnnotationObjSpace from pypy.interpreter import baseobjspace, executioncontext, pyframe class TestAnnotationObjSpace(test.TestCase): @@ -22,20 +23,35 @@ def setUp(self): self.space = AnnotationObjSpace() - def dont_test_simple1(self): + def test_any2any(self): x = self.codetest(''' def f(i): return i+1 ''', 'f', [W_Anything()]) - self.assert_(isinstance(x, W_Anything)) + self.assertEquals(type(x), W_Anything) - def test_simple2(self): + def test_const2const(self): x = self.codetest(''' def f(i): return i+1 ''', 'f', [self.space.wrap(5)]) self.assertEquals(self.space.unwrap(x), 6) + def test_constany2const(self): + x = self.codetest(''' +def f(i, j): + return i+1 +''', 'f', [self.space.wrap(5), W_Anything()]) + self.assertEquals(self.space.unwrap(x), 6) + + def test_int2int(self): + x = self.codetest(''' +def f(i): + return i+1 +''', 'f', [W_Integer()]) + self.assertEquals(type(x), W_Integer) + + if __name__ == '__main__': test.main() From mwh at codespeak.net Sat Jun 21 18:44:19 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 18:44:19 +0200 (MEST) Subject: [pypy-svn] rev 872 - pypy/trunk/src/pypy/objspace/ann/test Message-ID: <20030621164419.1B5B15A415@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 18:44:18 2003 New Revision: 872 Added: pypy/trunk/src/pypy/objspace/ann/test/__init__.py (contents, props changed) Log: make objspace.ann.test a package (so test_all.py stops breaking) Added: pypy/trunk/src/pypy/objspace/ann/test/__init__.py ============================================================================== From mwh at codespeak.net Sat Jun 21 18:44:57 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 18:44:57 +0200 (MEST) Subject: [pypy-svn] rev 873 - in pypy/trunk/src/pypy: interpreter objspace/std/test tool Message-ID: <20030621164457.D57FF5A415@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 18:44:57 2003 New Revision: 873 Modified: pypy/trunk/src/pypy/interpreter/py.py (props changed) pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py (props changed) pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py (props changed) pypy/trunk/src/pypy/tool/optik.py (props changed) Log: fixeol From gvanrossum at codespeak.net Sat Jun 21 18:50:23 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sat, 21 Jun 2003 18:50:23 +0200 (MEST) Subject: [pypy-svn] rev 874 - pypy/trunk/src/pypy/objspace/ann/test Message-ID: <20030621165023.A75045A415@thoth.codespeak.net> Author: gvanrossum Date: Sat Jun 21 18:50:23 2003 New Revision: 874 Modified: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Log: Reformat the source code of the tests. Modified: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_simple.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sat Jun 21 18:50:23 2003 @@ -24,31 +24,27 @@ self.space = AnnotationObjSpace() def test_any2any(self): - x = self.codetest(''' -def f(i): - return i+1 -''', 'f', [W_Anything()]) + x = self.codetest("def f(i):\n" + " return i+1\n", + 'f', [W_Anything()]) self.assertEquals(type(x), W_Anything) def test_const2const(self): - x = self.codetest(''' -def f(i): - return i+1 -''', 'f', [self.space.wrap(5)]) + x = self.codetest("def f(i):\n" + " return i+1\n", + 'f', [self.space.wrap(5)]) self.assertEquals(self.space.unwrap(x), 6) def test_constany2const(self): - x = self.codetest(''' -def f(i, j): - return i+1 -''', 'f', [self.space.wrap(5), W_Anything()]) + x = self.codetest("def f(i, j):\n" + " return i+1\n", + 'f', [self.space.wrap(5), W_Anything()]) self.assertEquals(self.space.unwrap(x), 6) def test_int2int(self): - x = self.codetest(''' -def f(i): - return i+1 -''', 'f', [W_Integer()]) + x = self.codetest("def f(i):\n" + " return i+1\n", + 'f', [W_Integer()]) self.assertEquals(type(x), W_Integer) From tismer at codespeak.net Sat Jun 21 18:53:34 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 18:53:34 +0200 (MEST) Subject: [pypy-svn] rev 875 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621165334.A616A5A415@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 18:53:34 2003 New Revision: 875 Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py pypy/trunk/src/pypy/objspace/std/slicetype.py pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py Log: checked, added/refined tests, seems complete Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Sat Jun 21 18:53:34 2003 @@ -1,3 +1,10 @@ +""" +Reviewed 03-06-21 + +slice object construction tested, OK +indices method tested, OK +""" + from pypy.objspace.std.objspace import * from pypy.interpreter.appfile import AppFile from pypy.interpreter.extmodule import make_builtin_func @@ -16,10 +23,12 @@ w_self.w_stop = w_stop w_self.w_step = w_step def indices(w_self, w_length): + # this is used internally, analogous to CPython's PySlice_GetIndicesEx w_ret = w_self.space.gethelper(appfile).call("sliceindices", [w_self, w_length]) w_start, w_stop, w_step, w_slicelength = w_self.space.unpackiterable(w_ret, 4) return w_start, w_stop, w_step, w_slicelength def indices2(w_self, w_length): + # this is used to implement the user-visible method 'indices' of slice objects return w_self.space.newtuple(w_self.indices(w_length)[:-1]) Modified: pypy/trunk/src/pypy/objspace/std/slicetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/slicetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/slicetype.py Sat Jun 21 18:53:34 2003 @@ -20,6 +20,9 @@ start, stop = args elif len(args) == 3: start, stop, step = args + elif len(args) > 3: + raise OperationError(space.w_TypeError, + space.wrap("slice() takes at most 3 arguments")) else: raise OperationError(space.w_TypeError, space.wrap("slice() takes at least 1 argument")) Modified: pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_sliceobject.py Sat Jun 21 18:53:34 2003 @@ -10,19 +10,21 @@ pass def equal_indices(self, got, expected): + got = self.space.unwrap(got) + self.assertEqual(len(got), len(expected)) for g, e in zip(got, expected): - self.assertEqual_w(g, self.space.wrap(e)) + self.assertEqual(g, e) def test_indices(self): space = self.space w = space.wrap w_None = space.w_None w_slice = space.newslice(w_None, w_None, w_None) - self.equal_indices(w_slice.indices(w(6)), (0, 6, 1, 6)) + self.equal_indices(w_slice.indices2(w(6)), (0, 6, 1)) w_slice = space.newslice(w(0), w(6), w(1)) - self.equal_indices(w_slice.indices(w(6)), (0, 6, 1, 6)) + self.equal_indices(w_slice.indices2(w(6)), (0, 6, 1)) w_slice = space.newslice(w_None, w_None, w(-1)) - self.equal_indices(w_slice.indices(w(6)), (5, -1, -1, 6)) + self.equal_indices(w_slice.indices2(w(6)), (5, -1, -1)) def test_indices_fail(self): space = self.space @@ -32,5 +34,17 @@ self.assertRaises_w(space.w_ValueError, w_slice.indices, w(10)) +class Test_SliceObject(test.AppTestCase): + def test_new(self): + def cmp_slice(sl1, sl2): + for attr in "start", "stop", "step": + if getattr(sl1, attr) != getattr(sl2, attr): + return False + return True + self.assertRaises(TypeError, slice) + self.assertRaises(TypeError, slice, 1, 2, 3, 4) + self.failUnless(cmp_slice(slice(23), slice(None, 23, None))) + self.failUnless(cmp_slice(slice(23, 45), slice(23, 45, None))) + if __name__ == '__main__': test.main() From tismer at codespeak.net Sat Jun 21 18:55:37 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 18:55:37 +0200 (MEST) Subject: [pypy-svn] rev 876 - pypy/trunk/doc Message-ID: <20030621165537.2E5BB5A415@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 18:55:36 2003 New Revision: 876 Modified: pypy/trunk/doc/sprint-planning.txt Log: slice done Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sat Jun 21 18:55:36 2003 @@ -25,7 +25,7 @@ cpythonobject done instmethobject done longobject done - sliceobject + sliceobject done userobject dictobject From tismer at codespeak.net Sat Jun 21 18:57:19 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 21 Jun 2003 18:57:19 +0200 (MEST) Subject: [pypy-svn] rev 877 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030621165719.363F85A415@thoth.codespeak.net> Author: tismer Date: Sat Jun 21 18:57:18 2003 New Revision: 877 Removed: pypy/trunk/src/pypy/objspace/std/longobject.py pypy/trunk/src/pypy/objspace/std/longobject_app.py Log: purged obsolete longobjectXXX.py Deleted: pypy/trunk/src/pypy/objspace/std/longobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/longobject.py Sat Jun 21 18:57:18 2003 +++ (empty file) @@ -1,165 +0,0 @@ -""" -Reviewed 03-06-21 -This isn't used at all, nor tested, and is totally cheating. -There isn't even any corresponding longtype. Should perhaps -be just removed. -""" - - -from pypy.objspace.std.objspace import * - - - -class W_LongObject(W_Object): - - def __init__(w_self, space, longval): - W_Object.__init__(w_self, space) - w_self.longval = longval - - def getattr(w_self, space, w_attrname): - return applicationfile.call(space, "long_getattr", [w_self, w_attrname]) - - -def long(space,w_value): - return applicationfile.call(space,"long_long",[w_value]) - -def add__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x + y - except OverflowError: - raise OperationError(OverflowError, "long addition") - return W_LongObject(space, z) - -def sub__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x - y - except Error,e: - raise OperationError(Error, e) - return W_LongObject(space, z) - -def mul__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x * y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - -def floordiv__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x // y - except ZeroDivisionError: - raise # we have to implement the exception or it will be ignored - # no overflow - return W_LongObject(space, z) - -def truediv__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x / y # XXX make sure this is the new true division - except ZeroDivisionError: - raise # we have to implement the exception or it will be ignored - # no overflow - return W_LongObject(space, z) - -if 1L / 2L == 1L // 2L: - long_long_div = long_long_floordiv -else: - long_long_div = long_long_truediv - -def mod__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x % y - except ZeroDivisionError: - raise # we have to implement the exception or it will be ignored - # no overflow - return W_LongObject(space, z) - -def divmod__Long_Long(space, w_long1, w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x // y - m = x % y - except ZeroDivisionError: - raise # we have to implement the exception or it will be ignored - # no overflow - return W_TupleObject(space, [W_LongObject(space, z), - W_LongObject(space, m)]) - -def pow__Long_Long(space, w_long1,w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x ** y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - -def pow__Long_Long_ANY(space, w_long1,w_long2,w_long3): - x = w_long1.longval - y = w_long2.longval - z = w_long3.longval - try: - z = (x ** y) % z - except Error,e: - raise OperationError(Error(e), "long multiplication") - return W_LongObject(space, z) - -def lshift__Long_Long(space, w_long1,w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x << y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - -def rshift__Long_Long(space, w_long1,w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x >> y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - -def and__Long_Long(space, w_long1,w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x & y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - -def xor__Long_Long(space, w_long1,w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x ^ y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - -def or__Long_Long(space, w_long1,w_long2): - x = w_long1.longval - y = w_long2.longval - try: - z = x | y - except OverflowError: - raise OperationError(OverflowError, "long multiplication") - return W_LongObject(space, z) - - -register_all(vars()) Deleted: pypy/trunk/src/pypy/objspace/std/longobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/longobject_app.py Sat Jun 21 18:57:18 2003 +++ (empty file) @@ -1,15 +0,0 @@ -""" -Reviewed 03-06-21 -This isn't used at all, nor tested, and is totally cheating. -It even has a syntax error...! -There isn't even any corresponding longtype. Should perhaps -be just removed. -""" - -def long_getattr(i, attr): - if attr == "__class__": - return int - raise AttributeError, .... - -def long_long(value): - return long(value) From jacob at codespeak.net Sat Jun 21 18:57:58 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 21 Jun 2003 18:57:58 +0200 (MEST) Subject: [pypy-svn] rev 878 - pypy/trunk/src/pypy/tool Message-ID: <20030621165758.B934D5AC55@thoth.codespeak.net> Author: jacob Date: Sat Jun 21 18:57:58 2003 New Revision: 878 Added: pypy/trunk/src/pypy/tool/methodChecker.py Log: Tool for checking what methods are implemented in the main built in object types. Added: pypy/trunk/src/pypy/tool/methodChecker.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/tool/methodChecker.py Sat Jun 21 18:57:58 2003 @@ -0,0 +1,77 @@ +import autopath +from pypy.objspace.std import Space +from pypy.interpreter import baseobjspace, executioncontext, pyframe + +class MethodChecker(object): + """ Checks which methods are available on builtin objects.""" + + def __init__(self): + types = (1, 1.0, 'a', [], {}, (), None) + + self.space = Space() + + totalImplemented = 0 + totalNotImplemented = 0 + str = ['-', 'Implemented'] + + for oneType in types: + subImplemented = 0 + subNotImplemented = 0 + + attribArr = dir(type(oneType)) + for attrib in attribArr: + x = self.codetest('def f():\n return hasattr("%s","%s")\n' + % (oneType, attrib), 'f', []) + print '%-16s%-18s%s' % (type(oneType), attrib, str[x]) + if x: + subImplemented += 1 + totalImplemented += 1 + else: + subNotImplemented += 1 + totalNotImplemented += 1 + print + print ' %-16s Implemented: %3d' % (type(oneType), + subImplemented) + print ' %-16s Not implemented: %3d' % (type(oneType), + subNotImplemented) + print ' %-16s TOTAL: %3d' % ( + type(oneType), subNotImplemented + subImplemented) + print + + print 'TOTAL Implemented: %3d' % totalImplemented + print 'TOTAL Not implemented: %3d' % totalNotImplemented + print 'GRAND TOTAL: %3d' % ( + totalNotImplemented + totalImplemented) + + def codetest(self, source, functionname, args): + """Compile and run the given code string, and then call its function + named by 'functionname' with arguments 'args'.""" + space = self.space + + compile = space.builtin.compile + w = space.wrap + w_code = compile(w(source), w(''), w('exec'), w(0), w(0)) + + ec = executioncontext.ExecutionContext(space) + + w_tempmodule = space.newmodule(w("__temp__")) + w_glob = space.getattr(w_tempmodule, w("__dict__")) + space.setitem(w_glob, w("__builtins__"), space.w_builtins) + + frame = pyframe.PyFrame(space, space.unwrap(w_code), w_glob, w_glob) + ec.eval_frame(frame) + + wrappedargs = w(args) + wrappedfunc = space.getitem(w_glob, w(functionname)) + wrappedkwds = space.newdict([]) + try: + w_output = space.call(wrappedfunc, wrappedargs, wrappedkwds) + except baseobjspace.OperationError, e: + #e.print_detailed_traceback(space) + return '<<<%s>>>' % e.errorstr(space) + else: + return space.unwrap(w_output) + + +if __name__ == '__main__': + MethodChecker() From jacob at codespeak.net Sat Jun 21 18:59:20 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 21 Jun 2003 18:59:20 +0200 (MEST) Subject: [pypy-svn] rev 879 - pypy/trunk/src/pypy/interpreter Message-ID: <20030621165920.706725AC55@thoth.codespeak.net> Author: jacob Date: Sat Jun 21 18:59:20 2003 New Revision: 879 Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py Log: Name change. Modified: pypy/trunk/src/pypy/interpreter/unittest_w.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/unittest_w.py (original) +++ pypy/trunk/src/pypy/interpreter/unittest_w.py Sat Jun 21 18:59:20 2003 @@ -33,24 +33,26 @@ class WrappedFunc(object): + def __init__(self, testCase, testMethod): self.testCase = testCase self.testMethod = testMethod + def __call__(self): from pypy.interpreter import executioncontext from pypy.interpreter import pyframe - s = self.testCase.space - w = s.wrap + space = self.testCase.space + w = space.wrap w_tc_attr = 'tc-attr-hacky-thing' - if hasattr(s, w_tc_attr): - w_tc = getattr(s, w_tc_attr) + if hasattr(space, w_tc_attr): + w_tc = getattr(space, w_tc_attr) else: - w_tc = make_testcase_class(s, self.testCase) - setattr(s, w_tc_attr, w_tc) + w_tc = make_testcase_class(space, self.testCase) + setattr(space, w_tc_attr, w_tc) - w_f = wrap_func(s, self.testMethod.im_func) - s.call_function(w_f, w_tc) + w_f = wrap_func(space, self.testMethod.im_func) + space.call_function(w_f, w_tc) class IntTestCase(unittest.TestCase): From mwh at codespeak.net Sat Jun 21 19:01:23 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 19:01:23 +0200 (MEST) Subject: [pypy-svn] rev 880 - pypy/trunk/src/pypy/interpreter Message-ID: <20030621170123.5322E5AC55@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 19:01:23 2003 New Revision: 880 Modified: pypy/trunk/src/pypy/interpreter/py.py Log: support for -c Modified: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/py.py (original) +++ pypy/trunk/src/pypy/interpreter/py.py Sat Jun 21 19:01:23 2003 @@ -6,17 +6,32 @@ class Options(option.Options): interactive = 0 + command = [] def get_main_options(): options = option.get_standard_options() options.append(make_option( '-i', action="store_true", dest="interactive")) + + def command_callback(option, opt, value, parser): + parser.values.command = parser.rargs[:] + parser.rargs[:] = [] + + options.append(make_option( + '-c', action="callback", + callback=command_callback)) + return options def main_(argv=None): args = option.process_options(get_main_options(), Options, argv[1:]) space = option.objspace() - if args: + if Options.command: + try: + main.run_string(Options.command[0], '', space) + except baseobjspace.PyPyError, pypyerr: + pypyerr.operationerr.print_detailed_traceback(pypyerr.space) + elif args: try: main.run_file(args[0], space) except baseobjspace.PyPyError, pypyerr: @@ -25,7 +40,6 @@ con = interactive.PyPyConsole(space) con.interact() - if __name__ == '__main__': main_(sys.argv) From mwh at codespeak.net Sat Jun 21 19:07:33 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 19:07:33 +0200 (MEST) Subject: [pypy-svn] rev 882 - in pypy/trunk/src/pypy: interpreter tool Message-ID: <20030621170733.52FDB5AC55@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 19:07:32 2003 New Revision: 882 Modified: pypy/trunk/src/pypy/interpreter/py.py pypy/trunk/src/pypy/tool/option.py Log: add some help for docstrings Modified: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/py.py (original) +++ pypy/trunk/src/pypy/interpreter/py.py Sat Jun 21 19:07:32 2003 @@ -11,7 +11,8 @@ def get_main_options(): options = option.get_standard_options() options.append(make_option( - '-i', action="store_true", dest="interactive")) + '-i', action="store_true", dest="interactive", + help="inspect interactively after running script")) def command_callback(option, opt, value, parser): parser.values.command = parser.rargs[:] @@ -19,7 +20,8 @@ options.append(make_option( '-c', action="callback", - callback=command_callback)) + callback=command_callback, + help="program passed in as CMD (terminates option list)")) return options Modified: pypy/trunk/src/pypy/tool/option.py ============================================================================== --- pypy/trunk/src/pypy/tool/option.py (original) +++ pypy/trunk/src/pypy/tool/option.py Sat Jun 21 19:07:32 2003 @@ -22,9 +22,11 @@ callback=objspace_callback, callback_args=("trivial",), help="run in trivial object space")) options.append(make_option( - '-v', action="count", dest="verbose")) + '-v', action="count", dest="verbose", + help="verbose")) options.append(make_option( - '-w', action="store_true", dest="showwarning")) + '-w', action="store_true", dest="showwarning", + help="something to do with warnings (ask Holger!)")) return options From mwh at codespeak.net Sat Jun 21 19:26:49 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 21 Jun 2003 19:26:49 +0200 (MEST) Subject: [pypy-svn] rev 883 - pypy/trunk/src/pypy/interpreter Message-ID: <20030621172649.E83085AC55@thoth.codespeak.net> Author: mwh Date: Sat Jun 21 19:26:49 2003 New Revision: 883 Modified: pypy/trunk/src/pypy/interpreter/py.py Log: *cough* take notice of -i *cough* still need to do some banner suppression, though Modified: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/py.py (original) +++ pypy/trunk/src/pypy/interpreter/py.py Sat Jun 21 19:26:49 2003 @@ -28,6 +28,7 @@ def main_(argv=None): args = option.process_options(get_main_options(), Options, argv[1:]) space = option.objspace() + go_interactive = Options.interactive if Options.command: try: main.run_string(Options.command[0], '', space) @@ -39,9 +40,10 @@ except baseobjspace.PyPyError, pypyerr: pypyerr.operationerr.print_detailed_traceback(pypyerr.space) else: + go_interactive = 1 + if go_interactive: con = interactive.PyPyConsole(space) con.interact() - if __name__ == '__main__': main_(sys.argv) From hpk at codespeak.net Sat Jun 21 19:33:11 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 19:33:11 +0200 (MEST) Subject: [pypy-svn] rev 884 - pypy/trunk/src/pypy Message-ID: <20030621173311.57DE65AC55@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 19:33:11 2003 New Revision: 884 Modified: pypy/trunk/src/pypy/__init__.py Log: test checkin please ignore Modified: pypy/trunk/src/pypy/__init__.py ============================================================================== --- pypy/trunk/src/pypy/__init__.py (original) +++ pypy/trunk/src/pypy/__init__.py Sat Jun 21 19:33:11 2003 @@ -1 +1 @@ -# empty +# empty (testing checkin) From arigo at codespeak.net Sat Jun 21 19:36:22 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 21 Jun 2003 19:36:22 +0200 (MEST) Subject: [pypy-svn] rev 885 - pypy/trunk/src/pypy/interpreter Message-ID: <20030621173622.350595A415@thoth.codespeak.net> Author: arigo Date: Sat Jun 21 19:36:21 2003 New Revision: 885 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py pypy/trunk/src/pypy/interpreter/pyframe.py Log: more general executioncontexts and control flow exceptions Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sat Jun 21 19:36:21 2003 @@ -32,6 +32,9 @@ w_globals = self.space.newdict([(w_key, w_value)]) return w_globals + def bytecode_trace(self, frame): + "Trace function called before each bytecode." + def exception_trace(self, operationerr): "Trace function called upon OperationError." operationerr.record_interpreter_traceback() Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Sat Jun 21 19:36:21 2003 @@ -36,6 +36,7 @@ try: while True: try: + executioncontext.bytecode_trace(self) last_instr = self.next_instr try: # fetch and dispatch the next opcode @@ -50,15 +51,16 @@ e.record_application_traceback(self, last_instr) self.last_exception = e executioncontext.exception_trace(e) - # convert an OperationError into a reason to unroll - # the stack + # convert an OperationError into a control flow + # exception raise SApplicationException(e) # XXX some other exceptions could be caught here too, # like KeyboardInterrupt - except StackUnroller, unroller: - # we have a reason to unroll the stack - unroller.unrollstack(self) + except ControlFlowException, ctlflowexc: + # we have a reason to change the control flow + # (typically unroll the stack) + ctlflowexc.action(self) except ExitFrame, e: # leave that frame @@ -124,7 +126,7 @@ # because the current valuestack is no longer deep enough # to hold the corresponding information while self.exceptionstack: - unroller, valuestackdepth = self.exceptionstack.top() + ctlflowexc, valuestackdepth = self.exceptionstack.top() if valuestackdepth <= self.valuestack.depth(): break self.exceptionstack.pop() @@ -209,7 +211,7 @@ def cleanup(self, frame): # upon normal entry into the finally: part, the standard Python # bytecode pushes a single None for END_FINALLY. In our case we - # always push three values into the stack: the wrapped unroller, + # always push three values into the stack: the wrapped ctlflowexc, # the exception value and the exception type (which are all None # here). self.cleanupstack(frame) @@ -229,10 +231,12 @@ raise StopUnrolling -### Block Stack unrollers ### +### Internal exceptions that change the control flow ### +### and (typically) unroll the block stack ### -class StackUnroller(Exception): - """Abstract base class for interpreter-level exceptions that unroll the +class ControlFlowException(Exception): + """Abstract base class for interpreter-level exceptions that + instruct the interpreter to change the control flow and the block stack. The concrete subclasses correspond to the various values WHY_XXX @@ -247,7 +251,7 @@ WHY_YIELD SYieldValue """ - def unrollstack(self, frame): + def action(self, frame): "Default unroller implementation." try: while not frame.blockstack.empty(): @@ -262,7 +266,7 @@ # could occur e.g. when a BREAK_LOOP is not actually within a loop raise BytecodeCorruption, "block stack exhausted" -class SApplicationException(StackUnroller): +class SApplicationException(ControlFlowException): """Unroll the stack because of an application-level exception (i.e. an OperationException).""" def emptystack(self, frame): @@ -270,14 +274,14 @@ operationerr = self.args[0] raise operationerr -class SBreakLoop(StackUnroller): +class SBreakLoop(ControlFlowException): """Signals a 'break' statement.""" -class SContinueLoop(StackUnroller): +class SContinueLoop(ControlFlowException): """Signals a 'continue' statement. Argument is the bytecode position of the beginning of the loop.""" -class SReturnValue(StackUnroller): +class SReturnValue(ControlFlowException): """Signals a 'return' statement. Argument is the wrapped object to return.""" def emptystack(self, frame): @@ -285,10 +289,10 @@ w_returnvalue = self.args[0] raise ExitFrame(w_returnvalue) -class SYieldValue(StackUnroller): +class SYieldValue(ControlFlowException): """Signals a 'yield' statement. Argument is the wrapped object to return.""" - def unrollstack(self, frame): + def action(self, frame): # XXX generators raise OperationError(frame.space.w_Exception, frame.space.wrap("generators are not ready yet")) From hpk at codespeak.net Sat Jun 21 19:40:10 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Jun 2003 19:40:10 +0200 (MEST) Subject: [pypy-svn] rev 886 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621174010.468525A415@thoth.codespeak.net> Author: hpk Date: Sat Jun 21 19:40:09 2003 New Revision: 886 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: implemented ljust, rjust and some tests Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sat Jun 21 19:40:09 2003 @@ -166,7 +166,7 @@ res = CharArraySize(reslen) pos = 0 - #fill in the string buffer + #fill in the string buffer" for w_item in list: if firstelem: res.setsubstring(pos, w_item._value.value()) @@ -182,17 +182,30 @@ return W_StringObject(space, "") -def str_ljust__String_ANY(space, w_str, w_arg): - # XXX look away for three lines, please :-) -- mwh +def str_rjust__String_ANY(space, w_self, w_arg): u = space.unwrap - w = space.wrap - return w(u(w_str).ljust(u(w_arg))) -def str_rjust__String_ANY(space, w_str, w_arg): - # XXX and another three -- mwh + u_arg = u(w_arg) + u_self = u(w_self) + + d = u_arg - len(u_self) + if d>0: + u_self = d * ' ' + u_self + + return W_StringObject(space, u_self) + + +def str_ljust__String_ANY(space, w_self, w_arg): u = space.unwrap - w = space.wrap - return w(u(w_str).rjust(u(w_arg))) + + u_self = u(w_self) + u_arg = u(w_arg) + + d = u_arg - len(u_self) + if d>0: + u_self += d * ' ' + + return W_StringObject(space, u_self) def unwrap__String(space, w_str): return w_str._value.value() Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sat Jun 21 19:40:09 2003 @@ -114,6 +114,17 @@ w_slice = space.newslice(w(1), w_None, w(2)) self.assertEqual_w(space.getitem(w_str, w_slice), w('el')) + +#AttributeError: W_StringObject instance has no attribute 'ljust' +# def test_ljust(self): +# w = self.space.wrap +# s = "abc" +# +# self.assertEqual_w(w(s).ljust(2), w(s)) +# self.assertEqual_w(w(s).ljust(3), w(s)) +# self.assertEqual_w(w(s).ljust(4), w(s + " ")) +# self.assertEqual_w(w(s).ljust(5), w(s + " ")) + class TestStringObject(test.AppTestCase): def test_split(self): self.assertEquals("".split(), []) @@ -124,8 +135,20 @@ def test_split_splitchar(self): self.assertEquals("/a/b/c".split('/'), ['','a','b','c']) + def test_rjust(self): + s = "abc" + self.assertEquals(s.rjust(2), s) + self.assertEquals(s.rjust(3), s) + self.assertEquals(s.rjust(4), " " + s) + self.assertEquals(s.rjust(5), " " + s) + def test_ljust(self): - self.assertEquals("abc".ljust(5), "abc ") + s = "abc" + self.assertEquals(s.ljust(2), s) + self.assertEquals(s.ljust(3), s) + self.assertEquals(s.ljust(4), s + " ") + self.assertEquals(s.ljust(5), s + " ") + def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) From guenter at codespeak.net Sat Jun 21 19:45:10 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Sat, 21 Jun 2003 19:45:10 +0200 (MEST) Subject: [pypy-svn] rev 887 - pypy/trunk/src/pypy Message-ID: <20030621174510.3F0FC5A415@thoth.codespeak.net> Author: guenter Date: Sat Jun 21 19:45:09 2003 New Revision: 887 Modified: pypy/trunk/src/pypy/__init__.py Log: test checkin Modified: pypy/trunk/src/pypy/__init__.py ============================================================================== --- pypy/trunk/src/pypy/__init__.py (original) +++ pypy/trunk/src/pypy/__init__.py Sat Jun 21 19:45:09 2003 @@ -1 +1 @@ -# empty (testing checkin) +# empty From tomek at codespeak.net Sat Jun 21 19:55:46 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Sat, 21 Jun 2003 19:55:46 +0200 (MEST) Subject: [pypy-svn] rev 889 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030621175546.E5CB35A415@thoth.codespeak.net> Author: tomek Date: Sat Jun 21 19:55:46 2003 New Revision: 889 Modified: pypy/trunk/src/pypy/objspace/std/rarray.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: I added two methods, title and capitalize, and the tests Modified: pypy/trunk/src/pypy/objspace/std/rarray.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/rarray.py (original) +++ pypy/trunk/src/pypy/objspace/std/rarray.py Sat Jun 21 19:55:46 2003 @@ -44,6 +44,10 @@ """returns char at the index""" return self._value[idx] + def setcharat(self, idx, ch): + """sets char at the index""" + self._value[idx] = ch + def setsize(self, size): """set size of the buffer to size""" self._value = array.array('c', ' ' * size) Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sat Jun 21 19:55:46 2003 @@ -86,6 +86,44 @@ def str_istitle(space, w_self): pass +def str_upper__String(space, w_self): + up = W_StringObject(space, w_self._value.value()) + for i in range(up._value.len): + ch = up._value.charat(i) + if _islower(ch): + o = ord(ch) - 32 + up._value.setcharat(i, chr(o)) + + return up + +def str_capitalize__String(space, w_self): + w_str = W_StringObject(space, space.unwrap(w_self)) + buffer = w_str._value + if buffer.len > 0: + ch = buffer.charat(0) + if _islower(ch): + o = ord(ch) - 32 + buffer.setcharat(0, chr(o)) + return w_str + +def str_title__String(space, w_self): + w_str = W_StringObject(space, space.unwrap(w_self)) + buffer = w_str._value + inword = 0 + + for pos in range(0, buffer.len): + ch = buffer.charat(pos) + if ch.isspace(): + if inword: + inword = 0 + else: + if not inword: + if _islower(ch): + o = ord(ch) - 32 + buffer.setcharat(pos, chr(o)) + inword = 1 + return w_str + def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1): res = [] inword = 0 Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sat Jun 21 19:55:46 2003 @@ -9,15 +9,20 @@ str_join = MultiMethod('join', 2) str_split = MultiMethod('split', 3, defaults=(None,-1)) - str_isdigit = MultiMethod('isdigit', 1) - str_isalpha = MultiMethod('isalpha', 1) - str_isspace = MultiMethod('isspace', 1) - str_isupper = MultiMethod('isupper', 1) - str_islower = MultiMethod('islower', 1) - str_istitle = MultiMethod('istitle', 1) - str_isalnum = MultiMethod('isalnum', 1) - str_ljust = MultiMethod('ljust', 2) - str_rjust = MultiMethod('rjust', 2) + str_isdigit = MultiMethod('isdigit', 1) + str_isalpha = MultiMethod('isalpha', 1) + str_isspace = MultiMethod('isspace', 1) + str_isupper = MultiMethod('isupper', 1) + str_islower = MultiMethod('islower', 1) + str_istitle = MultiMethod('istitle', 1) + str_isalnum = MultiMethod('isalnum', 1) + str_ljust = MultiMethod('ljust', 2) + str_rjust = MultiMethod('rjust', 2) + str_upper = MultiMethod('upper', 1) + str_capitalize = MultiMethod('capitalize', 1) + str_title = MultiMethod('title', 1) + + # XXX we'll worry about the __new__/__init__ distinction later def new__StringType_ANY_ANY(space, w_stringtype, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sat Jun 21 19:55:46 2003 @@ -135,6 +135,12 @@ def test_split_splitchar(self): self.assertEquals("/a/b/c".split('/'), ['','a','b','c']) + def test_title(self): + self.assertEquals("brown fox".title(), "Brown Fox") + + def test_capitalize(self): + self.assertEquals("brown fox".capitalize(), "Brown fox") + def test_rjust(self): s = "abc" self.assertEquals(s.rjust(2), s) From jacob at codespeak.net Sat Jun 21 20:02:36 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 21 Jun 2003 20:02:36 +0200 (MEST) Subject: [pypy-svn] rev 890 - in pypy/trunk/src/pypy/interpreter: . test Message-ID: <20030621180236.A7A6F5A532@thoth.codespeak.net> Author: jacob Date: Sat Jun 21 20:02:36 2003 New Revision: 890 Modified: pypy/trunk/src/pypy/interpreter/main.py pypy/trunk/src/pypy/interpreter/test/test_main.py Log: Added eval_string to main.py Modified: pypy/trunk/src/pypy/interpreter/main.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/main.py (original) +++ pypy/trunk/src/pypy/interpreter/main.py Sat Jun 21 20:02:36 2003 @@ -5,14 +5,19 @@ from pypy.interpreter import executioncontext, baseobjspace, pyframe import sys, os -def run_string(source, fname, space=None): +def _run_eval_string(source, filename, space, eval): + if eval: + cmd = 'eval' + else: + cmd = 'exec' + try: if space is None: space = StdObjSpace() compile = space.builtin.compile - w=space.wrap - w_code = compile(w(source), w(fname), w('exec'), + w = space.wrap + w_code = compile(w(source), w(filename), w(cmd), w(0), w(0)) ec = executioncontext.ExecutionContext(space) @@ -27,13 +32,22 @@ operationerr.record_interpreter_traceback() raise baseobjspace.PyPyError(space, operationerr) else: - ec.eval_frame(frame) + if eval: + return ec.eval_frame(frame) + else: + ec.eval_frame(frame) + +def run_string(source, filename='', space=None): + _run_eval_string(source, filename, space, False) + +def eval_string(source, filename='', space=None): + return _run_eval_string(source, filename, space, True) -def run_file(fname, space=None): +def run_file(filename, space=None): if __name__=='__main__': - print "Running %r with %r" % (fname, space) - istring = open(fname).read() - run_string(istring, fname, space) + print "Running %r with %r" % (filename, space) + istring = open(filename).read() + run_string(istring, filename, space) def main(argv=None): if argv is None: Modified: pypy/trunk/src/pypy/interpreter/test/test_main.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_main.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_main.py Sat Jun 21 20:02:36 2003 @@ -5,6 +5,8 @@ from pypy.tool import test from pypy.interpreter.baseobjspace import OperationError +from pypy.interpreter import main + testcode = """\ def main(): aStr = 'hello world' @@ -32,9 +34,10 @@ testfn = 'tmp_hello_world.py' -class TestMain(unittest.TestCase): +class TestMain(test.TestCase): def setUp(self): + self.space = test.objspace() ofile = open(testfn, 'w') ofile.write(testcode) ofile.close() @@ -44,14 +47,15 @@ os.remove(testfn) def test_run_file(self): - from pypy.interpreter import main self.assert_(checkoutput(testresultoutput,main.run_file,testfn)) def test_run_string(self): - from pypy.interpreter import main self.assert_(checkoutput(testresultoutput, main.run_string,testcode,testfn)) + def test_eval_string(self): + w_x = main.eval_string('2+2', space=self.space) + self.assertEqual_w(w_x, self.space.wrap(4)) + if __name__ == '__main__': - unittest.main() - + test.main() From hpk at codespeak.net Sun Jun 22 10:56:48 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 10:56:48 +0200 (MEST) Subject: [pypy-svn] rev 891 - pypy/trunk/doc Message-ID: <20030622085648.D48285A22F@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 10:56:48 2003 New Revision: 891 Modified: pypy/trunk/doc/coding-style.txt Log: test checkin with some info added Modified: pypy/trunk/doc/coding-style.txt ============================================================================== --- pypy/trunk/doc/coding-style.txt (original) +++ pypy/trunk/doc/coding-style.txt Sun Jun 22 10:56:48 2003 @@ -44,6 +44,7 @@ - the PYTHONPATH should be set to the filesytstem equivalent of http://codespeak.net:8080/svn/pypy/trunk/src + in fact the "autopath" module does this for you. - __init__.py is always empty except for "pypy/objspace/*" From jacob at codespeak.net Sun Jun 22 10:59:14 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sun, 22 Jun 2003 10:59:14 +0200 (MEST) Subject: [pypy-svn] rev 892 - pypy/trunk/src/pypy/tool Message-ID: <20030622085914.38BEE5A0B4@thoth.codespeak.net> Author: jacob Date: Sun Jun 22 10:59:13 2003 New Revision: 892 Modified: pypy/trunk/src/pypy/tool/methodChecker.py Log: Made methodChecker use eval_string in main.py Modified: pypy/trunk/src/pypy/tool/methodChecker.py ============================================================================== --- pypy/trunk/src/pypy/tool/methodChecker.py (original) +++ pypy/trunk/src/pypy/tool/methodChecker.py Sun Jun 22 10:59:13 2003 @@ -1,18 +1,17 @@ import autopath from pypy.objspace.std import Space -from pypy.interpreter import baseobjspace, executioncontext, pyframe +from pypy.interpreter.main import eval_string class MethodChecker(object): - """ Checks which methods are available on builtin objects.""" + """ Checks which methods are available on builtin types.""" - def __init__(self): - types = (1, 1.0, 'a', [], {}, (), None) + def __init__(self, types=(1, 1.0, 'a', [], {}, (), None)): - self.space = Space() + space = Space() + str = ['-', 'Implemented'] totalImplemented = 0 totalNotImplemented = 0 - str = ['-', 'Implemented'] for oneType in types: subImplemented = 0 @@ -20,8 +19,9 @@ attribArr = dir(type(oneType)) for attrib in attribArr: - x = self.codetest('def f():\n return hasattr("%s","%s")\n' - % (oneType, attrib), 'f', []) + x = space.unwrap(eval_string( + 'hasattr("%s","%s")\n' % (oneType, attrib), + '', space)) print '%-16s%-18s%s' % (type(oneType), attrib, str[x]) if x: subImplemented += 1 @@ -43,35 +43,5 @@ print 'GRAND TOTAL: %3d' % ( totalNotImplemented + totalImplemented) - def codetest(self, source, functionname, args): - """Compile and run the given code string, and then call its function - named by 'functionname' with arguments 'args'.""" - space = self.space - - compile = space.builtin.compile - w = space.wrap - w_code = compile(w(source), w(''), w('exec'), w(0), w(0)) - - ec = executioncontext.ExecutionContext(space) - - w_tempmodule = space.newmodule(w("__temp__")) - w_glob = space.getattr(w_tempmodule, w("__dict__")) - space.setitem(w_glob, w("__builtins__"), space.w_builtins) - - frame = pyframe.PyFrame(space, space.unwrap(w_code), w_glob, w_glob) - ec.eval_frame(frame) - - wrappedargs = w(args) - wrappedfunc = space.getitem(w_glob, w(functionname)) - wrappedkwds = space.newdict([]) - try: - w_output = space.call(wrappedfunc, wrappedargs, wrappedkwds) - except baseobjspace.OperationError, e: - #e.print_detailed_traceback(space) - return '<<<%s>>>' % e.errorstr(space) - else: - return space.unwrap(w_output) - - if __name__ == '__main__': MethodChecker() From hpk at codespeak.net Sun Jun 22 11:00:08 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 11:00:08 +0200 (MEST) Subject: [pypy-svn] rev 893 - pypy/trunk/doc Message-ID: <20030622090008.A98B05A22F@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 11:00:08 2003 New Revision: 893 Modified: pypy/trunk/doc/ObSpIntfc.txt Log: added a dot. Modified: pypy/trunk/doc/ObSpIntfc.txt ============================================================================== --- pypy/trunk/doc/ObSpIntfc.txt (original) +++ pypy/trunk/doc/ObSpIntfc.txt Sun Jun 22 11:00:08 2003 @@ -65,7 +65,7 @@ --------------------------------------- **wrap(x):** - Return ObjectSpace equivalent of x + Return ObjectSpace equivalent of x. **newbool(b):** Creates a Bool Object from an interpreter level object. From hpk at codespeak.net Sun Jun 22 11:08:25 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 11:08:25 +0200 (MEST) Subject: [pypy-svn] rev 894 - pypy/trunk/doc Message-ID: <20030622090825.26C545A0B4@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 11:08:24 2003 New Revision: 894 Modified: pypy/trunk/doc/ObSpIntfc.txt Log: added a dot Modified: pypy/trunk/doc/ObSpIntfc.txt ============================================================================== --- pypy/trunk/doc/ObSpIntfc.txt (original) +++ pypy/trunk/doc/ObSpIntfc.txt Sun Jun 22 11:08:24 2003 @@ -83,7 +83,7 @@ Makes a new slice object. **newfunction(w_code, w_globals, w_defaultarguments, w_closure=None):** - Creates a new function object + Creates a new function object. **newstring(asciilist):** Creates a string from a list of integers. From hpk at codespeak.net Sun Jun 22 11:10:41 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 11:10:41 +0200 (MEST) Subject: [pypy-svn] rev 895 - pypy/trunk/doc Message-ID: <20030622091041.B506F5A22F@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 11:10:41 2003 New Revision: 895 Modified: pypy/trunk/doc/ObSpIntfc.txt Log: added a dot Modified: pypy/trunk/doc/ObSpIntfc.txt ============================================================================== --- pypy/trunk/doc/ObSpIntfc.txt (original) +++ pypy/trunk/doc/ObSpIntfc.txt Sun Jun 22 11:10:41 2003 @@ -24,7 +24,7 @@ ---------------------------- **initialize():** - Function which initializes w_builtins and the other w_constants + Function which initializes w_builtins and the other w_constants. **getexecutioncontext():** Return current active execution context. From hpk at codespeak.net Sun Jun 22 11:13:55 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 11:13:55 +0200 (MEST) Subject: [pypy-svn] rev 896 - pypy/trunk/doc Message-ID: <20030622091355.65AE15A22F@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 11:13:55 2003 New Revision: 896 Modified: pypy/trunk/doc/ObSpIntfc.txt Log: added a dot Modified: pypy/trunk/doc/ObSpIntfc.txt ============================================================================== --- pypy/trunk/doc/ObSpIntfc.txt (original) +++ pypy/trunk/doc/ObSpIntfc.txt Sun Jun 22 11:13:55 2003 @@ -53,7 +53,7 @@ Call the next function for iterator w. **call(callable, args, kwds):** - Call a function with the given args and keywords + Call a function with the given args and keywords. **is_(w_x, w_y):** Implements 'w_x is w_y'. From mwh at codespeak.net Sun Jun 22 11:20:44 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 11:20:44 +0200 (MEST) Subject: [pypy-svn] rev 897 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622092044.266195A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 11:20:43 2003 New Revision: 897 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py Log: kill old code Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Sun Jun 22 11:20:43 2003 @@ -112,24 +112,6 @@ w_keys = dict_keys__Dict(space, w_dict) return iterobject.W_SeqIterObject(space, w_keys) - -##def getattr_dict(space, w_dict, w_attr): -## if space.is_true(space.eq(w_attr, space.wrap('copy'))): -## w_builtinfn = make_builtin_func(space, W_DictObject.copy) -## return W_InstMethObject(space, w_dict, w_builtinfn) -## if space.is_true(space.eq(w_attr, space.wrap('items'))): -## w_builtinfn = make_builtin_func(space, W_DictObject.items) -## return W_InstMethObject(space, w_dict, w_builtinfn) -## if space.is_true(space.eq(w_attr, space.wrap('keys'))): -## w_builtinfn = make_builtin_func(space, W_DictObject.keys) -## return W_InstMethObject(space, w_dict, w_builtinfn) -## if space.is_true(space.eq(w_attr, space.wrap('values'))): -## w_builtinfn = make_builtin_func(space, W_DictObject.values) -## return W_InstMethObject(space, w_dict, w_builtinfn) -## raise FailedToImplement(space.w_AttributeError) - -##StdObjSpace.getattr.register(getattr_dict, W_DictObject, W_ANY) - def eq__Dict_Dict(space, w_left, w_right): if len(w_left.data) != len(w_right.data): return space.newbool(0) From mwh at codespeak.net Sun Jun 22 11:21:15 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 11:21:15 +0200 (MEST) Subject: [pypy-svn] rev 898 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622092115.B0CB85A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 11:21:15 2003 New Revision: 898 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py Log: kill import too. Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Sun Jun 22 11:21:15 2003 @@ -1,7 +1,6 @@ from pypy.objspace.std.objspace import * from dicttype import W_DictType from stringobject import W_StringObject -from instmethobject import W_InstMethObject from pypy.interpreter.extmodule import make_builtin_func class _NoValueInCell: pass From mwh at codespeak.net Sun Jun 22 11:22:55 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 11:22:55 +0200 (MEST) Subject: [pypy-svn] rev 899 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622092255.6DFA55A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 11:22:55 2003 New Revision: 899 Modified: pypy/trunk/src/pypy/objspace/std/listobject.py Log: kill another old import. Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Sun Jun 22 11:22:55 2003 @@ -2,7 +2,6 @@ from listtype import W_ListType from intobject import W_IntObject from sliceobject import W_SliceObject -from instmethobject import W_InstMethObject from pypy.interpreter.extmodule import make_builtin_func from restricted_int import r_int, r_uint From mwh at codespeak.net Sun Jun 22 11:26:11 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 11:26:11 +0200 (MEST) Subject: [pypy-svn] rev 900 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622092611.9F0395A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 11:26:11 2003 New Revision: 900 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py Log: kill yet another old import. Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 11:26:11 2003 @@ -3,7 +3,6 @@ from intobject import W_IntObject from sliceobject import W_SliceObject from listobject import W_ListObject -from instmethobject import W_InstMethObject from noneobject import W_NoneObject from tupleobject import W_TupleObject From gvanrossum at codespeak.net Sun Jun 22 11:36:29 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 11:36:29 +0200 (MEST) Subject: [pypy-svn] rev 901 - in pypy/trunk/src/pypy: interpreter objspace/ann objspace/ann/test tool Message-ID: <20030622093629.66F9C5A0B4@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 11:36:28 2003 New Revision: 901 Added: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (contents, props changed) Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/interpreter/executioncontext.py pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_simple.py pypy/trunk/src/pypy/tool/methodChecker.py (props changed) Log: Clone the frame when in indeterminate 'if' is found. Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Sun Jun 22 11:36:28 2003 @@ -50,9 +50,13 @@ "Return what we consider to be the active execution context." ec = threadlocals.getlocals().executioncontext if ec is None: - ec = ExecutionContext(self) + ec = self.createexecutioncontext() return ec + def createexecutioncontext(self): + "Factory function for execution contexts." + return ExecutionContext(self) + def gethelper(self, applicationfile): try: helper = self.appfile_helpers[applicationfile] Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sun Jun 22 11:36:28 2003 @@ -226,6 +226,11 @@ def empty(self): return not self.items + def clone(self): + s = Stack() + s.items = self.items[:] + return s + # installing the excepthook for OperationErrors def operr_excepthook(exctype, value, traceback): Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Sun Jun 22 11:36:28 2003 @@ -30,6 +30,16 @@ self.last_exception = None self.next_instr = 0 + def clone(self): + f = PyFrame(self.space, self.bytecode, self.w_globals, self.w_locals) + f.valuestack = self.valuestack.clone() + f.blockstack = self.blockstack.clone() + f.last_exception = self.last_exception + f.next_instr = self.next_instr + # Clone the locals (only the annotation space implements this) + f.w_locals = self.space.clone_locals(self.w_locals) + return f + def eval(self, executioncontext): "Interpreter main loop!" from pypy.interpreter import opcode @@ -60,7 +70,7 @@ except ControlFlowException, ctlflowexc: # we have a reason to change the control flow # (typically unroll the stack) - ctlflowexc.action(self) + ctlflowexc.action(self, last_instr) except ExitFrame, e: # leave that frame @@ -251,7 +261,7 @@ WHY_YIELD SYieldValue """ - def action(self, frame): + def action(self, frame, last_instr): "Default unroller implementation." try: while not frame.blockstack.empty(): @@ -292,7 +302,7 @@ class SYieldValue(ControlFlowException): """Signals a 'yield' statement. Argument is the wrapped object to return.""" - def action(self, frame): + def action(self, frame, last_instr): # XXX generators raise OperationError(frame.space.w_Exception, frame.space.wrap("generators are not ready yet")) Added: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Sun Jun 22 11:36:28 2003 @@ -0,0 +1,44 @@ +from pypy.interpreter.executioncontext import ExecutionContext +from pypy.interpreter.pyframe import ControlFlowException + +class IndeterminateCondition(ControlFlowException): + + def __init__(self, w_obj): + ControlFlowException.__init__(self) + self.w_obj = w_obj + + def action(self, frame, last_instr): + frame.next_instr = last_instr + f2 = frame.clone() + clones = frame.clones + clones.append(f2) + f2.clones = clones # Share the joy + f2.force_w_obj = self.w_obj + self.w_obj.force = True + +class CloningExecutionContext(ExecutionContext): + + lastframe = None + + def bytecode_trace(self, frame): + self.lastframe = frame + + def eval_frame(self, frame): + from pypy.objspace.ann.objspace import W_Anything + assert not hasattr(frame, "clones") + space = frame.space + clones = [frame] + frame.clones = clones + frame.force_w_obj = None + result = None # W_Impossible + while clones: + f = clones.pop() + w_obj = f.force_w_obj + if w_obj is not None: + assert w_obj.force == True + w_obj.force = False + r = ExecutionContext.eval_frame(self, f) + result = space.union(result, r) + if isinstance(result, W_Anything): + break + return result Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sun Jun 22 11:36:28 2003 @@ -4,6 +4,8 @@ from pypy.interpreter.baseobjspace \ import ObjSpace, OperationError, NoValue, PyPyError from pypy.interpreter.pycode import PyByteCode +from pypy.objspace.ann.cloningcontext import CloningExecutionContext +from pypy.objspace.ann.cloningcontext import IndeterminateCondition class W_Object(object): @@ -28,11 +30,20 @@ return len(self.args_w) def __getitem__(self, i): return self.args_w[i] + def clone(self): + args_w = self.args_w + if isinstance(args_w, dict): + args_w = args_w.copy() + # XXX Recurse down the values? + return W_KnownKeysContainer(args_w) class AnnException(Exception): pass +class UnwrapException(AnnException): + pass + class AnnotationObjSpace(ObjSpace): @@ -48,7 +59,7 @@ setattr(self, 'w_' + c.__name__, self.wrap(c)) self.w_builtins = self.wrap(__builtin__) - # Service methods + # Service methods whose interface is in the abstract base class def wrap(self, obj): return W_Constant(obj) @@ -57,21 +68,59 @@ if isinstance(w_obj, W_Constant): return w_obj.value elif isinstance(w_obj, W_Object): - raise AnnException, "Cannot unwrap %r" % w_obj + raise UnwrapException("Cannot unwrap: " +repr(w_obj)) else: - raise TypeError, "not wrapped: %s" % repr(w_obj) - - def is_true(self, w_obj): - if isinstance(w_obj, W_KnownKeysContainer): - return bool(len(w_obj)) - obj = self.unwrap(w_obj) - return bool(obj) + raise TypeError("not wrapped: " + repr(w_obj)) def reraise(self): t, v = sys.exc_info()[:2] raise OperationError(self.wrap(t), self.wrap(v)) - # Specialized creators + def is_true(self, w_obj): + if hasattr(w_obj, "force"): + return w_obj.force # Forced by cloning machinery + if isinstance(w_obj, W_KnownKeysContainer): + return bool(len(w_obj)) + try: + obj = self.unwrap(w_obj) + except UnwrapException: + pass + else: + return bool(obj) + # It's indeterminate!!! Aargh!!! + # Raise an exception that will clone the interpreter. + raise IndeterminateCondition(w_obj) + + def createexecutioncontext(self): + return CloningExecutionContext(self) + + def clone_locals(self, w_locals): + assert isinstance(w_locals, W_KnownKeysContainer) + return w_locals.clone() + + def union(self, r1, r2): + # Unite two results + if r1 is r2: + return r1 + if r1 is None: + return r2 + if r2 is None: + return r1 + if isinstance(r1, W_Anything) or isinstance(r2, W_Anything): + return W_Anything() + if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and + r1.value == r2.value): + return W_Constant(r1.value) + if self.is_int(r1) and self.is_int(r2): + return W_Integer() + if (isinstance(r1, W_KnownKeysContainer) and + isinstance(r2, W_KnownKeysContainer) and + r1.args_w == r2.args_w): + return W_KnownKeysContainer(r1.args_w) + # XXX Could do more cases. This will blow up as we add more types + return W_Anything() + + # Specialized creators whose interface is in the abstract base class def newtuple(self, args_w): for w_arg in args_w: @@ -84,7 +133,7 @@ for w_key, w_value in items_w: try: key = self.unwrap(w_key) - except AnnException: + except UnwrapException: break else: values_w[key] = w_value @@ -105,7 +154,7 @@ try: left = self.unwrap(w_left) right = self.unwrap(w_right) - except AnnException: + except UnwrapException: pass else: return self.wrap(left + right) @@ -141,7 +190,7 @@ try: obj = self.unwrap(w_obj) name = self.unwrap(w_name) - except AnnException: + except UnwrapException: return W_Anything() else: try: @@ -154,7 +203,7 @@ return self.wrap(len(w_obj)) try: obj = self.unwrap(w_obj) - except AnnException: + except UnwrapException: return W_Anything() else: return self.wrap(len(obj)) @@ -162,11 +211,11 @@ def getitem(self, w_obj, w_key): try: key = self.unwrap(w_key) - except AnnException: + except UnwrapException: return W_Anything() try: obj = self.unwrap(w_obj) - except AnnException: + except UnwrapException: if isinstance(w_obj, W_KnownKeysContainer): return w_obj[key] else: Modified: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_simple.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sun Jun 22 11:36:28 2003 @@ -2,23 +2,23 @@ from pypy.tool import test from pypy.objspace.ann.objspace import W_Object, W_Anything, W_Integer from pypy.objspace.ann.objspace import AnnotationObjSpace -from pypy.interpreter import baseobjspace, executioncontext, pyframe +from pypy.interpreter import baseobjspace, pyframe class TestAnnotationObjSpace(test.TestCase): def codetest(self, source, functionname, args_w): """Compile and run the given code string, and then call its function named by 'functionname' with a list of wrapped arguments 'args_w'. - It returns the wrapped result.""" + Return the wrapped result.""" glob = {} exec source in glob + func = glob[functionname] - space = self.space - w_args = space.newtuple(args_w) - w_func = space.wrap(glob[functionname]) - w_kwds = space.newdict([]) - return space.call(w_func, w_args, w_kwds) + w_args = self.space.newtuple(args_w) + w_func = self.space.wrap(func) + w_kwds = self.space.newdict([]) + return self.space.call(w_func, w_args, w_kwds) def setUp(self): self.space = AnnotationObjSpace() @@ -47,6 +47,24 @@ 'f', [W_Integer()]) self.assertEquals(type(x), W_Integer) + def test_conditional_1(self): + x = self.codetest("def f(i):\n" + " if i < 0:\n" + " return 0\n" + " else:\n" + " return 1\n", + 'f', [W_Integer()]) + self.assertEquals(type(x), W_Integer) + + def test_conditional_2(self): + x = self.codetest("def f(i):\n" + " if i < 0:\n" + " return 0\n" + " else:\n" + " return 0\n", + 'f', [W_Integer()]) + self.assertEquals(self.space.unwrap(x), 0) + if __name__ == '__main__': From arigo at codespeak.net Sun Jun 22 11:39:23 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 22 Jun 2003 11:39:23 +0200 (MEST) Subject: [pypy-svn] rev 902 - pypy/trunk/src/pypy/objspace/ann/test Message-ID: <20030622093923.DCCEC5A0B4@thoth.codespeak.net> Author: arigo Date: Sun Jun 22 11:39:23 2003 New Revision: 902 Added: pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py - copied unchanged from rev 901, pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Removed: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Log: test rename Deleted: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sun Jun 22 11:39:23 2003 +++ (empty file) @@ -1,71 +0,0 @@ -import autopath -from pypy.tool import test -from pypy.objspace.ann.objspace import W_Object, W_Anything, W_Integer -from pypy.objspace.ann.objspace import AnnotationObjSpace -from pypy.interpreter import baseobjspace, pyframe - -class TestAnnotationObjSpace(test.TestCase): - - def codetest(self, source, functionname, args_w): - """Compile and run the given code string, and then call its function - named by 'functionname' with a list of wrapped arguments 'args_w'. - Return the wrapped result.""" - - glob = {} - exec source in glob - func = glob[functionname] - - w_args = self.space.newtuple(args_w) - w_func = self.space.wrap(func) - w_kwds = self.space.newdict([]) - return self.space.call(w_func, w_args, w_kwds) - - def setUp(self): - self.space = AnnotationObjSpace() - - def test_any2any(self): - x = self.codetest("def f(i):\n" - " return i+1\n", - 'f', [W_Anything()]) - self.assertEquals(type(x), W_Anything) - - def test_const2const(self): - x = self.codetest("def f(i):\n" - " return i+1\n", - 'f', [self.space.wrap(5)]) - self.assertEquals(self.space.unwrap(x), 6) - - def test_constany2const(self): - x = self.codetest("def f(i, j):\n" - " return i+1\n", - 'f', [self.space.wrap(5), W_Anything()]) - self.assertEquals(self.space.unwrap(x), 6) - - def test_int2int(self): - x = self.codetest("def f(i):\n" - " return i+1\n", - 'f', [W_Integer()]) - self.assertEquals(type(x), W_Integer) - - def test_conditional_1(self): - x = self.codetest("def f(i):\n" - " if i < 0:\n" - " return 0\n" - " else:\n" - " return 1\n", - 'f', [W_Integer()]) - self.assertEquals(type(x), W_Integer) - - def test_conditional_2(self): - x = self.codetest("def f(i):\n" - " if i < 0:\n" - " return 0\n" - " else:\n" - " return 0\n", - 'f', [W_Integer()]) - self.assertEquals(self.space.unwrap(x), 0) - - - -if __name__ == '__main__': - test.main() From mwh at codespeak.net Sun Jun 22 11:48:37 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 11:48:37 +0200 (MEST) Subject: [pypy-svn] rev 903 - pypy/trunk/src/pypy/interpreter Message-ID: <20030622094837.89BD65A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 11:48:37 2003 New Revision: 903 Modified: pypy/trunk/src/pypy/interpreter/interactive.py pypy/trunk/src/pypy/interpreter/py.py Log: some banner suppression for -i total banner suppression would seem to involve rewriting code.py, sigh Modified: pypy/trunk/src/pypy/interpreter/interactive.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/interactive.py (original) +++ pypy/trunk/src/pypy/interpreter/interactive.py Sun Jun 22 11:48:37 2003 @@ -27,9 +27,11 @@ self.space.wrap("__name__"), self.space.wrap("__main__")) - def interact(self): - banner = "Python %s in pypy\n%s / %s" % ( - sys.version, self.__class__.__name__, self.space.__class__.__name__) + def interact(self, banner=None): + if banner is None: + banner = "Python %s in pypy\n%s / %s" % ( + sys.version, self.__class__.__name__, + self.space.__class__.__name__) code.InteractiveConsole.interact(self, banner) def runcode(self, code): Modified: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/py.py (original) +++ pypy/trunk/src/pypy/interpreter/py.py Sun Jun 22 11:48:37 2003 @@ -29,6 +29,7 @@ args = option.process_options(get_main_options(), Options, argv[1:]) space = option.objspace() go_interactive = Options.interactive + banner = '' if Options.command: try: main.run_string(Options.command[0], '', space) @@ -41,9 +42,13 @@ pypyerr.operationerr.print_detailed_traceback(pypyerr.space) else: go_interactive = 1 + banner = None if go_interactive: con = interactive.PyPyConsole(space) - con.interact() + if banner == '': + banner = '%s / %s'%(con.__class__.__name__, + space.__class__.__name__) + con.interact(banner) if __name__ == '__main__': main_(sys.argv) From mwh at codespeak.net Sun Jun 22 11:49:56 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 11:49:56 +0200 (MEST) Subject: [pypy-svn] rev 904 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622094956.188D05A22F@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 11:49:55 2003 New Revision: 904 Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py pypy/trunk/src/pypy/objspace/std/instmethobject.py pypy/trunk/src/pypy/objspace/std/sliceobject.py pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py Log: implement unbound methods you can't actually create one yet, but hey, it's a start Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Sun Jun 22 11:49:55 2003 @@ -39,7 +39,7 @@ return w_ret def get__Func_ANY_ANY(space, w_function, w_instance, w_cls): - return W_InstMethObject(space, w_instance, w_function) + return W_InstMethObject(space, w_function, w_instance, w_cls) def getattr__Func_ANY(space, w_function, w_attr): if space.is_true(space.eq(w_attr, space.wrap('func_code'))): Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Sun Jun 22 11:49:55 2003 @@ -21,17 +21,28 @@ class W_InstMethObject(W_Object): statictype = W_InstMethType - def __init__(w_self, space, w_im_self, w_im_func): + def __init__(w_self, space, w_im_func, w_im_self, w_im_class): W_Object.__init__(w_self, space) w_self.w_im_self = w_im_self w_self.w_im_func = w_im_func + w_self.w_im_class = w_im_class registerimplementation(W_InstMethObject) -def call__InstMeth_ANY_ANY(space, w_instmeth, w_arguments, w_keywords): - w_args = space.add(space.newtuple([w_instmeth.w_im_self]), - w_arguments) +def call__InstMeth_ANY_ANY(space, w_instmeth, w_args, w_keywords): + if w_instmeth.w_im_self == None: + w_self = space.getitem(w_args, space.wrap(0)) + w_selftype = space.type(w_self) + w_issubtype = space.issubtype(w_selftype, w_instmeth.w_im_class) + if not space.is_true(w_issubtype): + raise OperationError(space.w_TypeError, + space.wrap("unbound method %s() must be " + "called with %s instance as first " + "argument (got %s instance instead)")) + else: + w_args = space.add(space.newtuple([w_instmeth.w_im_self]), + w_args) w_ret = space.call(w_instmeth.w_im_func, w_args, w_keywords) return w_ret Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Sun Jun 22 11:49:55 2003 @@ -53,7 +53,7 @@ return w_slice.w_step if space.is_true(space.eq(w_attr, space.wrap('indices'))): w_builtinfn = make_builtin_func(space, W_SliceObject.indices2) - return W_InstMethObject(space, w_slice, w_builtinfn) + return W_InstMethObject(space, w_builtinfn, w_slice, w_slice.w_statictype) raise FailedToImplement(space.w_AttributeError) Modified: pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py Sun Jun 22 11:49:55 2003 @@ -1,17 +1,34 @@ -import autopath -from pypy.tool import test - -class TestInstMethObject(test.AppTestCase): - def test_callBound(self): - boundMethod = [1,2,3].__len__ - self.assertEquals(boundMethod(), 3) - self.assertRaises(TypeError, boundMethod, 333) - def notworking_test_callUnbound(self): - unboundMethod = list.__len__ - self.assertEquals(unboundMethod([1,2,3]), 3) - self.assertRaises(TypeError, unboundMethod) - self.assertRaises(TypeError, unboundMethod, 333) - self.assertRaises(TypeError, unboundMethod, [1,2,3], 333) - -if __name__ == '__main__': - test.main() +import autopath +from pypy.tool import test + +class TestInstMethObject(test.TestCase): + def setUp(self): + self.space = test.objspace('std') + + def test_unbound(self): + from pypy.objspace.std.instmethobject import W_InstMethObject + space = self.space + w_list = space.newlist([]) + w_boundmeth = space.getattr(w_list, space.wrap('__len__')) + w_unboundmeth = W_InstMethObject(space, + w_boundmeth.w_im_func, + None, + w_boundmeth.w_im_class) + self.assertEqual_w(space.call_function(w_unboundmeth, w_list), + space.wrap(0)) + + +class TestInstMethObjectApp(test.AppTestCase): + def test_callBound(self): + boundMethod = [1,2,3].__len__ + self.assertEquals(boundMethod(), 3) + self.assertRaises(TypeError, boundMethod, 333) + def notworking_test_callUnbound(self): + unboundMethod = list.__len__ + self.assertEquals(unboundMethod([1,2,3]), 3) + self.assertRaises(TypeError, unboundMethod) + self.assertRaises(TypeError, unboundMethod, 333) + self.assertRaises(TypeError, unboundMethod, [1,2,3], 333) + +if __name__ == '__main__': + test.main() From gvanrossum at codespeak.net Sun Jun 22 11:50:44 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 11:50:44 +0200 (MEST) Subject: [pypy-svn] rev 905 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030622095044.F24355A22F@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 11:50:44 2003 New Revision: 905 Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Log: delete some unused code, Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Sun Jun 22 11:50:44 2003 @@ -18,10 +18,6 @@ class CloningExecutionContext(ExecutionContext): - lastframe = None - - def bytecode_trace(self, frame): - self.lastframe = frame def eval_frame(self, frame): from pypy.objspace.ann.objspace import W_Anything From guenter at codespeak.net Sun Jun 22 12:01:22 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Sun, 22 Jun 2003 12:01:22 +0200 (MEST) Subject: [pypy-svn] rev 906 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622100122.ED29F5A22F@thoth.codespeak.net> Author: guenter Date: Sun Jun 22 12:01:22 2003 New Revision: 906 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: Stringobject. methods strip, rstrip and lstrip implemented Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 12:01:22 2003 @@ -3,6 +3,7 @@ from intobject import W_IntObject from sliceobject import W_SliceObject from listobject import W_ListObject +from instmethobject import W_InstMethObject from noneobject import W_NoneObject from tupleobject import W_TupleObject @@ -244,6 +245,45 @@ return W_StringObject(space, u_self) + +def str_strip__String(space, w_self): + u = space.unwrap + u_self = u(w_self) + lpos = 0 + while u_self[lpos] == ' ': + lpos += 1 + + rpos = len(u_self) + while u_self[rpos - 1] == ' ': + rpos -= 1 + + return W_StringObject(space, u_self[lpos:rpos]) + + + +def str_rstrip__String(space, w_self): + u = space.unwrap + u_self = u(w_self) + + rpos = len(u_self) + while u_self[rpos - 1] == ' ': + rpos -= 1 + + return W_StringObject(space, u_self[:rpos]) + + + +def str_lstrip__String(space, w_self): + u = space.unwrap + u_self = u(w_self) + lpos = 0 + while u_self[lpos] == ' ': + lpos += 1 + + return W_StringObject(space, u_self[lpos:]) + + + def unwrap__String(space, w_str): return w_str._value.value() @@ -394,7 +434,6 @@ def mod__String_Tuple(space, w_str, w_tuple): return space.wrap(space.unwrap(w_str)%space.unwrap(w_tuple)) - # register all methods register_all(vars(), W_StringType) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sun Jun 22 12:01:22 2003 @@ -21,7 +21,9 @@ str_upper = MultiMethod('upper', 1) str_capitalize = MultiMethod('capitalize', 1) str_title = MultiMethod('title', 1) - + str_strip = MultiMethod('strip', 1) + str_rstrip = MultiMethod('rstrip', 1) + str_lstrip = MultiMethod('lstrip', 1) # XXX we'll worry about the __new__/__init__ distinction later Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sun Jun 22 12:01:22 2003 @@ -154,7 +154,12 @@ self.assertEquals(s.ljust(3), s) self.assertEquals(s.ljust(4), s + " ") self.assertEquals(s.ljust(5), s + " ") - + + def test_strip(self): + s = " a b " + self.assertEquals(s.strip(), "a b") + self.assertEquals(s.rstrip(), " a b") + self.assertEquals(s.lstrip(), "a b ") def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) From hpk at codespeak.net Sun Jun 22 12:05:07 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 12:05:07 +0200 (MEST) Subject: [pypy-svn] rev 907 - pypy/trunk/src/pypy/interpreter Message-ID: <20030622100507.E11F55A22F@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 12:05:07 2003 New Revision: 907 Modified: pypy/trunk/src/pypy/interpreter/py.py Log: made it directly executable under unix Modified: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/py.py (original) +++ pypy/trunk/src/pypy/interpreter/py.py Sun Jun 22 12:05:07 2003 @@ -1,3 +1,5 @@ +#!/usr/bin/env python + import autopath from pypy.tool import option from pypy.tool.optik import make_option From jacob at codespeak.net Sun Jun 22 12:20:18 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sun, 22 Jun 2003 12:20:18 +0200 (MEST) Subject: [pypy-svn] rev 908 - pypy/trunk/src/pypy/tool Message-ID: <20030622102018.C20A35A22F@thoth.codespeak.net> Author: jacob Date: Sun Jun 22 12:20:18 2003 New Revision: 908 Modified: pypy/trunk/src/pypy/tool/methodChecker.py Log: Fixed bug in methodChecker. Now gives reasonable output. Modified: pypy/trunk/src/pypy/tool/methodChecker.py ============================================================================== --- pypy/trunk/src/pypy/tool/methodChecker.py (original) +++ pypy/trunk/src/pypy/tool/methodChecker.py Sun Jun 22 12:20:18 2003 @@ -5,7 +5,7 @@ class MethodChecker(object): """ Checks which methods are available on builtin types.""" - def __init__(self, types=(1, 1.0, 'a', [], {}, (), None)): + def __init__(self, types=(1, 1.0, "'a'", [], {}, (), None)): space = Space() str = ['-', 'Implemented'] @@ -20,7 +20,7 @@ attribArr = dir(type(oneType)) for attrib in attribArr: x = space.unwrap(eval_string( - 'hasattr("%s","%s")\n' % (oneType, attrib), + 'hasattr(%s,"%s")\n' % (oneType, attrib), '', space)) print '%-16s%-18s%s' % (type(oneType), attrib, str[x]) if x: From tismer at codespeak.net Sun Jun 22 12:26:08 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:26:08 +0200 (MEST) Subject: [pypy-svn] rev 909 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622102608.72FB75A22F@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:26:08 2003 New Revision: 909 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py Log: fixed typos/thinkos wrt notimplemented Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 12:26:08 2003 @@ -355,7 +355,7 @@ elif op == GE: return space.newbool(c >= 0) else: - raise NotImplemented + return NotImplemented def lt__String_String(space, w_str1, w_str2): return string_richcompare(space, w_str1, w_str2, LT) @@ -410,7 +410,7 @@ return W_StringObject(space, buf.value()) def mod_str_tuple(space, w_format, w_args): - notImplemented + raise NotImplementedError def len__String(space, w_str): return space.wrap(w_str._value.len) From lac at codespeak.net Sun Jun 22 12:26:15 2003 From: lac at codespeak.net (lac at codespeak.net) Date: Sun, 22 Jun 2003 12:26:15 +0200 (MEST) Subject: [pypy-svn] rev 910 - pypy/trunk/doc Message-ID: <20030622102615.ACDF25A22F@thoth.codespeak.net> Author: lac Date: Sun Jun 22 12:26:15 2003 New Revision: 910 Modified: pypy/trunk/doc/sprint-planning.txt Log: Announce that we finished our tool. Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sun Jun 22 12:26:15 2003 @@ -40,7 +40,7 @@ - write a small tool that checks a type's methods of CPython against PyPy - (Jacob, Laura) + (Jacob, Laura) done - improve "main.py" tool and rename it to "py.py" :-) with a subset of the options of "python". This From tismer at codespeak.net Sun Jun 22 12:28:05 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:28:05 +0200 (MEST) Subject: [pypy-svn] rev 911 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622102805.B84625A22F@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:28:05 2003 New Revision: 911 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: added newint method Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 22 12:28:05 2003 @@ -222,6 +222,10 @@ import cpythonobject return cpythonobject.W_CPythonObject(self, x) + def newint(self, int_w): + import intobject + return intobject.W_IntObject(self, int_w) + def newtuple(self, list_w): import tupleobject return tupleobject.W_TupleObject(self, list_w) From tismer at codespeak.net Sun Jun 22 12:29:25 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:29:25 +0200 (MEST) Subject: [pypy-svn] rev 912 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622102925.E140D5A22F@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:29:25 2003 New Revision: 912 Modified: pypy/trunk/src/pypy/objspace/std/intobject.py pypy/trunk/src/pypy/objspace/std/inttype.py Log: added ability to call int Modified: pypy/trunk/src/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/intobject.py Sun Jun 22 12:29:25 2003 @@ -125,7 +125,7 @@ # Armin: unlike CPython we have no need to special-case the value -1 return w_int1 -# Chris: I'm not yet convinced that we want to make has() +# Chris: I'm not yet convinced that we want to make hash() # return different values that CPython does. # So for the moment, both versions are here, # and we might think of some config options Modified: pypy/trunk/src/pypy/objspace/std/inttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/inttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/inttype.py Sun Jun 22 12:29:25 2003 @@ -5,3 +5,20 @@ class W_IntType(W_TypeObject): typename = 'int' + + +# XXX we'll worry about the __new__/__init__ distinction later +def inttype_new(space, w_inttype, w_args, w_kwds): + if space.is_true(w_kwds): + raise OperationError(space.w_TypeError, + space.wrap("no keyword arguments expected")) + args = space.unpackiterable(w_args) + if len(args) == 0: + return space.newint(0) + elif len(args) == 1: + return space.newint(args[0]) + else: + raise OperationError(space.w_TypeError, + space.wrap("int() takes at most 1 argument")) + +StdObjSpace.new.register(inttype_new, W_IntType, W_ANY, W_ANY) From anna at codespeak.net Sun Jun 22 12:30:19 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 12:30:19 +0200 (MEST) Subject: [pypy-svn] rev 913 - pypy/trunk/doc/objspacedoc Message-ID: <20030622103019.8E6005A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 12:30:19 2003 New Revision: 913 Added: pypy/trunk/doc/objspacedoc/ pypy/trunk/doc/objspacedoc/AbObSp.txt pypy/trunk/doc/objspacedoc/AnnotateObSp.txt pypy/trunk/doc/objspacedoc/MultiMeth.txt pypy/trunk/doc/objspacedoc/ObSpIntfc.txt pypy/trunk/doc/objspacedoc/ObjSpc.txt pypy/trunk/doc/objspacedoc/RestrictedPython.txt pypy/trunk/doc/objspacedoc/StObSp.txt pypy/trunk/doc/objspacedoc/TrivObSp.txt Log: adding directory Added: pypy/trunk/doc/objspacedoc/AbObSp.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/AbObSp.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,16 @@ +======================= +AbstractObjectSpace +======================= + +User History +------------------------ + +This is an example of abstract interpretation, i.e. following the bytecode instructions of a program like an interpreter does but with abstract objects instead of concrete ones. Remember that in PyPy this is done by using alternate object spaces with the same interpreter main loop. + +The most abstract object space is the one manipulating the most abstract objects that you could imagine: they are all equivalent, because we have abstracted away any information about the object. There is actually only one of them left, and we can call it "the object". In Python terms, our AbstractObjectSpace uses None for all its wrapped objects. Any operation between wrapped objects gives None again as the wrapped result -- there is nothing else it could give anyway. So when you have said that the add method of AbstractObjectSpace takes None and None and returns None you have said everything. + +The point of such an object space is for example to check the bytecode. The interpreter will really run your bytecode, just with completely abstract arguments. If there is no problem then you are sure that the bytecode is valid. You could also record, during this abstract interpretation, how much the stack ever grows; that would give you a fool-proof method of computing the co_stacksize argument of a code object which might be useful for the PyPy compiler. (There are subtleties which I won't describe here, but that's the basic idea.) + +Typically, however, abstract object spaces are a (little) bit less abstract, still maintaining a minimal amount of information about the objects. For example, a wrapped object could be represented by its type. You then define the object space's add to return int when the two arguments are int and int. That way, you abstractedly call a function with the input argument's types and what the interpreter will do is a type inference. (Here also there are subtle problems, even besides the remark that integer operations can overflow and actually return longs in a real Python implementation.) + +As an example of more abstract object spaces you have the ones with finite domain, i.e. with a finite number of different possible wrapped objects. For example, you can use True and False as wrapped values to denote the fact that the object is, respectively, a non-negative integer or anything else. In this way you are doing another kind of type inference that just tells you which variables will only ever contain non-negative integers. Added: pypy/trunk/doc/objspacedoc/AnnotateObSp.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/AnnotateObSp.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,29 @@ +========================= +Annotated Object Space +========================= + +was TranslateObjectSpace +------------------------- +This has been renamed and is currently being re-written. Old information follows: + +User History +------------------ + +This is an example of an ObjectSpace that differs a lot from StandardObjectSpace_. + +At some point in the near future we will have to design a translator from all the RestrictedPython_ code we have into C code. This is the sine qua non condition for our work to be actually usable. Quite unexpectedly, the major piece of the translator is itself an object space, the TranslateObjectSpace. Its goal is to run any RestrictedPython code and produce C code in the background as it does so. + +More specifically, we take our PyPy interpreter with the TranslateObjectSpace instead of the StandardObjectSpace, and run that, asking it to interpret some RestrictedPython bytecode. The idea is that a wrapped object is now the name of a variable in the C program we are emitting: + +The TranslateObjectSpace's add method takes two such variable names x and y, and emits the C code z=x+y;, where z is a new variable name which is returned as the result of add. So when the interpreter goes along the bytecode, the TranslateObjectSpace will create variable names and emit C code that does just the same thing as the bytecode. + +The above description is what would occur if RestrictedPython only had integer data types. We must actually make the wrapped objects a bit more elaborate to also record, besides the C variable name, its basic type. This can be easy, like prefixing the variable name with a type character; for example, add would behave as above if the variable names begin with ``i_`` but differently if they begin with the prefix denoting floats or lists, say. + +Once you grasp the idea that this process can actually easily translate any RestrictedPython to C, and if you remember that the interpreter main loop itself is written in RestrictedPython, then you shouldn't be surprised if I say that all we have to do next is run the interpreter to interpret itself (and thus translate itself to C)! + +This is again a rough sketch, but it shows why I expect translating RestrictedPython to C to be easy. The RestrictedPython is precisely restricted in such a way that makes the above process work, e.g. we only ever use well-known types and operations that are easy to convert to an efficient C equivalent. (For example, if lists are translated to C arrays, I'm sure Christian would insist on not using '+' between lists in RestrictedPython but rather '+=', which has a more direct translation as realloc() -- although by now he might be convinced that supporting '+' as a bonus isn't going to be any difficult anyway :-) ) + +------------------------------ + +.. _StandardObjectSpace: StObSp.html +.. _RestrictedPython: RestrictedPython.html Added: pypy/trunk/doc/objspacedoc/MultiMeth.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/MultiMeth.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,143 @@ +======================== +PyPython MultiMethod +======================== + +Notes on Multimethods +------------------------ + +Interpreter-level classes correspond to implementations of application-level +types. Several implementations can be given for the same type (e.g. several +ways to code strings or dictionaries), and conversely the same implementation +can cover several types (e.g. all instances of user-defined types currently +share the same implementation). + +The hierarchy among the classes used for the implementations is convenient +for implementation purposes. It is not related to any application-level type +hierarchy. + +Dispatch +------------------- + +Multimethods dispatch by looking in a set of registered functions. Each +registered function has a signature, which defines which object implementation +classes are accepted at the corresponding argument position. + +The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' +later). As it accepts anything, it is the only way to guarantee that the +registered function will be called with exactly the same object as was +passed originally. ATTENTION: in all other cases the argument received by +the function may have been converted in some way. It must thus not be +considered to be 'id'entical to the original argument. For example it should +not be stored in a data structure, nor be queried for type, nor be used for +another multimethod dispatch -- the only thing you should do is read and +write its internal data. + +For example, 'getattr(obj, attr)' is implemented with a ``W_StringObject`` second +argument when all it needs is just the name of the attr, and with a W_ANY +when the 'attr' object could be used as a key in ``obj.__dict__``. + + +Delegation +--------------- + +Delegation is a transparent convertion mechanism between object +implementations. The convertion can give a result of a different type +(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). +There is a global table of delegators. We should not rely on the delegators +to be tried in any particlar order, or at all (e.g. the int -> float delegator +could be ignored when we know that no registered function will accept a float +anyway). + +Delegation is also used to emulate inheritance between built-in types +(e.g. bool -> int). This is done by delegation because there is no reason +that a particular implementation of a sub-type can be trivially typecast +to some other particular implementation of the parent type; the process might +require some work. + + +Types +--------- + +Types are implemented by the class W_TypeObject. This is where inheritance +and the Method Resolution Order are defined, and where attribute look-ups +are done. + +Instances of user-defined types are implementated as W_UserObjects. +A user-defined type can inherit from built-in types (maybe more than one, +although this is incompatible with CPython). The W_UserObject delegator +converts the object into any of these "parent objects" if needed. This is +how user-defined types appear to inherit all built-in operator +implementations. + +Delegators should be able to invoke user code; this would let us +implement special methods like __int__() by calling them within a +W_UserObject -> int delegator. + +Specifics of multimethods +--------------------------- + +Multimethods dispatch more-specific-first, left-to-right (i.e. if there is +an exact match for the first argument it will always be tried first). + +Delegators are automatically chained (i.e. A -> B and B -> C would be +combined to allow for A -> C delegation). + +Delegators do not publish the class of the converted object in advance, +so that the W_UserObject delegator can potentially produce any other +built-in implementation. This means chaining and chain loop detection cannot +be done statically (at least without help from an analysis tool like the +translator-to-C). To break loops, we can assume (unless a particular need +arises) that delegators are looping when they return an object of an +already-seen class. + +Registration +-------------------- + +The register() method of multimethods adds a function to its database of +functions, with the given signature. A function that raises +!FailedToImplement causes the next match to be tried. + +'delegate' is the special unary multimethod that should try to convert +its argument to something else. For greater control, it can also return +a list of 2-tuples (class, object), or an empty list for failure to convert +the argument to anything. All delegators will potentially be tried, and +recursively on each other's results to do chaining. + +A priority ordering between delegators is used. See ``objspace.PRIORITY_*``. + + +Translation +----------------------- + +The code in multimethod.py is not supposed to be read by the +translator-to-C. Special optimized code will be generated instead +(typically some kind of precomputed dispatch tables). + +Delegation is special-cased too. Most delegators will be found +to return an object of a statically known class, which means that +most of the chaining and loop detection can be done in advance. + + +Multimethod slicing +------------------------ + +Multimethods are visible to user code as (bound or unbound) methods +defined for the corresponding types. (At some point built-in functions +like len() and the operator.xxx() should really directly map to the +multimethods themselves, too.) + +To build a method from a multimethod (e.g. as in 'l.append' or +'int.__add__'), the result is actually a "slice" of the whole +multimethod, i.e. a sub-multimethod in which the registration table has +been trimmed down. (Delegation mechanisms are not restricted for sliced +multimethods.) + +Say that C is the class the new method is attached to (in the above +examples, respectively, C=type(l) and C=int). The restriction is +based on the registered class of the first argument ('self' for the +new method) in the signature. If this class corresponds to a fixed +type (as advertized by 'statictype'), and this fixed type is C or a +superclass of C, then we keep it. + +Some multimethods can also be sliced along their second argument, +e.g. for __radd__(). Added: pypy/trunk/doc/objspacedoc/ObSpIntfc.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/ObSpIntfc.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,111 @@ +================================ +PyPython ObjectSpaceInterface +================================ + +Note this is only a draft version of the ObjectSpace_ interface. The reality of the interface depends on the particular implementation you are using. Consult the code for details. + +class ObjSpace +================= + +Data Members +----------------- + ++ ObjSpace.MethodTable: + List of tuples (method name, symbol, number of arguments) for the regular part of the interface. (Tuples are interpreter level.) + ++ self.w_builtins ++ self.w_modules ++ self.appfile_helpers ++ self.w_None: The ObjectSpace's None ++ self.w_True: The ObjectSpace's True ++ self.w_False: The ObjectSpace's False + +Administrative Functions +---------------------------- + +**initialize():** + Function which initializes w_builtins and the other w_constants. + +**getexecutioncontext():** + Return current active execution context. + +**gethelper(applicationfile):** + Get helper for applicationfile. + +Operations on Objects in ObjectSpace +----------------------------------------- + +These functions both take and return "wrapped" objects. + +*The following functions implement the same operations as those in CPython:* + +``id, type, issubtype, iter, repr, str, len, hash,`` + +``getattr, setattr, delattr, getitem, setitem, delitem,`` + +``pos, neg, not_, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,`` + +``lt, le, eq, ne, gt, ge, contains,`` + +``inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor`` + +**next(w):** + Call the next function for iterator w. + +**call(callable, args, kwds):** + Call a function with the given args and keywords. + +**is_(w_x, w_y):** + Implements 'w_x is w_y'. + +**exception_match(w_exc_type, w_check_class):** + Checks if the given exception type matches 'w_check_class'. Used in matching the actual exception raised with the list of those to catch in an except clause. Returns a bool. + +Creation of Application Level objects +--------------------------------------- + +**wrap(x):** + Return ObjectSpace equivalent of x. + +**newbool(b):** + Creates a Bool Object from an interpreter level object. + +**newtuple([..]):** + Take an interpreter level list of wrapped objects. + +**newlist([..]):** + Takes an interpreter level list of wrapped objects. + +**newdict([..]):** + Takes an interpreter level list of interpreter level pairs of wrapped key:wrapped value entries. + +**newslice(w_start, w_end, w_step):** + Makes a new slice object. + +**newfunction(w_code, w_globals, w_defaultarguments, w_closure=None):** + Creates a new function object. + +**newstring(asciilist):** + Creates a string from a list of integers. + +**newmodule(w_name):** + Creates a new module with a given name. + +Conversions from Application Level to Interpreter Level +---------------------------------------------------------- + +**unwrap(w_x):** + Return Interpreter Level equivalent of w_x + +**is_true(w_x):** + Return a interpreter level bool (True or False). + +**unpackiterable(w_iterable, expected_length=None):** + Unpack an iterable object into a real (interpreter level) list. Raise a real ValueError if the expected_length is wrong. + +**unpacktuple(w_tuple, expected_length=None):** + Same as unpackiterable(), but only for tuples. + +--------------------------- + +.. _ObjectSpace: ObjSpcDoc.html Added: pypy/trunk/doc/objspacedoc/ObjSpc.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/ObjSpc.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,39 @@ +===================== +PyPython ObjectSpace +===================== + +See ObjectSpaceInterface_ for a draft version of the interface specification to ObjectSpace objects. +------------------------------------------------------------------------------------------------------ + +In a Python-like language, a running interpreter has three main parts: + ++ the compiler, which represents the static optimization of the source code into an intermediate format, the bytecode; ++ the object library, implementing the various types of objects and their semantics; ++ the main loop, which suffles data around and calls the operations defined in the object library according to the bytecode. + +The main loop generally assumes little about the semantics of the objects: they are essentially black boxes (PyObject pointers). The interpreter stack and the variables only contain such black boxes. Every operation is done via calls to the object library, like PyNumber_Add(). + +In PyPy, the three parts are clearly separated and can be replaced independently. I will discuss below the reasons I think it is very useful to have, in particular, the object library be replaced. We call object space such an object library. The standard object space is the object space that works just like Python's, that is, the object space whose black boxes are real Python objects that work as expected. We will call wrapped objects the black boxes of an object space. + +Here are four examples of object spaces: + +- TrivialObjectSpace_ +- StandardObjectSpace_ +- AbstractObjectSpace_ +- TranslateObjectSpace_ + +(We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.) + +I believe that the above examples should give a hint at why we might really want object spaces that behave differently: this is called abstact interpretation in the litterature. But there are also more funny ways to use object spaces, for example: + ++ running with several object spaces at once, to clearly separate the data into domains ++ proxy object spaces, which forward all requests over a network to a "Python object server" ++ and more... there have been numerous ideas in pypy-dev. + +------------ + +.. _ObjectSpaceInterface: ObSpIntfc.html +.. _TrivialObjectSpace: TrivObSp.html +.. _StandardObjectSpace: StObSp.html +.. _AbstractObjectSpace: AbObSp.html +.. _TranslateObjectSpace: TranObSp.html Added: pypy/trunk/doc/objspacedoc/RestrictedPython.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/RestrictedPython.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,147 @@ +================== +Restricted Python +================== + +We are writing a Python interpreter in Python, using Python's well known ability to step behind the algorithmic problems as language. At first glance, one might think this achives nothing but a better understanding for everbody how the interpreter works. This alone would make it worth doing, but we have much larger goals. + + +CPython vs. PyPy +------------------- + +Compared to the CPython implementation, Python takes the role of the C Code. So actually, we descibe something by Python, which has been coded in C already, with all the restrictions that are implied by C. We are not trying to make the structures of the CPython interpreter more flexible by rewriting things in C, but we want to use Python to give an alternative description of the interpreter. + +The clear advantage is that this description is probably shorter and simpler to read, and many implementation details vanish. The drawback of this approach is that this interpreter will be unbearably slow. + +To get to a useful interpreter again, we need to apply some mappings to the implementation, later. One rather straight-forward is to do a whole program analysis of the PyPy interpreter and create a C source, again. There are many other ways, but let's stick with the easiest approach, first. + +In order to make a C code generator simple, we resrict ourselves to a subset of the Python language, and we adhere to some rules, which make code generation obvious and easy. + + +Restricted Python is Runtime Python +------------------------------------- + +Restricted Python describes a runnable Python interpreter implementation. This is a quite static object that can be suitably described by RPython. But the restrictions do not apply during the startup phase. + + +PyPy Bootstrap +------------------- + +When the PyPy interpreter is started as a CPython program, it can use all of CPython for a while, until it reaches runtime. That is, all executable code will be executed using the full power of Python. + +An example can be found in the implementation, which is quite elegant: For the definition of all the opcodes of the Python interpreter, the module dis is imported and used. This saves us from adding extra modules to PyPy. The import code is run at startup time, and we are allowed to use the CPython builtin import function. + +When the startup code is done, all resulting objects, functions, code blocks etc. must adhere to the runtime restrictions. All initialized modules are written out in a persistent manner. Our current idea is to emit a huge C source file which contains everything created so far. During this process, a whole program analysis is performed, which makes use of the restrictions defined in RPython. This enables the code generator to emit efficient replacements for pure integer objects, for instance. + + +RPython Definition +-------------------- + +It might make sense to define a sublanguage of Python called RPython, with the restrictions depicted below. This is an evolving topic, and we're just collecting things which come up during trying to code the interpreter, so this is no language at all, but an arbitrary set of rules, which are about to be changed all day. + + +Object restrictions +------------------------- + +We are using + +**variables** + the same variable in the same context can receive values of different types, at a possible overhead cost. For example, a variable that can contain a wrapped object or None is efficiently implemented as a PyObject* pointer that can be NULL, but a variable that can contain either an integer or a float must be implemented as a union with a type tag in C. + +**constants** + all module globals are considered constants. + +**integer, float, string, boolean** + avoid string methods and complex operations like slicing with a step + +**tuples** + no variable-length tuples; use them to store or return pairs or n-tuples of values + +**lists** + lists are used as an allocated array; list.append() does naive resizing, so as far as possible use list comprehensions (see below) + +**dicts** + no dicts + +**control structures** + all allowed + +**list comprehensions** + may be used to create allocated, initialized array. the array size must be computable in advance, which implies that we don't allow an if clause. + +**functions** ++ statically called functions may use defaults and a variable number of arguments (which may be passed as a list instead of a tuple, so write code that does not depend on it being a tuple). + ++ dynamic dispatch enforces use of very simple signatures, equal for all functions to be called in that context. At the moment, this occours in the opcode dispatch, only. + +**builtin functions** + A few builtin functions will be used, while this set is not defined completely, yet. Some builtin functions are special forms: + +**range** + does not create an array. It is only allowed in for loops. The step argument must be a constant. + +**len** ++ may be used with basic types that have a length. But len is a special form that is recognized by the compiler. ++ If a certain structure is never touched by len, the compiler might save the length field from the underlying structure. + +``int, float, ord, chr``... are available as simple convertion functions. +``int, float, str``... have a special meaning as a type inside of isinstance only. + +**classes** ++ methods do not change after startup ++ methods are never hidden by attributes ++ inheritance is supported ++ classes are first-class objects too + +**exceptions** ++ fully supported ++ see below for restrictions on exceptions raised by built-in operations + +**objects** + wrapped objects are borrowed from the object space. Just like in CPython, code that needs e.g. a dictionary can use a wrapped dict and the object space operations on it. + +This layout makes the number of types to take care about quite limited. + + +Example: Integer Types +------------------------- + +While implementing the integer type, I (Chris) stumbled over the problem, that integers are quite in flux in CPython right now. Depending on the version, integers either raise an overflow exception or mutate into longs on overflow. Also, shifting right now truncates (upto 2.3) but is going to extend to longs as well. In order to enable us to run the restricted Python stuff in CPython, I needed to use a derived class r_int(int), which always behaves the same: Never leaving its domain, but always staying an integer. + +The r_int type is implemented in a pervasive way: Every operation that involves an r_int creates an r_int as the result. Therefore, the implementation is not cluttered with special type casts. Just the initial value of an emulated integer's intval field is initialized by obj.intval = r_int(val) . This way, the r_int type propagates itself through all operations without extra effort of the programmer. + +This concept looks promising, and since we will need unsigned integers which do not overflow as well, I also created r_uint. It is always a word-sized unsigned integer and never overflows. This will be a building block for things like computing hash values, where wrap-around effects are intended and should be easily coded without lots of explicit mask shuffling. + +Now I think to extend this even more and build a full set of primitive types, which are intended to + ++ define the semantics of the primitive type ++ give a working implementation for unrestricted Python + +These primitive types can later easily be augmented with methods to emit C code instead of executing. I guess this would be implemented in an extra ObjectSpace. + + +Exception rules +--------------------- + +Exceptions are by default not generated for simple cases.:: + + + #!/usr/bin/python + + x = 5 + x = x + 1 # this code is not checked for overflow + + try: + x = x + y + except OverflowError: + # implement using longs + + +Code with no exception handlers does not raise exceptions. By supplying an exception handler, you ask for error checking. Without, you assure the system that the operation cannot overflow. + +Exceptions explicitly raised will always be generated. + + +Testing +------------ + +Besides extra tests which have to be written, PyPy has the advantage that it is runnable on standard CPython. That means, we can run all of PyPy with all exception handling enabled, so we might catch cases where we failed to adhere to our implicit assertions. Added: pypy/trunk/doc/objspacedoc/StObSp.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/StObSp.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,26 @@ +========================= +StandardObjectSpace +========================= + +User History +--------------- + +The StandardObjectSpace is the direct equivalent of CPython's object library (the "Objects/" subdirectory in the distribution). It is an implementation of the common Python types in a lower-level language. + +The StandardObjectSpace defines an abstract parent class, W_Object, and a bunch of subclasses like W_IntObject, W_ListObject, and so on. A wrapped object (a "black box" for the interpreter main loop) is thus an instance of one of these classes. When the main loop invokes an operation, say the addition, between two wrapped objects w1 and w2, the StandardObjectSpace does some internal dispatching (similar to "Object/ abstract.c" in CPython) and invokes a method of the proper W_XyzObject class that can do the operation. The operation itself is done with the primitives allowed by RestrictedPython. The result is constructed as a wrapped object again. For example, compare the following implementation of integer addition with the function "int_add()" in "Object/intobject.c": :: + + def int_int_add(space, w_int1, w_int2): + x = w_int1.intval + y = w_int2.intval + try: + z = x + y + except OverflowError: + raise FailedToImplement(space.w_OverflowError, + space.wrap("integer addition")) + return W_IntObject(z) + +Why such a burden just for integer objects? Why did we have to wrap them into W_IntObject instances? For them it seems it would have been sufficient just to use plain Python integers. But this argumentation fails just like it fails for more complex kind of objects. Wrapping them just like everything else is the cleanest solution. You could introduce case testing wherever you use a wrapped object, to know if it is a plain integer or an instance of (a subclass of) W_Object. But that makes the whole program more complicated. The equivalent in CPython would be to use PyObject* pointers all around except when the object is an integer (after all, integers are directly available in C too). You could represent small integers as odd-valuated pointers. But it puts extra burden on the whole C code, so the CPython team avoided it. + +In our case it is a later optimization that we could make. We just don't want to make it now (and certainly not hard-coded at this level -- it could be introduced by the C translators that we will eventually write). So in summary: wrapping integers as instances is the simple path, while using plain integers instead is the complex path, not the other way around. + +Note that the current StandardObjectSpace implementation uses MultiMethod dispatch instead of the complex rules of "Object/abstract.c". I think that this can be translated to a different low-level dispatch implementation that would be binary compatible with CPython's (basically the PyTypeObject structure and its function pointers). If compatibility is not required it will be more straightforwardly converted into some efficient multimethod code. Added: pypy/trunk/doc/objspacedoc/TrivObSp.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/objspacedoc/TrivObSp.txt Sun Jun 22 12:30:19 2003 @@ -0,0 +1,20 @@ +================================= +PyPython TrivialObjectSpace +================================= + +User History +---------------- + +The easiest way to implement an ObjectSpace is to represent a Python object with itself. + +A PyPy interpreter using the TrivialObjectSpace is an interpreter with its own main loop (written in Python), but this main loop manipulates real Python objects and all operations are done directly on the Python objects. For example, "1" really means "1" and when the interpreter encounters the BINARY_ADD bytecode instructions the TrivialObjectSpace will just add two real Python objects together using Python's "+". The same for lists, dictionaries, classes... We just use Python's own. + +Of course you cannot do this if the goal is to write PyPy in such a way that it doesn't rely on a real underlying Python implementation like CPython. Still, it works, and it has its own uses, like testing our interpreter, or even interpreting a different kind of bytecode -- for example, it could probably be used to emulate generators in any Python version. (That would be quite slow, however.) + +(This is already done; it is funny to watch "dis.dis" disassembling itself painfully slowly :-) ) + +See StandardObjectSpace_ for the rest of the story. + +------------------------------------------------------------------- + +.. _StandardObjectSpace: StObSp.html \ No newline at end of file From anna at codespeak.net Sun Jun 22 12:31:45 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 12:31:45 +0200 (MEST) Subject: [pypy-svn] rev 914 - in pypy/trunk/doc: objspace objspacedoc Message-ID: <20030622103145.26E575A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 12:31:44 2003 New Revision: 914 Added: pypy/trunk/doc/objspace/ - copied from rev 913, pypy/trunk/doc/objspacedoc/ Removed: pypy/trunk/doc/objspacedoc/ Log: renamed directory From mwh at codespeak.net Sun Jun 22 12:39:43 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 12:39:43 +0200 (MEST) Subject: [pypy-svn] rev 915 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622103943.287105A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 12:39:42 2003 New Revision: 915 Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py Log: fix tyop Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Sun Jun 22 12:39:42 2003 @@ -53,7 +53,7 @@ return w_slice.w_step if space.is_true(space.eq(w_attr, space.wrap('indices'))): w_builtinfn = make_builtin_func(space, W_SliceObject.indices2) - return W_InstMethObject(space, w_builtinfn, w_slice, w_slice.w_statictype) + return W_InstMethObject(space, w_builtinfn, w_slice, w_slice.statictype) raise FailedToImplement(space.w_AttributeError) From mwh at codespeak.net Sun Jun 22 12:43:20 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 12:43:20 +0200 (MEST) Subject: [pypy-svn] rev 916 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622104320.CC00F5A22F@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 12:43:20 2003 New Revision: 916 Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: Unbound method support. Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Sun Jun 22 12:43:20 2003 @@ -31,7 +31,9 @@ registerimplementation(W_InstMethObject) def call__InstMeth_ANY_ANY(space, w_instmeth, w_args, w_keywords): - if w_instmeth.w_im_self == None: + if w_instmeth.w_im_self == space.w_Null: + if space.is_true(space.eq(space.len(w_args), space.wrap(0))): + raise OperationError(space.w_TypeError, space.wrap('bleargh')) w_self = space.getitem(w_args, space.wrap(0)) w_selftype = space.type(w_self) w_issubtype = space.issubtype(w_selftype, w_instmeth.w_im_class) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 22 12:43:20 2003 @@ -144,11 +144,13 @@ def initialize(self): from noneobject import W_NoneObject + from nullobject import W_NullObject from boolobject import W_BoolObject from cpythonobject import W_CPythonObject # singletons self.w_None = W_NoneObject(self) + self.w_Null = W_NullObject(self) self.w_False = W_BoolObject(self, False) self.w_True = W_BoolObject(self, True) self.w_NotImplemented = self.wrap(NotImplemented) # XXX do me Modified: pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_instmethobject.py Sun Jun 22 12:43:20 2003 @@ -12,7 +12,7 @@ w_boundmeth = space.getattr(w_list, space.wrap('__len__')) w_unboundmeth = W_InstMethObject(space, w_boundmeth.w_im_func, - None, + space.w_Null, w_boundmeth.w_im_class) self.assertEqual_w(space.call_function(w_unboundmeth, w_list), space.wrap(0)) @@ -23,7 +23,7 @@ boundMethod = [1,2,3].__len__ self.assertEquals(boundMethod(), 3) self.assertRaises(TypeError, boundMethod, 333) - def notworking_test_callUnbound(self): + def test_callUnbound(self): unboundMethod = list.__len__ self.assertEquals(unboundMethod([1,2,3]), 3) self.assertRaises(TypeError, unboundMethod) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sun Jun 22 12:43:20 2003 @@ -145,7 +145,11 @@ return w_type.w_tpname if space.is_true(space.eq(w_attr, space.wrap('__mro__'))): return space.newtuple(list(w_type.getmro())) - raise FailedToImplement + try: + desc = w_type.lookup(w_attr) + except KeyError: + raise FailedToImplement #OperationError(space.w_AttributeError,w_attr) + return space.get(desc, space.w_Null, w_type) register_all(vars()) From tismer at codespeak.net Sun Jun 22 12:46:01 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:46:01 +0200 (MEST) Subject: [pypy-svn] rev 917 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622104601.82F245A0B4@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:46:01 2003 New Revision: 917 Modified: pypy/trunk/src/pypy/objspace/std/inttype.py Log: fixed int(x) Modified: pypy/trunk/src/pypy/objspace/std/inttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/inttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/inttype.py Sun Jun 22 12:46:01 2003 @@ -16,7 +16,7 @@ if len(args) == 0: return space.newint(0) elif len(args) == 1: - return space.newint(args[0]) + return space.newint(space.unwrap(args[0])) else: raise OperationError(space.w_TypeError, space.wrap("int() takes at most 1 argument")) From tismer at codespeak.net Sun Jun 22 12:46:36 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:46:36 +0200 (MEST) Subject: [pypy-svn] rev 918 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622104636.CF7605A0B4@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:46:36 2003 New Revision: 918 Added: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Modified: pypy/trunk/src/pypy/objspace/std/userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: added tests, tested, seems complete and correct Added: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Sun Jun 22 12:46:36 2003 @@ -0,0 +1,45 @@ +import autopath +from pypy.tool import test + +class TestUserObject(test.AppTestCase): + + def test_emptyclass(self): + class empty: pass + inst = empty() + self.failUnless(isinstance(inst, empty)) + inst.attr=23 + self.assertEquals(inst.attr,23) + + def test_subclassing(self): + for base in tuple, list, dict, str, int, float: + try: + class subclass(base): pass + stuff = subclass() + except: + print 'not subclassable:', base + else: + self.failUnless(isinstance(stuff, base)) + + def test_subclasstuple(self): + class subclass(tuple): pass + stuff = subclass() + self.failUnless(isinstance(stuff, tuple)) + stuff.attr = 23 + self.assertEquals(stuff.attr,23) + self.assertEquals(len(stuff),0) + result = stuff + (1,2,3) + self.assertEquals(len(result),3) + + def test_subsubclass(self): + class base: + baseattr = 12 + class derived(base): + derivedattr = 34 + inst = derived() + self.failUnless(isinstance(inst, base)) + self.assertEquals(inst.baseattr,12) + self.assertEquals(inst.derivedattr,34) + + +if __name__ == '__main__': + test.main() Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Sun Jun 22 12:46:36 2003 @@ -1,3 +1,11 @@ +""" +Reviewed 03-06-22 +This object implements "instances of custom types" completely and +accurately. We have selectively tested (in the testfile) a key +selection of features: setting and getting attributes and the +correct working of inheritance from both builtin and user types +as well as of normal and special attributes. +""" from pypy.objspace.std.objspace import * from usertype import W_UserType import typeobject Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Sun Jun 22 12:46:36 2003 @@ -1,3 +1,6 @@ +""" +Reviewed 03-06-22 +""" from __future__ import nested_scopes from pypy.objspace.std.objspace import * import typeobject, objecttype @@ -42,6 +45,14 @@ # XXX we'll worry about the __new__/__init__ distinction later +# XXX NOTE: currently (03-06-21) user-object can only sublass +# types which register an implementation for ?new? -- currently +# this means that e.g. subclassing list or str works, subclassing +# int or float does not -- this is not a bug fixable in userobject +# (perhaps in the object-space, perhaps in each builtin type...?) +# but we're documenting it here as there seems no better place!!! +# The problem is actually that, currently, several types such as +# int and float just cannot be CALLED -- this needs to be fixed soon. def usertype_new(space, w_usertype, w_args, w_kwds): from userobject import W_UserObject newobj = W_UserObject(space, w_usertype, w_args, w_kwds) From tismer at codespeak.net Sun Jun 22 12:48:34 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:48:34 +0200 (MEST) Subject: [pypy-svn] rev 919 - pypy/trunk/doc Message-ID: <20030622104834.09AD45A0B4@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:48:33 2003 New Revision: 919 Modified: pypy/trunk/doc/sprint-planning.txt Log: user done Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sun Jun 22 12:48:33 2003 @@ -26,7 +26,7 @@ instmethobject done longobject done sliceobject done - userobject + userobject done dictobject intobject From anna at codespeak.net Sun Jun 22 12:49:05 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 12:49:05 +0200 (MEST) Subject: [pypy-svn] rev 920 - pypy/trunk/doc/objspace Message-ID: <20030622104905.601D35A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 12:49:05 2003 New Revision: 920 Added: pypy/trunk/doc/objspace/ObjSpace.txt - copied unchanged from rev 918, pypy/trunk/doc/objspace/ObjSpc.txt Removed: pypy/trunk/doc/objspace/ObjSpc.txt Log: renamed file Deleted: pypy/trunk/doc/objspace/ObjSpc.txt ============================================================================== --- pypy/trunk/doc/objspace/ObjSpc.txt Sun Jun 22 12:49:05 2003 +++ (empty file) @@ -1,39 +0,0 @@ -===================== -PyPython ObjectSpace -===================== - -See ObjectSpaceInterface_ for a draft version of the interface specification to ObjectSpace objects. ------------------------------------------------------------------------------------------------------- - -In a Python-like language, a running interpreter has three main parts: - -+ the compiler, which represents the static optimization of the source code into an intermediate format, the bytecode; -+ the object library, implementing the various types of objects and their semantics; -+ the main loop, which suffles data around and calls the operations defined in the object library according to the bytecode. - -The main loop generally assumes little about the semantics of the objects: they are essentially black boxes (PyObject pointers). The interpreter stack and the variables only contain such black boxes. Every operation is done via calls to the object library, like PyNumber_Add(). - -In PyPy, the three parts are clearly separated and can be replaced independently. I will discuss below the reasons I think it is very useful to have, in particular, the object library be replaced. We call object space such an object library. The standard object space is the object space that works just like Python's, that is, the object space whose black boxes are real Python objects that work as expected. We will call wrapped objects the black boxes of an object space. - -Here are four examples of object spaces: - -- TrivialObjectSpace_ -- StandardObjectSpace_ -- AbstractObjectSpace_ -- TranslateObjectSpace_ - -(We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.) - -I believe that the above examples should give a hint at why we might really want object spaces that behave differently: this is called abstact interpretation in the litterature. But there are also more funny ways to use object spaces, for example: - -+ running with several object spaces at once, to clearly separate the data into domains -+ proxy object spaces, which forward all requests over a network to a "Python object server" -+ and more... there have been numerous ideas in pypy-dev. - ------------- - -.. _ObjectSpaceInterface: ObSpIntfc.html -.. _TrivialObjectSpace: TrivObSp.html -.. _StandardObjectSpace: StObSp.html -.. _AbstractObjectSpace: AbObSp.html -.. _TranslateObjectSpace: TranObSp.html From tismer at codespeak.net Sun Jun 22 12:50:45 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 12:50:45 +0200 (MEST) Subject: [pypy-svn] rev 921 - pypy/trunk/doc Message-ID: <20030622105045.756615A0B4@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 12:50:45 2003 New Revision: 921 Modified: pypy/trunk/doc/sprint-planning.txt Log: reassigned reviews Modified: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt (original) +++ pypy/trunk/doc/sprint-planning.txt Sun Jun 22 12:50:45 2003 @@ -19,7 +19,7 @@ - list object/type - check all other type implementation and document their state: - christian, tomek, holger, alex, guenter, + alex, christian boolobject done cpythonobject done @@ -28,16 +28,18 @@ sliceobject done userobject done dictobject - intobject - moduleobject done - stringobject listobject floatobject iterobject - noneobject tupleobject + tomek, holger, guenter + + moduleobject done + stringobject + noneobject + - write a small tool that checks a type's methods of CPython against PyPy (Jacob, Laura) done From gvanrossum at codespeak.net Sun Jun 22 12:56:46 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 12:56:46 +0200 (MEST) Subject: [pypy-svn] rev 922 - pypy/trunk/src/pypy/appspace Message-ID: <20030622105646.F12385A0B4@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 12:56:46 2003 New Revision: 922 Modified: pypy/trunk/src/pypy/appspace/complexobject.py Log: Implement __eq__ as well as __ne__. Modified: pypy/trunk/src/pypy/appspace/complexobject.py ============================================================================== --- pypy/trunk/src/pypy/appspace/complexobject.py (original) +++ pypy/trunk/src/pypy/appspace/complexobject.py Sun Jun 22 12:56:46 2003 @@ -246,13 +246,13 @@ return complex(self.real, -self.imag) + def __eq__(self, other): + self, other = self.__coerce__(other) + return self.real == other.real and self.imag == other.imag + def __ne__(self, other): self, other = self.__coerce__(other) - if self.real != other.real: - return 1 - if self.imag != other.imag: - return 1 - return 0 + return self.real != other.real or self.imag != other.imag # unsupported operations From gvanrossum at codespeak.net Sun Jun 22 12:57:47 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 12:57:47 +0200 (MEST) Subject: [pypy-svn] rev 923 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622105747.6EFC05A0B4@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 12:57:47 2003 New Revision: 923 Modified: pypy/trunk/src/pypy/objspace/std/restricted_int.py Log: use *=2 instead of <<=1, to avoid Python 2.3 warnings and 2.4 breakage. Modified: pypy/trunk/src/pypy/objspace/std/restricted_int.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/restricted_int.py (original) +++ pypy/trunk/src/pypy/objspace/std/restricted_int.py Sun Jun 22 12:57:47 2003 @@ -141,8 +141,8 @@ _itest = 1 _Ltest = 1L while _itest == _Ltest and type(_itest) is int: - _itest <<= 1 - _Ltest <<= 1 + _itest *= 2 + _Ltest *= 2 _bits += 1 LONG_BIT = _bits+1 From mwh at codespeak.net Sun Jun 22 12:58:22 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 12:58:22 +0200 (MEST) Subject: [pypy-svn] rev 924 - in pypy/trunk/src/pypy: interpreter objspace/std Message-ID: <20030622105822.E10B25A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 12:58:22 2003 New Revision: 924 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/objspace.py Log: support for the data/non-data descriptor distinction. Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Sun Jun 22 12:58:22 2003 @@ -214,6 +214,8 @@ ('next', 'next', 1, ['next']), # iterator interface ('call', 'call', 3, ['__call__']), ('get', 'get', 3, ['__get__']), + ('set', 'set', 2, ['__set__']), + ('delete', 'delete', 2, ['__delete__']), ('new', 'new', 3, ['__new__']), ('init', 'init', 3, ['__init__']), ] Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Sun Jun 22 12:58:22 2003 @@ -67,6 +67,9 @@ def get__ANY_ANY_ANY(space, w_descr, w_inst, w_cls): return w_descr +def is_data_descr__ANY(space, w_descr): + return 0 + def issubtype__ANY_ANY(space, w_one, w_two): # XXX -- mwh return space.newbool(0) Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Sun Jun 22 12:58:22 2003 @@ -53,11 +53,29 @@ if space.is_true(space.eq(w_attr, space.wrap('__class__'))): return w_type + # 1) look for descriptor + # 2) if data descriptor, call it + # 3) check __dict__ + # 4) if present, return that + # 5) if descriptor found in 2), call that + # 6) raise AttrbuteError + + w_descr = None + + from typeobject import W_TypeObject + if isinstance(w_type, W_TypeObject): # XXX must always be true at some point + try: + w_descr = w_type.lookup(w_attr) + except KeyError: + pass + else: + if space.is_data_descr(w_descr): + return space.get(w_descr, w_obj, w_type) # XXX 3rd arg is wrong + try: w_dict = space.getdict(w_obj) except OperationError, e: - # catch TypeError("unsupported type for getdict") - if not e.match(space, space.w_TypeError): + if not e.match(space, space.w_TypeError): # 'unsupported type for getdict' raise else: if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): @@ -65,21 +83,13 @@ try: w_value = space.getitem(w_dict, w_attr) except OperationError, e: - # catch KeyErrors if not e.match(space, space.w_KeyError): raise else: return w_value # got a value from 'obj.__dict__[attr]' - # XXX implement lookup as a multimethod? - from typeobject import W_TypeObject - if isinstance(w_type, W_TypeObject): # XXX must always be true at some point - try: - w_value = w_type.lookup(w_attr) - except KeyError: - pass - else: - return space.get(w_value, w_obj, w_type) # XXX 3rd arg is wrong + if w_descr is not None: + return space.get(w_descr, w_obj, w_type) raise OperationError(space.w_AttributeError, w_attr) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 22 12:58:22 2003 @@ -270,6 +270,7 @@ delegate = DelegateMultiMethod() # delegators unwrap = MultiMethod('unwrap', 1, []) # returns an unwrapped object is_true = MultiMethod('nonzero', 1, []) # returns an unwrapped bool + is_data_descr = MultiMethod('is_data_descr', 1, []) # returns an unwrapped bool # XXX do something about __nonzero__ ! getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute From mwh at codespeak.net Sun Jun 22 13:01:18 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 13:01:18 +0200 (MEST) Subject: [pypy-svn] rev 925 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622110118.4A3E95A22F@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 13:01:17 2003 New Revision: 925 Added: pypy/trunk/src/pypy/objspace/std/nullobject.py pypy/trunk/src/pypy/objspace/std/nulltype.py Log: oops: add nullobject.py Added: pypy/trunk/src/pypy/objspace/std/nullobject.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/nullobject.py Sun Jun 22 13:01:17 2003 @@ -0,0 +1,24 @@ +""" + Null Object implementation + + ok and tested +""" + +from pypy.objspace.std.objspace import * +from nulltype import W_NullType + +class W_NullObject(W_Object): + statictype = W_NullType +registerimplementation(W_NullObject) + +def unwrap__Null(space, w_null): + return Null + +def is_true__Null(space, w_null): + return False + +def repr__Null(space, w_null): + return space.wrap('Null') + +register_all(vars()) + Added: pypy/trunk/src/pypy/objspace/std/nulltype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/nulltype.py Sun Jun 22 13:01:17 2003 @@ -0,0 +1,7 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_NullType(W_TypeObject): + + typename = 'NullType' From anna at codespeak.net Sun Jun 22 13:02:19 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 13:02:19 +0200 (MEST) Subject: [pypy-svn] rev 926 - pypy/trunk/doc Message-ID: <20030622110219.13B785A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 13:02:18 2003 New Revision: 926 Removed: pypy/trunk/doc/ObjSpc.txt Log: removed obsolete file Deleted: pypy/trunk/doc/ObjSpc.txt ============================================================================== --- pypy/trunk/doc/ObjSpc.txt Sun Jun 22 13:02:18 2003 +++ (empty file) @@ -1,39 +0,0 @@ -===================== -PyPython ObjectSpace -===================== - -See ObjectSpaceInterface_ for a draft version of the interface specification to ObjectSpace objects. ------------------------------------------------------------------------------------------------------- - -In a Python-like language, a running interpreter has three main parts: - -+ the compiler, which represents the static optimization of the source code into an intermediate format, the bytecode; -+ the object library, implementing the various types of objects and their semantics; -+ the main loop, which suffles data around and calls the operations defined in the object library according to the bytecode. - -The main loop generally assumes little about the semantics of the objects: they are essentially black boxes (PyObject pointers). The interpreter stack and the variables only contain such black boxes. Every operation is done via calls to the object library, like PyNumber_Add(). - -In PyPy, the three parts are clearly separated and can be replaced independently. I will discuss below the reasons I think it is very useful to have, in particular, the object library be replaced. We call object space such an object library. The standard object space is the object space that works just like Python's, that is, the object space whose black boxes are real Python objects that work as expected. We will call wrapped objects the black boxes of an object space. - -Here are four examples of object spaces: - -- TrivialObjectSpace_ -- StandardObjectSpace_ -- AbstractObjectSpace_ -- TranslateObjectSpace_ - -(We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.) - -I believe that the above examples should give a hint at why we might really want object spaces that behave differently: this is called abstact interpretation in the litterature. But there are also more funny ways to use object spaces, for example: - -+ running with several object spaces at once, to clearly separate the data into domains -+ proxy object spaces, which forward all requests over a network to a "Python object server" -+ and more... there have been numerous ideas in pypy-dev. - ------------- - -.. _ObjectSpaceInterface: ObSpIntfc.html -.. _TrivialObjectSpace: TrivObSp.html -.. _StandardObjectSpace: StObSp.html -.. _AbstractObjectSpace: AbObSp.html -.. _TranslateObjectSpace: TranObSp.html From anna at codespeak.net Sun Jun 22 13:03:20 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 13:03:20 +0200 (MEST) Subject: [pypy-svn] rev 927 - pypy/trunk/doc Message-ID: <20030622110320.85C895A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 13:03:20 2003 New Revision: 927 Removed: pypy/trunk/doc/ObSpIntfc.txt Log: removed obsolete file Deleted: pypy/trunk/doc/ObSpIntfc.txt ============================================================================== --- pypy/trunk/doc/ObSpIntfc.txt Sun Jun 22 13:03:20 2003 +++ (empty file) @@ -1,111 +0,0 @@ -================================ -PyPython ObjectSpaceInterface -================================ - -Note this is only a draft version of the ObjectSpace_ interface. The reality of the interface depends on the particular implementation you are using. Consult the code for details. - -class ObjSpace -================= - -Data Members ------------------ - -+ ObjSpace.MethodTable: - List of tuples (method name, symbol, number of arguments) for the regular part of the interface. (Tuples are interpreter level.) - -+ self.w_builtins -+ self.w_modules -+ self.appfile_helpers -+ self.w_None: The ObjectSpace's None -+ self.w_True: The ObjectSpace's True -+ self.w_False: The ObjectSpace's False - -Administrative Functions ----------------------------- - -**initialize():** - Function which initializes w_builtins and the other w_constants. - -**getexecutioncontext():** - Return current active execution context. - -**gethelper(applicationfile):** - Get helper for applicationfile. - -Operations on Objects in ObjectSpace ------------------------------------------ - -These functions both take and return "wrapped" objects. - -*The following functions implement the same operations as those in CPython:* - -``id, type, issubtype, iter, repr, str, len, hash,`` - -``getattr, setattr, delattr, getitem, setitem, delitem,`` - -``pos, neg, not_, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,`` - -``lt, le, eq, ne, gt, ge, contains,`` - -``inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor`` - -**next(w):** - Call the next function for iterator w. - -**call(callable, args, kwds):** - Call a function with the given args and keywords. - -**is_(w_x, w_y):** - Implements 'w_x is w_y'. - -**exception_match(w_exc_type, w_check_class):** - Checks if the given exception type matches 'w_check_class'. Used in matching the actual exception raised with the list of those to catch in an except clause. Returns a bool. - -Creation of Application Level objects ---------------------------------------- - -**wrap(x):** - Return ObjectSpace equivalent of x. - -**newbool(b):** - Creates a Bool Object from an interpreter level object. - -**newtuple([..]):** - Take an interpreter level list of wrapped objects. - -**newlist([..]):** - Takes an interpreter level list of wrapped objects. - -**newdict([..]):** - Takes an interpreter level list of interpreter level pairs of wrapped key:wrapped value entries. - -**newslice(w_start, w_end, w_step):** - Makes a new slice object. - -**newfunction(w_code, w_globals, w_defaultarguments, w_closure=None):** - Creates a new function object. - -**newstring(asciilist):** - Creates a string from a list of integers. - -**newmodule(w_name):** - Creates a new module with a given name. - -Conversions from Application Level to Interpreter Level ----------------------------------------------------------- - -**unwrap(w_x):** - Return Interpreter Level equivalent of w_x - -**is_true(w_x):** - Return a interpreter level bool (True or False). - -**unpackiterable(w_iterable, expected_length=None):** - Unpack an iterable object into a real (interpreter level) list. Raise a real ValueError if the expected_length is wrong. - -**unpacktuple(w_tuple, expected_length=None):** - Same as unpackiterable(), but only for tuples. - ---------------------------- - -.. _ObjectSpace: ObjSpcDoc.html From tismer at codespeak.net Sun Jun 22 13:04:59 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 13:04:59 +0200 (MEST) Subject: [pypy-svn] rev 928 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622110459.E3A6B5A22F@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 13:04:59 2003 New Revision: 928 Modified: pypy/trunk/src/pypy/objspace/std/intobject.py Log: fixed bug: int_is_true (thx Jacob) Modified: pypy/trunk/src/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/intobject.py Sun Jun 22 13:04:59 2003 @@ -321,7 +321,7 @@ StdObjSpace.abs.register(int_abs, W_IntObject) def int_is_true(space, w_int1): - return w_int1.intval != 0 + return space.newbool(w_int1.intval != 0) StdObjSpace.is_true.register(int_is_true, W_IntObject) From anna at codespeak.net Sun Jun 22 13:05:15 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 13:05:15 +0200 (MEST) Subject: [pypy-svn] rev 929 - pypy/trunk/doc Message-ID: <20030622110515.B41CC5A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 13:05:15 2003 New Revision: 929 Removed: pypy/trunk/doc/MultiMeth.txt pypy/trunk/doc/mm_notes.txt Log: removed obsolete files Deleted: pypy/trunk/doc/MultiMeth.txt ============================================================================== --- pypy/trunk/doc/MultiMeth.txt Sun Jun 22 13:05:15 2003 +++ (empty file) @@ -1,143 +0,0 @@ -======================== -PyPython MultiMethod -======================== - -Notes on Multimethods ------------------------- - -Interpreter-level classes correspond to implementations of application-level -types. Several implementations can be given for the same type (e.g. several -ways to code strings or dictionaries), and conversely the same implementation -can cover several types (e.g. all instances of user-defined types currently -share the same implementation). - -The hierarchy among the classes used for the implementations is convenient -for implementation purposes. It is not related to any application-level type -hierarchy. - -Dispatch -------------------- - -Multimethods dispatch by looking in a set of registered functions. Each -registered function has a signature, which defines which object implementation -classes are accepted at the corresponding argument position. - -The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' -later). As it accepts anything, it is the only way to guarantee that the -registered function will be called with exactly the same object as was -passed originally. ATTENTION: in all other cases the argument received by -the function may have been converted in some way. It must thus not be -considered to be 'id'entical to the original argument. For example it should -not be stored in a data structure, nor be queried for type, nor be used for -another multimethod dispatch -- the only thing you should do is read and -write its internal data. - -For example, 'getattr(obj, attr)' is implemented with a ``W_StringObject`` second -argument when all it needs is just the name of the attr, and with a W_ANY -when the 'attr' object could be used as a key in ``obj.__dict__``. - - -Delegation ---------------- - -Delegation is a transparent convertion mechanism between object -implementations. The convertion can give a result of a different type -(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). -There is a global table of delegators. We should not rely on the delegators -to be tried in any particlar order, or at all (e.g. the int -> float delegator -could be ignored when we know that no registered function will accept a float -anyway). - -Delegation is also used to emulate inheritance between built-in types -(e.g. bool -> int). This is done by delegation because there is no reason -that a particular implementation of a sub-type can be trivially typecast -to some other particular implementation of the parent type; the process might -require some work. - - -Types ---------- - -Types are implemented by the class W_TypeObject. This is where inheritance -and the Method Resolution Order are defined, and where attribute look-ups -are done. - -Instances of user-defined types are implementated as W_UserObjects. -A user-defined type can inherit from built-in types (maybe more than one, -although this is incompatible with CPython). The W_UserObject delegator -converts the object into any of these "parent objects" if needed. This is -how user-defined types appear to inherit all built-in operator -implementations. - -Delegators should be able to invoke user code; this would let us -implement special methods like __int__() by calling them within a -W_UserObject -> int delegator. - -Specifics of multimethods ---------------------------- - -Multimethods dispatch more-specific-first, left-to-right (i.e. if there is -an exact match for the first argument it will always be tried first). - -Delegators are automatically chained (i.e. A -> B and B -> C would be -combined to allow for A -> C delegation). - -Delegators do not publish the class of the converted object in advance, -so that the W_UserObject delegator can potentially produce any other -built-in implementation. This means chaining and chain loop detection cannot -be done statically (at least without help from an analysis tool like the -translator-to-C). To break loops, we can assume (unless a particular need -arises) that delegators are looping when they return an object of an -already-seen class. - -Registration --------------------- - -The register() method of multimethods adds a function to its database of -functions, with the given signature. A function that raises -!FailedToImplement causes the next match to be tried. - -'delegate' is the special unary multimethod that should try to convert -its argument to something else. For greater control, it can also return -a list of 2-tuples (class, object), or an empty list for failure to convert -the argument to anything. All delegators will potentially be tried, and -recursively on each other's results to do chaining. - -A priority ordering between delegators is used. See ``objspace.PRIORITY_*``. - - -Translation ------------------------ - -The code in multimethod.py is not supposed to be read by the -translator-to-C. Special optimized code will be generated instead -(typically some kind of precomputed dispatch tables). - -Delegation is special-cased too. Most delegators will be found -to return an object of a statically known class, which means that -most of the chaining and loop detection can be done in advance. - - -Multimethod slicing ------------------------- - -Multimethods are visible to user code as (bound or unbound) methods -defined for the corresponding types. (At some point built-in functions -like len() and the operator.xxx() should really directly map to the -multimethods themselves, too.) - -To build a method from a multimethod (e.g. as in 'l.append' or -'int.__add__'), the result is actually a "slice" of the whole -multimethod, i.e. a sub-multimethod in which the registration table has -been trimmed down. (Delegation mechanisms are not restricted for sliced -multimethods.) - -Say that C is the class the new method is attached to (in the above -examples, respectively, C=type(l) and C=int). The restriction is -based on the registered class of the first argument ('self' for the -new method) in the signature. If this class corresponds to a fixed -type (as advertized by 'statictype'), and this fixed type is C or a -superclass of C, then we keep it. - -Some multimethods can also be sliced along their second argument, -e.g. for __radd__(). Deleted: pypy/trunk/doc/mm_notes.txt ============================================================================== --- pypy/trunk/doc/mm_notes.txt Sun Jun 22 13:05:15 2003 +++ (empty file) @@ -1,145 +0,0 @@ - - -Notes on Multimethods -********************* - - -Interpreter-level classes correspond to implementations of application-level -types. Several implementations can be given for the same type (e.g. several -ways to code strings or dictionaries), and conversely the same implementation -can cover several types (e.g. all instances of user-defined types currently -share the same implementation). - -The hierarchy among the classes used for the implementations is convenient -for implementation purposes. It is not related to any application-level type -hierarchy. - - -Dispatch --------- - -Multimethods dispatch by looking in a set of registered functions. Each -registered function has a signature, which defines which object implementation -classes are accepted at the corresponding argument position. - -The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' -later). As it accepts anything, it is the only way to guarantee that the -registered function will be called with exactly the same object as was -passed originally. ATTENTION: in all other cases the argument received by -the function may have been converted in some way. It must thus not be -considered to be 'id'entical to the original argument. For example it should -not be stored in a data structure, nor be queried for type, nor be used for -another multimethod dispatch -- the only thing you should do is read and -write its internal data. - -For example, 'getattr(obj, attr)' is implemented with a W_StringObject second -argument when all it needs is just the name of the attr, and with a W_ANY -when the 'attr' object could be used as a key in obj.__dict__. - - -Delegation ----------- - -Delegation is a transparent convertion mechanism between object -implementations. The convertion can give a result of a different type -(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). -There is a global table of delegators. We should not rely on the delegators -to be tried in any particlar order, or at all (e.g. the int -> float delegator -could be ignored when we know that no registered function will accept a float -anyway). - -Delegation is also used to emulate inheritance between built-in types -(e.g. bool -> int). This is done by delegation because there is no reason -that a particular implementation of a sub-type can be trivially typecast -to some other particular implementation of the parent type; the process might -require some work. - - -Types ------ - -Types are implemented by the class W_TypeObject. This is where inheritance -and the Method Resolution Order are defined, and where attribute look-ups -are done. - -Instances of user-defined types are implementated as W_UserObjects. -A user-defined type can inherit from built-in types (maybe more than one, -although this is incompatible with CPython). The W_UserObject delegator -converts the object into any of these "parent objects" if needed. This is -how user-defined types appear to inherit all built-in operator -implementations. - -Delegators should be able to invoke user code; this would let us -implement special methods like __int__() by calling them within a -W_UserObject -> int delegator. - - -Specifics of multimethods -------------------------- - -Multimethods dispatch more-specific-first, left-to-right (i.e. if there is -an exact match for the first argument it will always be tried first). - -Delegators are automatically chained (i.e. A -> B and B -> C would be -combined to allow for A -> C delegation). - -Delegators do not publish the class of the converted object in advance, -so that the W_UserObject delegator can potentially produce any other -built-in implementation. This means chaining and chain loop detection cannot -be done statically (at least without help from an analysis tool like the -translator-to-C). To break loops, we can assume (unless a particular need -arises) that delegators are looping when they return an object of an -already-seen class. - - -Registration ------------- - -The register() method of multimethods adds a function to its database of -functions, with the given signature. A function that raises -FailedToImplement causes the next match to be tried. - -'delegate' is the special unary multimethod that should try to convert -its argument to something else. For greater control, it can also return -a list of 2-tuples (class, object), or an empty list for failure to convert -the argument to anything. All delegators will potentially be tried, and -recursively on each other's results to do chaining. - -A priority ordering between delegators is used. See objspace.PRIORITY_*. - - -Translation ------------ - -The code in multimethod.py is not supposed to be read by the -translator-to-C. Special optimized code will be generated instead -(typically some kind of precomputed dispatch tables). - -Delegation is special-cased too. Most delegators will be found -to return an object of a statically known class, which means that -most of the chaining and loop detection can be done in advance. - - -Multimethod slicing -------------------- - -Multimethods are visible to user code as (bound or unbound) methods -defined for the corresponding types. (At some point built-in functions -like len() and the operator.xxx() should really directly map to the -multimethods themselves, too.) - -To build a method from a multimethod (e.g. as in 'l.append' or -'int.__add__'), the result is actually a "slice" of the whole -multimethod, i.e. a sub-multimethod in which the registration table has -been trimmed down. (Delegation mechanisms are not restricted for sliced -multimethods.) - -Say that C is the class the new method is attached to (in the above -examples, respectively, C=type(l) and C=int). The restriction is -based on the registered class of the first argument ('self' for the -new method) in the signature. If this class corresponds to a fixed -type (as advertized by 'statictype'), and this fixed type is C or a -superclass of C, then we keep it. - -Some multimethods can also be sliced along their second argument, -e.g. for __radd__(). From anna at codespeak.net Sun Jun 22 13:08:08 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 13:08:08 +0200 (MEST) Subject: [pypy-svn] rev 930 - in pypy/trunk/doc: . devel Message-ID: <20030622110808.1A7795A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 13:08:07 2003 New Revision: 930 Added: pypy/trunk/doc/devel/ pypy/trunk/doc/devel/coding-style.txt - copied unchanged from rev 918, pypy/trunk/doc/coding-style.txt pypy/trunk/doc/devel/sys-names.txt - copied unchanged from rev 918, pypy/trunk/doc/sys-names.txt pypy/trunk/doc/devel/using-testsupport.txt - copied unchanged from rev 918, pypy/trunk/doc/using-testsupport.txt Removed: pypy/trunk/doc/coding-style.txt pypy/trunk/doc/sys-names.txt pypy/trunk/doc/using-testsupport.txt Log: created devel directory and moved files into it Deleted: pypy/trunk/doc/coding-style.txt ============================================================================== --- pypy/trunk/doc/coding-style.txt Sun Jun 22 13:08:07 2003 +++ (empty file) @@ -1,100 +0,0 @@ -Directory Structure (example sketch) ------------------------------------- - -trunk/ - src/ - pypy/ - interpreter/ - pyframe.py - opcodes.py - opcodes_app.py - baseobjspace.py - - module/ # mixed interpreter/app-code - builtin.py - builtin_app.py - struct.py - struct_app.py - test/ - test_struct_app.py - test_struct.py - - objspace/ # all objectsspaces go here - std/ # __init__.py pulls in the ObjSpace class - floatobject.py - intobject.py - objspace.py - trivial.py - - appspace/ # pure app-python modules converted/modified from CPython - parser.py - compiler/ - - www/ - moincode/ -> site-packages/MoinMoin - moininstance/ -> wiki-instance - data/text/ - issue/ -> issue-tracker-instance # rename - htdocs-pypy/ -> www-root visible as /pypy/ - util/ -> used for internal deployment (not visible to outside) - doc/ # meta-documents about pypy (unordered) - -naming and environment ------------------------------ - -- the PYTHONPATH should be set to the filesytstem equivalent of - http://codespeak.net:8080/svn/pypy/trunk/src - in fact the "autopath" module does this for you. - -- __init__.py is always empty except for "pypy/objspace/*" - -- directories/modules/namespaces are always lowercase - -- classes are CamelCase - -- functions/methods are lowercase and '_'-separated (if - you need to separate at all) - -Object Spaces ---------------- - -- objectspace classes are always spelled "ObjSpace" - e.g. TrivialObjSpace - StdObjSpace - -- at interpreter level and in ObjSpace all boxed values - have a leading 'w_' to indicate "wrapped values". This - includes w_self. Don't use 'w_' in application level - python only code. - -- not more than 4 directory nesting levels - -- never use plural names in directory and file names - - -Test conventions --------------------- - -- each module has a canonical test-script (using the "unittests" - package if feasible) - - test/test_exactmodulename.py - -- each TestCase is named after the class it tests - - class TestExactClass(unittest.TestCase): - -- all other testcases are assumed to test single/more functions - or something that spans more than one class - -- every non-test file is forbidden to start with "t" - -- each test directory needs a copy of testsupport.py. see doc/using-testsupport.txt for more information. - - -Miscallenous stuff ------------------- - -- to edit wiki pages do - - svn co http://codespeak.net:8080/svn/pypy/trunk/www/moininstance/data/text wiki-pages Deleted: pypy/trunk/doc/sys-names.txt ============================================================================== --- pypy/trunk/doc/sys-names.txt Sun Jun 22 13:08:07 2003 +++ (empty file) @@ -1,66 +0,0 @@ -# this is just a list of names from the sys module as of 2.2.3c1 -# we expect to annotate the file with comments about ease of -# implementation & implemented-ness of each thing - -annotations: difficulty/strategy/urgency - -e == easy -h == hard - -o == essentially implemented by the objectspace -p == just write it in python -v == variable -t == type -m == messy - -u == urgent -i == important -n == normal -d == really don't care -r == resolved, done -U == unsupported - -ev __displayhook__ -ev __doc__ -ev __excepthook__ -ev __name__ -ev __stderr__ -ev __stdin__ -ev __stdout__ -emn _getframe -evn argv -evd builtin_module_names -evn byteorder -evn copyright - pi displayhook - mi exc_info -evn exc_traceback -evn exc_type -evn exc_value - pi excepthook -evn exec_prefix -evn executable -epn exit -- maybe SystemExit should be different... - n exitfunc -epn getdefaultencoding -hmd getdlopenflags -- just don't mention it -epd getrecursionlimit - U getrefcount -ev hexversion -evn maxint -evn maxunicode -evi modules -evi path -evn platform -evn prefix -hmd setcheckinterval -hmU setdlopenflags -hmd setprofile - d setrecursionlimit -hmd settrace -evi stderr -evi stdin -evi stdout -evi version -evi version_info -evn warnoptions Deleted: pypy/trunk/doc/using-testsupport.txt ============================================================================== --- pypy/trunk/doc/using-testsupport.txt Sun Jun 22 13:08:07 2003 +++ (empty file) @@ -1,20 +0,0 @@ -Tile testsupport.py should be copied into every test subdirectory. -The main copy lives in pypy/testsupport.py . - -import testsupport - -fixes the path so that all 'import pypy.something' should work. - -Module testsupport also exposes the following: - main a function just like unittest.main - TestCase a class just like unittest.TestCase but with extra methods - objspace the object space class to be used in this test - -testsupport.objspace is normally the trivial object space, but you -can set it (via an environment variable set before running Python) -to be the standard object space instead. Specifically: - - set OBJSPACE=pypy.objspace.std.objspace.StdObjSpace - -(or equivalent syntax depending on your shell) does the job. - From anna at codespeak.net Sun Jun 22 13:13:03 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 13:13:03 +0200 (MEST) Subject: [pypy-svn] rev 931 - pypy/trunk/doc/devel Message-ID: <20030622111303.A1CA85A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 13:13:03 2003 New Revision: 931 Added: pypy/trunk/doc/devel/builtins.txt - copied unchanged from rev 918, pypy/trunk/doc/builtins.txt Removed: pypy/trunk/doc/devel/sys-names.txt Log: replaced obsolete files Deleted: pypy/trunk/doc/devel/sys-names.txt ============================================================================== --- pypy/trunk/doc/devel/sys-names.txt Sun Jun 22 13:13:03 2003 +++ (empty file) @@ -1,66 +0,0 @@ -# this is just a list of names from the sys module as of 2.2.3c1 -# we expect to annotate the file with comments about ease of -# implementation & implemented-ness of each thing - -annotations: difficulty/strategy/urgency - -e == easy -h == hard - -o == essentially implemented by the objectspace -p == just write it in python -v == variable -t == type -m == messy - -u == urgent -i == important -n == normal -d == really don't care -r == resolved, done -U == unsupported - -ev __displayhook__ -ev __doc__ -ev __excepthook__ -ev __name__ -ev __stderr__ -ev __stdin__ -ev __stdout__ -emn _getframe -evn argv -evd builtin_module_names -evn byteorder -evn copyright - pi displayhook - mi exc_info -evn exc_traceback -evn exc_type -evn exc_value - pi excepthook -evn exec_prefix -evn executable -epn exit -- maybe SystemExit should be different... - n exitfunc -epn getdefaultencoding -hmd getdlopenflags -- just don't mention it -epd getrecursionlimit - U getrefcount -ev hexversion -evn maxint -evn maxunicode -evi modules -evi path -evn platform -evn prefix -hmd setcheckinterval -hmU setdlopenflags -hmd setprofile - d setrecursionlimit -hmd settrace -evi stderr -evi stdin -evi stdout -evi version -evi version_info -evn warnoptions From mwh at codespeak.net Sun Jun 22 14:22:50 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 14:22:50 +0200 (MEST) Subject: [pypy-svn] rev 932 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030622122250.984465A22F@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 14:22:50 2003 New Revision: 932 Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Log: Add test for user-defined descriptors. Couldn't write the test the way we wanted, which is our next problem... Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Sun Jun 22 14:22:50 2003 @@ -39,7 +39,14 @@ self.failUnless(isinstance(inst, base)) self.assertEquals(inst.baseattr,12) self.assertEquals(inst.derivedattr,34) - + + def test_descr_get(self): + class C: + class desc: + def __get__(self, ob, cls=None): + return 42 + prop = desc() + self.assertEquals(C().prop, 42) if __name__ == '__main__': test.main() From mwh at codespeak.net Sun Jun 22 14:23:58 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 14:23:58 +0200 (MEST) Subject: [pypy-svn] rev 933 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622122358.4F9EF5A22F@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 14:23:57 2003 New Revision: 933 Modified: pypy/trunk/src/pypy/objspace/std/nullobject.py (props changed) pypy/trunk/src/pypy/objspace/std/nulltype.py (props changed) pypy/trunk/src/pypy/objspace/std/test/test_userobject.py (props changed) Log: fixeol From hpk at codespeak.net Sun Jun 22 14:25:21 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 14:25:21 +0200 (MEST) Subject: [pypy-svn] rev 934 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622122521.A0CBB5A22F@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 14:25:21 2003 New Revision: 934 Modified: pypy/trunk/src/pypy/objspace/std/usertype.py Log: - new style registration - fixed some leaked utf8-code in a comment (coming from windows?) Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Sun Jun 22 14:25:21 2003 @@ -6,7 +6,6 @@ import typeobject, objecttype from typeobject import W_TypeObject - class W_UserType(W_TypeObject): """Instances of this class are user-defined Python type objects. All user-defined types are instances of the present class. @@ -43,17 +42,16 @@ raise KeyError return w_value - # XXX we'll worry about the __new__/__init__ distinction later # XXX NOTE: currently (03-06-21) user-object can only sublass -# types which register an implementation for ?new? -- currently +# types which register an implementation for 'new' -- currently # this means that e.g. subclassing list or str works, subclassing # int or float does not -- this is not a bug fixable in userobject # (perhaps in the object-space, perhaps in each builtin type...?) # but we're documenting it here as there seems no better place!!! # The problem is actually that, currently, several types such as # int and float just cannot be CALLED -- this needs to be fixed soon. -def usertype_new(space, w_usertype, w_args, w_kwds): +def new__UserType_ANY_ANY(space, w_usertype, w_args, w_kwds): from userobject import W_UserObject newobj = W_UserObject(space, w_usertype, w_args, w_kwds) try: @@ -64,6 +62,8 @@ else: space.call(init, w_args, w_kwds) return newobj - -StdObjSpace.new.register(usertype_new, W_UserType, W_ANY, W_ANY) +def repr__UserType(space, w_usertype): + return space.wrap("" % w_usertype.typename) + +register_all(vars()) From anna at codespeak.net Sun Jun 22 14:26:59 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 14:26:59 +0200 (MEST) Subject: [pypy-svn] rev 935 - pypy/trunk/doc/objspace Message-ID: <20030622122659.8A7945A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 14:26:59 2003 New Revision: 935 Added: pypy/trunk/doc/objspace/abstractobjspace.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/AbObSp.txt pypy/trunk/doc/objspace/annotateobjspace.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/AnnotateObSp.txt pypy/trunk/doc/objspace/multimethod.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/MultiMeth.txt pypy/trunk/doc/objspace/objspace.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/ObjSpace.txt pypy/trunk/doc/objspace/objspaceinterface.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/ObSpIntfc.txt pypy/trunk/doc/objspace/restrictedpy.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/RestrictedPython.txt pypy/trunk/doc/objspace/stdobjspace.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/StObSp.txt pypy/trunk/doc/objspace/trivialobjspace.txt - copied unchanged from rev 924, pypy/trunk/doc/objspace/TrivObSp.txt Removed: pypy/trunk/doc/objspace/AbObSp.txt pypy/trunk/doc/objspace/AnnotateObSp.txt pypy/trunk/doc/objspace/MultiMeth.txt pypy/trunk/doc/objspace/ObSpIntfc.txt pypy/trunk/doc/objspace/ObjSpace.txt pypy/trunk/doc/objspace/RestrictedPython.txt pypy/trunk/doc/objspace/StObSp.txt pypy/trunk/doc/objspace/TrivObSp.txt Log: renamed files to lowercase and clearer filenames Deleted: pypy/trunk/doc/objspace/AbObSp.txt ============================================================================== --- pypy/trunk/doc/objspace/AbObSp.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,16 +0,0 @@ -======================= -AbstractObjectSpace -======================= - -User History ------------------------- - -This is an example of abstract interpretation, i.e. following the bytecode instructions of a program like an interpreter does but with abstract objects instead of concrete ones. Remember that in PyPy this is done by using alternate object spaces with the same interpreter main loop. - -The most abstract object space is the one manipulating the most abstract objects that you could imagine: they are all equivalent, because we have abstracted away any information about the object. There is actually only one of them left, and we can call it "the object". In Python terms, our AbstractObjectSpace uses None for all its wrapped objects. Any operation between wrapped objects gives None again as the wrapped result -- there is nothing else it could give anyway. So when you have said that the add method of AbstractObjectSpace takes None and None and returns None you have said everything. - -The point of such an object space is for example to check the bytecode. The interpreter will really run your bytecode, just with completely abstract arguments. If there is no problem then you are sure that the bytecode is valid. You could also record, during this abstract interpretation, how much the stack ever grows; that would give you a fool-proof method of computing the co_stacksize argument of a code object which might be useful for the PyPy compiler. (There are subtleties which I won't describe here, but that's the basic idea.) - -Typically, however, abstract object spaces are a (little) bit less abstract, still maintaining a minimal amount of information about the objects. For example, a wrapped object could be represented by its type. You then define the object space's add to return int when the two arguments are int and int. That way, you abstractedly call a function with the input argument's types and what the interpreter will do is a type inference. (Here also there are subtle problems, even besides the remark that integer operations can overflow and actually return longs in a real Python implementation.) - -As an example of more abstract object spaces you have the ones with finite domain, i.e. with a finite number of different possible wrapped objects. For example, you can use True and False as wrapped values to denote the fact that the object is, respectively, a non-negative integer or anything else. In this way you are doing another kind of type inference that just tells you which variables will only ever contain non-negative integers. Deleted: pypy/trunk/doc/objspace/AnnotateObSp.txt ============================================================================== --- pypy/trunk/doc/objspace/AnnotateObSp.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,29 +0,0 @@ -========================= -Annotated Object Space -========================= - -was TranslateObjectSpace -------------------------- -This has been renamed and is currently being re-written. Old information follows: - -User History ------------------- - -This is an example of an ObjectSpace that differs a lot from StandardObjectSpace_. - -At some point in the near future we will have to design a translator from all the RestrictedPython_ code we have into C code. This is the sine qua non condition for our work to be actually usable. Quite unexpectedly, the major piece of the translator is itself an object space, the TranslateObjectSpace. Its goal is to run any RestrictedPython code and produce C code in the background as it does so. - -More specifically, we take our PyPy interpreter with the TranslateObjectSpace instead of the StandardObjectSpace, and run that, asking it to interpret some RestrictedPython bytecode. The idea is that a wrapped object is now the name of a variable in the C program we are emitting: - -The TranslateObjectSpace's add method takes two such variable names x and y, and emits the C code z=x+y;, where z is a new variable name which is returned as the result of add. So when the interpreter goes along the bytecode, the TranslateObjectSpace will create variable names and emit C code that does just the same thing as the bytecode. - -The above description is what would occur if RestrictedPython only had integer data types. We must actually make the wrapped objects a bit more elaborate to also record, besides the C variable name, its basic type. This can be easy, like prefixing the variable name with a type character; for example, add would behave as above if the variable names begin with ``i_`` but differently if they begin with the prefix denoting floats or lists, say. - -Once you grasp the idea that this process can actually easily translate any RestrictedPython to C, and if you remember that the interpreter main loop itself is written in RestrictedPython, then you shouldn't be surprised if I say that all we have to do next is run the interpreter to interpret itself (and thus translate itself to C)! - -This is again a rough sketch, but it shows why I expect translating RestrictedPython to C to be easy. The RestrictedPython is precisely restricted in such a way that makes the above process work, e.g. we only ever use well-known types and operations that are easy to convert to an efficient C equivalent. (For example, if lists are translated to C arrays, I'm sure Christian would insist on not using '+' between lists in RestrictedPython but rather '+=', which has a more direct translation as realloc() -- although by now he might be convinced that supporting '+' as a bonus isn't going to be any difficult anyway :-) ) - ------------------------------- - -.. _StandardObjectSpace: StObSp.html -.. _RestrictedPython: RestrictedPython.html Deleted: pypy/trunk/doc/objspace/MultiMeth.txt ============================================================================== --- pypy/trunk/doc/objspace/MultiMeth.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,143 +0,0 @@ -======================== -PyPython MultiMethod -======================== - -Notes on Multimethods ------------------------- - -Interpreter-level classes correspond to implementations of application-level -types. Several implementations can be given for the same type (e.g. several -ways to code strings or dictionaries), and conversely the same implementation -can cover several types (e.g. all instances of user-defined types currently -share the same implementation). - -The hierarchy among the classes used for the implementations is convenient -for implementation purposes. It is not related to any application-level type -hierarchy. - -Dispatch -------------------- - -Multimethods dispatch by looking in a set of registered functions. Each -registered function has a signature, which defines which object implementation -classes are accepted at the corresponding argument position. - -The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object' -later). As it accepts anything, it is the only way to guarantee that the -registered function will be called with exactly the same object as was -passed originally. ATTENTION: in all other cases the argument received by -the function may have been converted in some way. It must thus not be -considered to be 'id'entical to the original argument. For example it should -not be stored in a data structure, nor be queried for type, nor be used for -another multimethod dispatch -- the only thing you should do is read and -write its internal data. - -For example, 'getattr(obj, attr)' is implemented with a ``W_StringObject`` second -argument when all it needs is just the name of the attr, and with a W_ANY -when the 'attr' object could be used as a key in ``obj.__dict__``. - - -Delegation ---------------- - -Delegation is a transparent convertion mechanism between object -implementations. The convertion can give a result of a different type -(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str). -There is a global table of delegators. We should not rely on the delegators -to be tried in any particlar order, or at all (e.g. the int -> float delegator -could be ignored when we know that no registered function will accept a float -anyway). - -Delegation is also used to emulate inheritance between built-in types -(e.g. bool -> int). This is done by delegation because there is no reason -that a particular implementation of a sub-type can be trivially typecast -to some other particular implementation of the parent type; the process might -require some work. - - -Types ---------- - -Types are implemented by the class W_TypeObject. This is where inheritance -and the Method Resolution Order are defined, and where attribute look-ups -are done. - -Instances of user-defined types are implementated as W_UserObjects. -A user-defined type can inherit from built-in types (maybe more than one, -although this is incompatible with CPython). The W_UserObject delegator -converts the object into any of these "parent objects" if needed. This is -how user-defined types appear to inherit all built-in operator -implementations. - -Delegators should be able to invoke user code; this would let us -implement special methods like __int__() by calling them within a -W_UserObject -> int delegator. - -Specifics of multimethods ---------------------------- - -Multimethods dispatch more-specific-first, left-to-right (i.e. if there is -an exact match for the first argument it will always be tried first). - -Delegators are automatically chained (i.e. A -> B and B -> C would be -combined to allow for A -> C delegation). - -Delegators do not publish the class of the converted object in advance, -so that the W_UserObject delegator can potentially produce any other -built-in implementation. This means chaining and chain loop detection cannot -be done statically (at least without help from an analysis tool like the -translator-to-C). To break loops, we can assume (unless a particular need -arises) that delegators are looping when they return an object of an -already-seen class. - -Registration --------------------- - -The register() method of multimethods adds a function to its database of -functions, with the given signature. A function that raises -!FailedToImplement causes the next match to be tried. - -'delegate' is the special unary multimethod that should try to convert -its argument to something else. For greater control, it can also return -a list of 2-tuples (class, object), or an empty list for failure to convert -the argument to anything. All delegators will potentially be tried, and -recursively on each other's results to do chaining. - -A priority ordering between delegators is used. See ``objspace.PRIORITY_*``. - - -Translation ------------------------ - -The code in multimethod.py is not supposed to be read by the -translator-to-C. Special optimized code will be generated instead -(typically some kind of precomputed dispatch tables). - -Delegation is special-cased too. Most delegators will be found -to return an object of a statically known class, which means that -most of the chaining and loop detection can be done in advance. - - -Multimethod slicing ------------------------- - -Multimethods are visible to user code as (bound or unbound) methods -defined for the corresponding types. (At some point built-in functions -like len() and the operator.xxx() should really directly map to the -multimethods themselves, too.) - -To build a method from a multimethod (e.g. as in 'l.append' or -'int.__add__'), the result is actually a "slice" of the whole -multimethod, i.e. a sub-multimethod in which the registration table has -been trimmed down. (Delegation mechanisms are not restricted for sliced -multimethods.) - -Say that C is the class the new method is attached to (in the above -examples, respectively, C=type(l) and C=int). The restriction is -based on the registered class of the first argument ('self' for the -new method) in the signature. If this class corresponds to a fixed -type (as advertized by 'statictype'), and this fixed type is C or a -superclass of C, then we keep it. - -Some multimethods can also be sliced along their second argument, -e.g. for __radd__(). Deleted: pypy/trunk/doc/objspace/ObSpIntfc.txt ============================================================================== --- pypy/trunk/doc/objspace/ObSpIntfc.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,111 +0,0 @@ -================================ -PyPython ObjectSpaceInterface -================================ - -Note this is only a draft version of the ObjectSpace_ interface. The reality of the interface depends on the particular implementation you are using. Consult the code for details. - -class ObjSpace -================= - -Data Members ------------------ - -+ ObjSpace.MethodTable: - List of tuples (method name, symbol, number of arguments) for the regular part of the interface. (Tuples are interpreter level.) - -+ self.w_builtins -+ self.w_modules -+ self.appfile_helpers -+ self.w_None: The ObjectSpace's None -+ self.w_True: The ObjectSpace's True -+ self.w_False: The ObjectSpace's False - -Administrative Functions ----------------------------- - -**initialize():** - Function which initializes w_builtins and the other w_constants. - -**getexecutioncontext():** - Return current active execution context. - -**gethelper(applicationfile):** - Get helper for applicationfile. - -Operations on Objects in ObjectSpace ------------------------------------------ - -These functions both take and return "wrapped" objects. - -*The following functions implement the same operations as those in CPython:* - -``id, type, issubtype, iter, repr, str, len, hash,`` - -``getattr, setattr, delattr, getitem, setitem, delitem,`` - -``pos, neg, not_, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,`` - -``lt, le, eq, ne, gt, ge, contains,`` - -``inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor`` - -**next(w):** - Call the next function for iterator w. - -**call(callable, args, kwds):** - Call a function with the given args and keywords. - -**is_(w_x, w_y):** - Implements 'w_x is w_y'. - -**exception_match(w_exc_type, w_check_class):** - Checks if the given exception type matches 'w_check_class'. Used in matching the actual exception raised with the list of those to catch in an except clause. Returns a bool. - -Creation of Application Level objects ---------------------------------------- - -**wrap(x):** - Return ObjectSpace equivalent of x. - -**newbool(b):** - Creates a Bool Object from an interpreter level object. - -**newtuple([..]):** - Take an interpreter level list of wrapped objects. - -**newlist([..]):** - Takes an interpreter level list of wrapped objects. - -**newdict([..]):** - Takes an interpreter level list of interpreter level pairs of wrapped key:wrapped value entries. - -**newslice(w_start, w_end, w_step):** - Makes a new slice object. - -**newfunction(w_code, w_globals, w_defaultarguments, w_closure=None):** - Creates a new function object. - -**newstring(asciilist):** - Creates a string from a list of integers. - -**newmodule(w_name):** - Creates a new module with a given name. - -Conversions from Application Level to Interpreter Level ----------------------------------------------------------- - -**unwrap(w_x):** - Return Interpreter Level equivalent of w_x - -**is_true(w_x):** - Return a interpreter level bool (True or False). - -**unpackiterable(w_iterable, expected_length=None):** - Unpack an iterable object into a real (interpreter level) list. Raise a real ValueError if the expected_length is wrong. - -**unpacktuple(w_tuple, expected_length=None):** - Same as unpackiterable(), but only for tuples. - ---------------------------- - -.. _ObjectSpace: ObjSpcDoc.html Deleted: pypy/trunk/doc/objspace/ObjSpace.txt ============================================================================== --- pypy/trunk/doc/objspace/ObjSpace.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,39 +0,0 @@ -===================== -PyPython ObjectSpace -===================== - -See ObjectSpaceInterface_ for a draft version of the interface specification to ObjectSpace objects. ------------------------------------------------------------------------------------------------------- - -In a Python-like language, a running interpreter has three main parts: - -+ the compiler, which represents the static optimization of the source code into an intermediate format, the bytecode; -+ the object library, implementing the various types of objects and their semantics; -+ the main loop, which suffles data around and calls the operations defined in the object library according to the bytecode. - -The main loop generally assumes little about the semantics of the objects: they are essentially black boxes (PyObject pointers). The interpreter stack and the variables only contain such black boxes. Every operation is done via calls to the object library, like PyNumber_Add(). - -In PyPy, the three parts are clearly separated and can be replaced independently. I will discuss below the reasons I think it is very useful to have, in particular, the object library be replaced. We call object space such an object library. The standard object space is the object space that works just like Python's, that is, the object space whose black boxes are real Python objects that work as expected. We will call wrapped objects the black boxes of an object space. - -Here are four examples of object spaces: - -- TrivialObjectSpace_ -- StandardObjectSpace_ -- AbstractObjectSpace_ -- TranslateObjectSpace_ - -(We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.) - -I believe that the above examples should give a hint at why we might really want object spaces that behave differently: this is called abstact interpretation in the litterature. But there are also more funny ways to use object spaces, for example: - -+ running with several object spaces at once, to clearly separate the data into domains -+ proxy object spaces, which forward all requests over a network to a "Python object server" -+ and more... there have been numerous ideas in pypy-dev. - ------------- - -.. _ObjectSpaceInterface: ObSpIntfc.html -.. _TrivialObjectSpace: TrivObSp.html -.. _StandardObjectSpace: StObSp.html -.. _AbstractObjectSpace: AbObSp.html -.. _TranslateObjectSpace: TranObSp.html Deleted: pypy/trunk/doc/objspace/RestrictedPython.txt ============================================================================== --- pypy/trunk/doc/objspace/RestrictedPython.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,147 +0,0 @@ -================== -Restricted Python -================== - -We are writing a Python interpreter in Python, using Python's well known ability to step behind the algorithmic problems as language. At first glance, one might think this achives nothing but a better understanding for everbody how the interpreter works. This alone would make it worth doing, but we have much larger goals. - - -CPython vs. PyPy -------------------- - -Compared to the CPython implementation, Python takes the role of the C Code. So actually, we descibe something by Python, which has been coded in C already, with all the restrictions that are implied by C. We are not trying to make the structures of the CPython interpreter more flexible by rewriting things in C, but we want to use Python to give an alternative description of the interpreter. - -The clear advantage is that this description is probably shorter and simpler to read, and many implementation details vanish. The drawback of this approach is that this interpreter will be unbearably slow. - -To get to a useful interpreter again, we need to apply some mappings to the implementation, later. One rather straight-forward is to do a whole program analysis of the PyPy interpreter and create a C source, again. There are many other ways, but let's stick with the easiest approach, first. - -In order to make a C code generator simple, we resrict ourselves to a subset of the Python language, and we adhere to some rules, which make code generation obvious and easy. - - -Restricted Python is Runtime Python -------------------------------------- - -Restricted Python describes a runnable Python interpreter implementation. This is a quite static object that can be suitably described by RPython. But the restrictions do not apply during the startup phase. - - -PyPy Bootstrap -------------------- - -When the PyPy interpreter is started as a CPython program, it can use all of CPython for a while, until it reaches runtime. That is, all executable code will be executed using the full power of Python. - -An example can be found in the implementation, which is quite elegant: For the definition of all the opcodes of the Python interpreter, the module dis is imported and used. This saves us from adding extra modules to PyPy. The import code is run at startup time, and we are allowed to use the CPython builtin import function. - -When the startup code is done, all resulting objects, functions, code blocks etc. must adhere to the runtime restrictions. All initialized modules are written out in a persistent manner. Our current idea is to emit a huge C source file which contains everything created so far. During this process, a whole program analysis is performed, which makes use of the restrictions defined in RPython. This enables the code generator to emit efficient replacements for pure integer objects, for instance. - - -RPython Definition --------------------- - -It might make sense to define a sublanguage of Python called RPython, with the restrictions depicted below. This is an evolving topic, and we're just collecting things which come up during trying to code the interpreter, so this is no language at all, but an arbitrary set of rules, which are about to be changed all day. - - -Object restrictions -------------------------- - -We are using - -**variables** - the same variable in the same context can receive values of different types, at a possible overhead cost. For example, a variable that can contain a wrapped object or None is efficiently implemented as a PyObject* pointer that can be NULL, but a variable that can contain either an integer or a float must be implemented as a union with a type tag in C. - -**constants** - all module globals are considered constants. - -**integer, float, string, boolean** - avoid string methods and complex operations like slicing with a step - -**tuples** - no variable-length tuples; use them to store or return pairs or n-tuples of values - -**lists** - lists are used as an allocated array; list.append() does naive resizing, so as far as possible use list comprehensions (see below) - -**dicts** - no dicts - -**control structures** - all allowed - -**list comprehensions** - may be used to create allocated, initialized array. the array size must be computable in advance, which implies that we don't allow an if clause. - -**functions** -+ statically called functions may use defaults and a variable number of arguments (which may be passed as a list instead of a tuple, so write code that does not depend on it being a tuple). - -+ dynamic dispatch enforces use of very simple signatures, equal for all functions to be called in that context. At the moment, this occours in the opcode dispatch, only. - -**builtin functions** - A few builtin functions will be used, while this set is not defined completely, yet. Some builtin functions are special forms: - -**range** - does not create an array. It is only allowed in for loops. The step argument must be a constant. - -**len** -+ may be used with basic types that have a length. But len is a special form that is recognized by the compiler. -+ If a certain structure is never touched by len, the compiler might save the length field from the underlying structure. - -``int, float, ord, chr``... are available as simple convertion functions. -``int, float, str``... have a special meaning as a type inside of isinstance only. - -**classes** -+ methods do not change after startup -+ methods are never hidden by attributes -+ inheritance is supported -+ classes are first-class objects too - -**exceptions** -+ fully supported -+ see below for restrictions on exceptions raised by built-in operations - -**objects** - wrapped objects are borrowed from the object space. Just like in CPython, code that needs e.g. a dictionary can use a wrapped dict and the object space operations on it. - -This layout makes the number of types to take care about quite limited. - - -Example: Integer Types -------------------------- - -While implementing the integer type, I (Chris) stumbled over the problem, that integers are quite in flux in CPython right now. Depending on the version, integers either raise an overflow exception or mutate into longs on overflow. Also, shifting right now truncates (upto 2.3) but is going to extend to longs as well. In order to enable us to run the restricted Python stuff in CPython, I needed to use a derived class r_int(int), which always behaves the same: Never leaving its domain, but always staying an integer. - -The r_int type is implemented in a pervasive way: Every operation that involves an r_int creates an r_int as the result. Therefore, the implementation is not cluttered with special type casts. Just the initial value of an emulated integer's intval field is initialized by obj.intval = r_int(val) . This way, the r_int type propagates itself through all operations without extra effort of the programmer. - -This concept looks promising, and since we will need unsigned integers which do not overflow as well, I also created r_uint. It is always a word-sized unsigned integer and never overflows. This will be a building block for things like computing hash values, where wrap-around effects are intended and should be easily coded without lots of explicit mask shuffling. - -Now I think to extend this even more and build a full set of primitive types, which are intended to - -+ define the semantics of the primitive type -+ give a working implementation for unrestricted Python - -These primitive types can later easily be augmented with methods to emit C code instead of executing. I guess this would be implemented in an extra ObjectSpace. - - -Exception rules ---------------------- - -Exceptions are by default not generated for simple cases.:: - - - #!/usr/bin/python - - x = 5 - x = x + 1 # this code is not checked for overflow - - try: - x = x + y - except OverflowError: - # implement using longs - - -Code with no exception handlers does not raise exceptions. By supplying an exception handler, you ask for error checking. Without, you assure the system that the operation cannot overflow. - -Exceptions explicitly raised will always be generated. - - -Testing ------------- - -Besides extra tests which have to be written, PyPy has the advantage that it is runnable on standard CPython. That means, we can run all of PyPy with all exception handling enabled, so we might catch cases where we failed to adhere to our implicit assertions. Deleted: pypy/trunk/doc/objspace/StObSp.txt ============================================================================== --- pypy/trunk/doc/objspace/StObSp.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,26 +0,0 @@ -========================= -StandardObjectSpace -========================= - -User History ---------------- - -The StandardObjectSpace is the direct equivalent of CPython's object library (the "Objects/" subdirectory in the distribution). It is an implementation of the common Python types in a lower-level language. - -The StandardObjectSpace defines an abstract parent class, W_Object, and a bunch of subclasses like W_IntObject, W_ListObject, and so on. A wrapped object (a "black box" for the interpreter main loop) is thus an instance of one of these classes. When the main loop invokes an operation, say the addition, between two wrapped objects w1 and w2, the StandardObjectSpace does some internal dispatching (similar to "Object/ abstract.c" in CPython) and invokes a method of the proper W_XyzObject class that can do the operation. The operation itself is done with the primitives allowed by RestrictedPython. The result is constructed as a wrapped object again. For example, compare the following implementation of integer addition with the function "int_add()" in "Object/intobject.c": :: - - def int_int_add(space, w_int1, w_int2): - x = w_int1.intval - y = w_int2.intval - try: - z = x + y - except OverflowError: - raise FailedToImplement(space.w_OverflowError, - space.wrap("integer addition")) - return W_IntObject(z) - -Why such a burden just for integer objects? Why did we have to wrap them into W_IntObject instances? For them it seems it would have been sufficient just to use plain Python integers. But this argumentation fails just like it fails for more complex kind of objects. Wrapping them just like everything else is the cleanest solution. You could introduce case testing wherever you use a wrapped object, to know if it is a plain integer or an instance of (a subclass of) W_Object. But that makes the whole program more complicated. The equivalent in CPython would be to use PyObject* pointers all around except when the object is an integer (after all, integers are directly available in C too). You could represent small integers as odd-valuated pointers. But it puts extra burden on the whole C code, so the CPython team avoided it. - -In our case it is a later optimization that we could make. We just don't want to make it now (and certainly not hard-coded at this level -- it could be introduced by the C translators that we will eventually write). So in summary: wrapping integers as instances is the simple path, while using plain integers instead is the complex path, not the other way around. - -Note that the current StandardObjectSpace implementation uses MultiMethod dispatch instead of the complex rules of "Object/abstract.c". I think that this can be translated to a different low-level dispatch implementation that would be binary compatible with CPython's (basically the PyTypeObject structure and its function pointers). If compatibility is not required it will be more straightforwardly converted into some efficient multimethod code. Deleted: pypy/trunk/doc/objspace/TrivObSp.txt ============================================================================== --- pypy/trunk/doc/objspace/TrivObSp.txt Sun Jun 22 14:26:59 2003 +++ (empty file) @@ -1,20 +0,0 @@ -================================= -PyPython TrivialObjectSpace -================================= - -User History ----------------- - -The easiest way to implement an ObjectSpace is to represent a Python object with itself. - -A PyPy interpreter using the TrivialObjectSpace is an interpreter with its own main loop (written in Python), but this main loop manipulates real Python objects and all operations are done directly on the Python objects. For example, "1" really means "1" and when the interpreter encounters the BINARY_ADD bytecode instructions the TrivialObjectSpace will just add two real Python objects together using Python's "+". The same for lists, dictionaries, classes... We just use Python's own. - -Of course you cannot do this if the goal is to write PyPy in such a way that it doesn't rely on a real underlying Python implementation like CPython. Still, it works, and it has its own uses, like testing our interpreter, or even interpreting a different kind of bytecode -- for example, it could probably be used to emulate generators in any Python version. (That would be quite slow, however.) - -(This is already done; it is funny to watch "dis.dis" disassembling itself painfully slowly :-) ) - -See StandardObjectSpace_ for the rest of the story. - -------------------------------------------------------------------- - -.. _StandardObjectSpace: StObSp.html \ No newline at end of file From anna at codespeak.net Sun Jun 22 14:30:52 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 14:30:52 +0200 (MEST) Subject: [pypy-svn] rev 936 - pypy/trunk/doc/objspace Message-ID: <20030622123052.D9A3B5A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 14:30:52 2003 New Revision: 936 Modified: pypy/trunk/doc/objspace/objspace.txt Log: updated filenames in links Modified: pypy/trunk/doc/objspace/objspace.txt ============================================================================== --- pypy/trunk/doc/objspace/objspace.txt (original) +++ pypy/trunk/doc/objspace/objspace.txt Sun Jun 22 14:30:52 2003 @@ -20,7 +20,7 @@ - TrivialObjectSpace_ - StandardObjectSpace_ - AbstractObjectSpace_ -- TranslateObjectSpace_ +- AnnotateObjectSpace_ (We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.) @@ -32,8 +32,8 @@ ------------ -.. _ObjectSpaceInterface: ObSpIntfc.html -.. _TrivialObjectSpace: TrivObSp.html -.. _StandardObjectSpace: StObSp.html -.. _AbstractObjectSpace: AbObSp.html -.. _TranslateObjectSpace: TranObSp.html +.. _ObjectSpaceInterface: objspaceinterface.html +.. _TrivialObjectSpace: trivialobjspace.html +.. _StandardObjectSpace: stdobjspace.html +.. _AbstractObjectSpace: abstractobjspace.html +.. _AnnotateObjectSpace: annotateobjspace.html From tismer at codespeak.net Sun Jun 22 14:33:59 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 14:33:59 +0200 (MEST) Subject: [pypy-svn] rev 937 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622123359.31F0D5A22F@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 14:33:58 2003 New Revision: 937 Modified: pypy/trunk/src/pypy/objspace/std/intobject.py Log: undid wrongheaded fix (wasn't a bug) Modified: pypy/trunk/src/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/intobject.py Sun Jun 22 14:33:58 2003 @@ -321,7 +321,8 @@ StdObjSpace.abs.register(int_abs, W_IntObject) def int_is_true(space, w_int1): - return space.newbool(w_int1.intval != 0) + ''' note: this must return an UNWRAPPED bool!!! ''' + return w_int1.intval != 0 StdObjSpace.is_true.register(int_is_true, W_IntObject) From gvanrossum at codespeak.net Sun Jun 22 14:34:48 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 14:34:48 +0200 (MEST) Subject: [pypy-svn] rev 938 - pypy/trunk/src/pypy/interpreter Message-ID: <20030622123448.C4B4A5A22F@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 14:34:48 2003 New Revision: 938 Modified: pypy/trunk/src/pypy/interpreter/pyframe.py Log: Minor refactoring. load_builtins() returns w_builtins rather than setting it. Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Sun Jun 22 14:34:48 2003 @@ -24,20 +24,21 @@ self.bytecode = bytecode self.w_globals = w_globals self.w_locals = w_locals - self.load_builtins() + self.w_builtins = self.load_builtins() self.valuestack = Stack() self.blockstack = Stack() self.last_exception = None self.next_instr = 0 def clone(self): - f = PyFrame(self.space, self.bytecode, self.w_globals, self.w_locals) + # Clone the locals (only the annotation space implements this) + w_locals = self.space.clone_locals(self.w_locals) + # XXX assume globals are constant + f = PyFrame(self.space, self.bytecode, self.w_globals, w_locals) f.valuestack = self.valuestack.clone() f.blockstack = self.blockstack.clone() f.last_exception = self.last_exception f.next_instr = self.next_instr - # Clone the locals (only the annotation space implements this) - f.w_locals = self.space.clone_locals(self.w_locals) return f def eval(self, executioncontext): @@ -109,7 +110,7 @@ ### frame initialization ### def load_builtins(self): - # initialize self.w_builtins. This cannot be done in the '.app.py' + # compute w_builtins. This cannot be done in the '.app.py' # file for bootstrapping reasons. w_builtinsname = self.space.wrap("__builtins__") try: @@ -127,7 +128,7 @@ w_builtins = self.space.getattr(w_builtins, w_attrname) except OperationError: pass # catch and ignore any error - self.w_builtins = w_builtins + return w_builtins ### exception stack ### From anna at codespeak.net Sun Jun 22 14:36:06 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 14:36:06 +0200 (MEST) Subject: [pypy-svn] rev 939 - pypy/trunk/doc/objspace Message-ID: <20030622123606.7BBB45A22F@thoth.codespeak.net> Author: anna Date: Sun Jun 22 14:36:06 2003 New Revision: 939 Modified: pypy/trunk/doc/objspace/trivialobjspace.txt Log: updated filename in link Modified: pypy/trunk/doc/objspace/trivialobjspace.txt ============================================================================== --- pypy/trunk/doc/objspace/trivialobjspace.txt (original) +++ pypy/trunk/doc/objspace/trivialobjspace.txt Sun Jun 22 14:36:06 2003 @@ -17,4 +17,4 @@ ------------------------------------------------------------------- -.. _StandardObjectSpace: StObSp.html \ No newline at end of file +.. _StandardObjectSpace: stdobjspace.html From gvanrossum at codespeak.net Sun Jun 22 14:36:16 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 14:36:16 +0200 (MEST) Subject: [pypy-svn] rev 940 - in pypy/trunk/src/pypy/objspace/ann: . test Message-ID: <20030622123616.880B85A22F@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 14:36:16 2003 New Revision: 940 Added: pypy/trunk/src/pypy/objspace/ann/wrapper.py Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Log: Refactoring. Move wrapper objects to new file. Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Sun Jun 22 14:36:16 2003 @@ -1,5 +1,6 @@ from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.pyframe import ControlFlowException +from pypy.objspace.ann.wrapper import union class IndeterminateCondition(ControlFlowException): @@ -34,7 +35,7 @@ assert w_obj.force == True w_obj.force = False r = ExecutionContext.eval_frame(self, f) - result = space.union(result, r) + result = union(result, r) if isinstance(result, W_Anything): break return result Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sun Jun 22 14:36:16 2003 @@ -7,35 +7,8 @@ from pypy.objspace.ann.cloningcontext import CloningExecutionContext from pypy.objspace.ann.cloningcontext import IndeterminateCondition +from pypy.objspace.ann.wrapper import * -class W_Object(object): - pass - -class W_Anything(W_Object): - pass - -class W_Integer(W_Object): - pass - -class W_Constant(W_Object): - def __init__(self, value): - self.value = value - def __repr__(self): - return '' % self.value - -class W_KnownKeysContainer(W_Object): - def __init__(self, args_w): - self.args_w = args_w - def __len__(self): - return len(self.args_w) - def __getitem__(self, i): - return self.args_w[i] - def clone(self): - args_w = self.args_w - if isinstance(args_w, dict): - args_w = args_w.copy() - # XXX Recurse down the values? - return W_KnownKeysContainer(args_w) class AnnException(Exception): @@ -98,27 +71,6 @@ assert isinstance(w_locals, W_KnownKeysContainer) return w_locals.clone() - def union(self, r1, r2): - # Unite two results - if r1 is r2: - return r1 - if r1 is None: - return r2 - if r2 is None: - return r1 - if isinstance(r1, W_Anything) or isinstance(r2, W_Anything): - return W_Anything() - if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and - r1.value == r2.value): - return W_Constant(r1.value) - if self.is_int(r1) and self.is_int(r2): - return W_Integer() - if (isinstance(r1, W_KnownKeysContainer) and - isinstance(r2, W_KnownKeysContainer) and - r1.args_w == r2.args_w): - return W_KnownKeysContainer(r1.args_w) - # XXX Could do more cases. This will blow up as we add more types - return W_Anything() # Specialized creators whose interface is in the abstract base class @@ -158,19 +110,11 @@ pass else: return self.wrap(left + right) - if self.is_int(w_left) and self.is_int(w_right): + if is_int(w_left) and is_int(w_right): return W_Integer() else: return W_Anything() - def is_int(self, w_obj): - if isinstance(w_obj, W_Integer): - return True - if isinstance(w_obj, W_Constant): - return isinstance(w_obj.value, int) - else: - return False - def call(self, w_func, w_args, w_kwds): func = self.unwrap(w_func) # Would be bad it it was W_Anything code = func.func_code Modified: pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Sun Jun 22 14:36:16 2003 @@ -47,6 +47,14 @@ 'f', [W_Integer()]) self.assertEquals(type(x), W_Integer) + def test_call(self): + x = self.codetest("def f(i):\n" + " return g(i)+2\n" + "def g(i):\n" + " return i+1\n", + 'f', [self.space.wrap(0)]) + self.assertEquals(self.space.unwrap(x), 3) + def test_conditional_1(self): x = self.codetest("def f(i):\n" " if i < 0:\n" @@ -65,6 +73,28 @@ 'f', [W_Integer()]) self.assertEquals(self.space.unwrap(x), 0) + def dont_test_while(self): + x = self.codetest("def f(i):\n" + " while i > 0:\n" + " i = i-1\n" + " return i\n", + 'f', [W_Integer()]) + self.assertEquals(type(x), W_Integer) + + def dont_test_global(self): + # XXX This doesn't work because we don't handle mutating globals + x = self.codetest("def f(i, j):\n" + " global x\n" + " x = i\n" + " if j > 0: pass\n" + " g()\n" + " return x\n" + "def g():\n" + " global x\n" + " x = x+1\n", + 'f', [self.space.wrap(0), W_Anything()]) + self.assertEquals(self.space.unwrap(x), 1) + if __name__ == '__main__': Added: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Sun Jun 22 14:36:16 2003 @@ -0,0 +1,65 @@ +"""Wrapper objects used by annotating space. + +The classes here represent various amounts of knowledge about a +wrapped object, from W_Constant (we know the exact value) to +W_Anything (we know nothing). The union() function computes unions. +We expect that there will eventually be a class that represents a +union of constants or other types too, in some cases. + +""" + +class W_Object(object): + pass + +class W_Anything(W_Object): + pass + +class W_Integer(W_Object): + pass + +class W_Constant(W_Object): + def __init__(self, value): + self.value = value + def __repr__(self): + return '' % self.value + +class W_KnownKeysContainer(W_Object): + def __init__(self, args_w): + self.args_w = args_w + def __len__(self): + return len(self.args_w) + def __getitem__(self, i): + return self.args_w[i] + def clone(self): + args_w = self.args_w + if isinstance(args_w, dict): + args_w = args_w.copy() + # XXX Recurse down the values? + return W_KnownKeysContainer(args_w) + +def union(r1, r2): + # Unite two results + if r1 is r2: + return r1 + if r1 is None: + return r2 + if r2 is None: + return r1 + if isinstance(r1, W_Anything) or isinstance(r2, W_Anything): + return W_Anything() + if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and + r1.value == r2.value): + return W_Constant(r1.value) + if is_int(r1) and is_int(r2): + return W_Integer() + if (isinstance(r1, W_KnownKeysContainer) and + isinstance(r2, W_KnownKeysContainer) and + r1.args_w == r2.args_w): + return W_KnownKeysContainer(r1.args_w) + # XXX Could do more cases. + # XXX This will blow up as we add more types. Refactor when that happens. + return W_Anything() + +def is_int(w_obj): + return (isinstance(w_obj, W_Integer) or + isinstance(w_obj, W_Constant) and isinstance(w_obj.value, int)) From gvanrossum at codespeak.net Sun Jun 22 14:38:04 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 14:38:04 +0200 (MEST) Subject: [pypy-svn] rev 941 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030622123804.C3EF95A22F@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 14:38:04 2003 New Revision: 941 Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py (contents, props changed) Log: fixeol. Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Sun Jun 22 14:38:04 2003 @@ -1,65 +1,65 @@ -"""Wrapper objects used by annotating space. - -The classes here represent various amounts of knowledge about a -wrapped object, from W_Constant (we know the exact value) to -W_Anything (we know nothing). The union() function computes unions. -We expect that there will eventually be a class that represents a -union of constants or other types too, in some cases. - -""" - -class W_Object(object): - pass - -class W_Anything(W_Object): - pass - -class W_Integer(W_Object): - pass - -class W_Constant(W_Object): - def __init__(self, value): - self.value = value - def __repr__(self): - return '' % self.value - -class W_KnownKeysContainer(W_Object): - def __init__(self, args_w): - self.args_w = args_w - def __len__(self): - return len(self.args_w) - def __getitem__(self, i): - return self.args_w[i] - def clone(self): - args_w = self.args_w - if isinstance(args_w, dict): - args_w = args_w.copy() - # XXX Recurse down the values? - return W_KnownKeysContainer(args_w) - -def union(r1, r2): - # Unite two results - if r1 is r2: - return r1 - if r1 is None: - return r2 - if r2 is None: - return r1 - if isinstance(r1, W_Anything) or isinstance(r2, W_Anything): - return W_Anything() - if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and - r1.value == r2.value): - return W_Constant(r1.value) - if is_int(r1) and is_int(r2): - return W_Integer() - if (isinstance(r1, W_KnownKeysContainer) and - isinstance(r2, W_KnownKeysContainer) and - r1.args_w == r2.args_w): - return W_KnownKeysContainer(r1.args_w) - # XXX Could do more cases. - # XXX This will blow up as we add more types. Refactor when that happens. - return W_Anything() - -def is_int(w_obj): - return (isinstance(w_obj, W_Integer) or - isinstance(w_obj, W_Constant) and isinstance(w_obj.value, int)) +"""Wrapper objects used by annotating space. + +The classes here represent various amounts of knowledge about a +wrapped object, from W_Constant (we know the exact value) to +W_Anything (we know nothing). The union() function computes unions. +We expect that there will eventually be a class that represents a +union of constants or other types too, in some cases. + +""" + +class W_Object(object): + pass + +class W_Anything(W_Object): + pass + +class W_Integer(W_Object): + pass + +class W_Constant(W_Object): + def __init__(self, value): + self.value = value + def __repr__(self): + return '' % self.value + +class W_KnownKeysContainer(W_Object): + def __init__(self, args_w): + self.args_w = args_w + def __len__(self): + return len(self.args_w) + def __getitem__(self, i): + return self.args_w[i] + def clone(self): + args_w = self.args_w + if isinstance(args_w, dict): + args_w = args_w.copy() + # XXX Recurse down the values? + return W_KnownKeysContainer(args_w) + +def union(r1, r2): + # Unite two results + if r1 is r2: + return r1 + if r1 is None: + return r2 + if r2 is None: + return r1 + if isinstance(r1, W_Anything) or isinstance(r2, W_Anything): + return W_Anything() + if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and + r1.value == r2.value): + return W_Constant(r1.value) + if is_int(r1) and is_int(r2): + return W_Integer() + if (isinstance(r1, W_KnownKeysContainer) and + isinstance(r2, W_KnownKeysContainer) and + r1.args_w == r2.args_w): + return W_KnownKeysContainer(r1.args_w) + # XXX Could do more cases. + # XXX This will blow up as we add more types. Refactor when that happens. + return W_Anything() + +def is_int(w_obj): + return (isinstance(w_obj, W_Integer) or + isinstance(w_obj, W_Constant) and isinstance(w_obj.value, int)) From mwh at codespeak.net Sun Jun 22 14:42:08 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 14:42:08 +0200 (MEST) Subject: [pypy-svn] rev 942 - in pypy/trunk/src/pypy: interpreter objspace/std Message-ID: <20030622124208.311855A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 14:42:07 2003 New Revision: 942 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/objspace.py Log: "do something about nonzero" Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Sun Jun 22 14:42:07 2003 @@ -190,6 +190,7 @@ ('and_', '&', 2, ['__and__', '__rand__']), ('or_', '|', 2, ['__or__', '__ror__']), ('xor', '^', 2, ['__xor__', '__rxor__']), + ('nonzero', 'nonzero', 1, ['__nonzero__']), ('inplace_add', '+=', 2, ['__iadd__']), ('inplace_sub', '-=', 2, ['__isub__']), ('inplace_mul', '*=', 2, ['__imul__']), Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Sun Jun 22 14:42:07 2003 @@ -74,4 +74,7 @@ # XXX -- mwh return space.newbool(0) +def nonzero__ANY(space, w_obj): + return space.newbool(space.is_true(w_obj)) + register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 22 14:42:07 2003 @@ -271,7 +271,6 @@ unwrap = MultiMethod('unwrap', 1, []) # returns an unwrapped object is_true = MultiMethod('nonzero', 1, []) # returns an unwrapped bool is_data_descr = MultiMethod('is_data_descr', 1, []) # returns an unwrapped bool - # XXX do something about __nonzero__ ! getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute From anna at codespeak.net Sun Jun 22 14:44:30 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 14:44:30 +0200 (MEST) Subject: [pypy-svn] rev 943 - pypy/trunk/doc/objspace Message-ID: <20030622124430.261545A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 14:44:29 2003 New Revision: 943 Modified: pypy/trunk/doc/objspace/annotateobjspace.txt pypy/trunk/doc/objspace/objspaceinterface.txt pypy/trunk/doc/objspace/stdobjspace.txt pypy/trunk/doc/objspace/trivialobjspace.txt Log: updated filenames in links Modified: pypy/trunk/doc/objspace/annotateobjspace.txt ============================================================================== --- pypy/trunk/doc/objspace/annotateobjspace.txt (original) +++ pypy/trunk/doc/objspace/annotateobjspace.txt Sun Jun 22 14:44:29 2003 @@ -25,5 +25,5 @@ ------------------------------ -.. _StandardObjectSpace: StObSp.html -.. _RestrictedPython: RestrictedPython.html +.. _StandardObjectSpace: stdobjspace.html +.. _RestrictedPython: restrictedpy.html Modified: pypy/trunk/doc/objspace/objspaceinterface.txt ============================================================================== --- pypy/trunk/doc/objspace/objspaceinterface.txt (original) +++ pypy/trunk/doc/objspace/objspaceinterface.txt Sun Jun 22 14:44:29 2003 @@ -108,4 +108,4 @@ --------------------------- -.. _ObjectSpace: ObjSpcDoc.html +.. _ObjectSpace: objspace.html Modified: pypy/trunk/doc/objspace/stdobjspace.txt ============================================================================== --- pypy/trunk/doc/objspace/stdobjspace.txt (original) +++ pypy/trunk/doc/objspace/stdobjspace.txt Sun Jun 22 14:44:29 2003 @@ -23,4 +23,9 @@ In our case it is a later optimization that we could make. We just don't want to make it now (and certainly not hard-coded at this level -- it could be introduced by the C translators that we will eventually write). So in summary: wrapping integers as instances is the simple path, while using plain integers instead is the complex path, not the other way around. -Note that the current StandardObjectSpace implementation uses MultiMethod dispatch instead of the complex rules of "Object/abstract.c". I think that this can be translated to a different low-level dispatch implementation that would be binary compatible with CPython's (basically the PyTypeObject structure and its function pointers). If compatibility is not required it will be more straightforwardly converted into some efficient multimethod code. +Note that the current StandardObjectSpace_ implementation uses MultiMethod_ dispatch instead of the complex rules of "Object/abstract.c". I think that this can be translated to a different low-level dispatch implementation that would be binary compatible with CPython's (basically the PyTypeObject structure and its function pointers). If compatibility is not required it will be more straightforwardly converted into some efficient multimethod code. + +--------------------------------------------------------------------------- + +.. _StandardObjectSpace: stdobjspace.html +.. _MultiMethod: multimethod.html \ No newline at end of file Modified: pypy/trunk/doc/objspace/trivialobjspace.txt ============================================================================== --- pypy/trunk/doc/objspace/trivialobjspace.txt (original) +++ pypy/trunk/doc/objspace/trivialobjspace.txt Sun Jun 22 14:44:29 2003 @@ -1,13 +1,13 @@ ================================= -PyPython TrivialObjectSpace +PyPython Trivial Object Space ================================= User History ---------------- -The easiest way to implement an ObjectSpace is to represent a Python object with itself. +The easiest way to implement an Object Space is to represent a Python object with itself. -A PyPy interpreter using the TrivialObjectSpace is an interpreter with its own main loop (written in Python), but this main loop manipulates real Python objects and all operations are done directly on the Python objects. For example, "1" really means "1" and when the interpreter encounters the BINARY_ADD bytecode instructions the TrivialObjectSpace will just add two real Python objects together using Python's "+". The same for lists, dictionaries, classes... We just use Python's own. +A PyPy interpreter using the Trivial Object Space is an interpreter with its own main loop (written in Python), but this main loop manipulates real Python objects and all operations are done directly on the Python objects. For example, "1" really means "1" and when the interpreter encounters the BINARY_ADD bytecode instructions the TrivialObjectSpace will just add two real Python objects together using Python's "+". The same for lists, dictionaries, classes... We just use Python's own. Of course you cannot do this if the goal is to write PyPy in such a way that it doesn't rely on a real underlying Python implementation like CPython. Still, it works, and it has its own uses, like testing our interpreter, or even interpreting a different kind of bytecode -- for example, it could probably be used to emulate generators in any Python version. (That would be quite slow, however.) From mwh at codespeak.net Sun Jun 22 14:44:59 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 14:44:59 +0200 (MEST) Subject: [pypy-svn] rev 944 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622124459.CB9BB5A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 14:44:59 2003 New Revision: 944 Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: support attribute assignment on user defined classes Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Sun Jun 22 14:44:59 2003 @@ -1,52 +1,59 @@ -import autopath -from pypy.tool import test - -class TestUserObject(test.AppTestCase): - - def test_emptyclass(self): - class empty: pass - inst = empty() - self.failUnless(isinstance(inst, empty)) - inst.attr=23 - self.assertEquals(inst.attr,23) - - def test_subclassing(self): - for base in tuple, list, dict, str, int, float: - try: - class subclass(base): pass - stuff = subclass() - except: - print 'not subclassable:', base - else: - self.failUnless(isinstance(stuff, base)) - - def test_subclasstuple(self): - class subclass(tuple): pass - stuff = subclass() - self.failUnless(isinstance(stuff, tuple)) - stuff.attr = 23 - self.assertEquals(stuff.attr,23) - self.assertEquals(len(stuff),0) - result = stuff + (1,2,3) - self.assertEquals(len(result),3) - - def test_subsubclass(self): - class base: - baseattr = 12 - class derived(base): - derivedattr = 34 - inst = derived() - self.failUnless(isinstance(inst, base)) - self.assertEquals(inst.baseattr,12) - self.assertEquals(inst.derivedattr,34) - - def test_descr_get(self): - class C: - class desc: - def __get__(self, ob, cls=None): - return 42 - prop = desc() - self.assertEquals(C().prop, 42) - -if __name__ == '__main__': - test.main() +import autopath +from pypy.tool import test + +class TestUserObject(test.AppTestCase): + + def test_emptyclass(self): + class empty: pass + inst = empty() + self.failUnless(isinstance(inst, empty)) + inst.attr=23 + self.assertEquals(inst.attr,23) + + def test_subclassing(self): + for base in tuple, list, dict, str, int, float: + try: + class subclass(base): pass + stuff = subclass() + except: + print 'not subclassable:', base + else: + self.failUnless(isinstance(stuff, base)) + + def test_subclasstuple(self): + class subclass(tuple): pass + stuff = subclass() + self.failUnless(isinstance(stuff, tuple)) + stuff.attr = 23 + self.assertEquals(stuff.attr,23) + self.assertEquals(len(stuff),0) + result = stuff + (1,2,3) + self.assertEquals(len(result),3) + + def test_subsubclass(self): + class base: + baseattr = 12 + class derived(base): + derivedattr = 34 + inst = derived() + self.failUnless(isinstance(inst, base)) + self.assertEquals(inst.baseattr,12) + self.assertEquals(inst.derivedattr,34) + + def test_descr_get(self): + class C: + class desc: + def __get__(self, ob, cls=None): + return 42 + prop = desc() + self.assertEquals(C().prop, 42) + + def test_class_setattr(self): + class C: + pass + C.a = 1 + self.assert_(hasattr(C, 'a')) + self.assertEquals(C.a, 1) + +if __name__ == '__main__': + test.main() Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Sun Jun 22 14:44:59 2003 @@ -63,6 +63,9 @@ space.call(init, w_args, w_kwds) return newobj +def getdict__UserType(space, w_usertype): + return w_usertype.w_dict + def repr__UserType(space, w_usertype): return space.wrap("" % w_usertype.typename) From anna at codespeak.net Sun Jun 22 14:50:04 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 14:50:04 +0200 (MEST) Subject: [pypy-svn] rev 945 - pypy/trunk/doc Message-ID: <20030622125004.3B67A5A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 14:50:03 2003 New Revision: 945 Removed: pypy/trunk/doc/builtins.txt Log: removed obsolete file Deleted: pypy/trunk/doc/builtins.txt ============================================================================== --- pypy/trunk/doc/builtins.txt Sun Jun 22 14:50:03 2003 +++ (empty file) @@ -1,152 +0,0 @@ -# this is just a list of the builtins from 2.2.3c1 -# we expect to annotate the file with comments about ease of -# implementation & implemented-ness of each builtin - -annotations: status/difficulty/strategy/urgency - -d == done -p == written, but the are problems -w == it works, but has not the full functionality -n == need to be done - -e == easy -h == hard - -o == essentially implemented by the objectspace -p == just write it in python -v == variable -t == type -m == messy - -u == urgent -i == important -n == normal -d == really don't care -r == resolved, done -U == unsupported - -For now, all exception names are synonyms (until inheritance happens). - -+ ArithmeticError -+ AssertionError -+ AttributeError -++DeprecationWarning -+ EOFError -+ EnvironmentError -+ Exception -+ FloatingPointError -+ IOError -+ ImportError -+ IndentationError -+ IndexError -+ KeyError -+ KeyboardInterrupt -+ LookupError -+ MemoryError -+ NameError -+ NotImplementedError -+ OSError -+ OverflowError -++OverflowWarning -+ ReferenceError -+ RuntimeError -++RuntimeWarning -+ StandardError -+ StopIteration -+ SyntaxError -++SyntaxWarning -+ SystemError -+ SystemExit -+ TabError -+ TypeError -+ UnboundLocalError -+ UnicodeError -++UserWarning -+ ValueError -++Warning -+ ZeroDivisionError - -Ellipsis -False -None -NotImplemented -True - - -- all singletons. - -ev __debug__ -ev __doc__ - - -whmu __import__ -nevd __name__ -deon abs -deon apply -n ti bool -nhtd buffer -nhpn callable -deon chr -nhtn classmethod -n pn cmp -nhmd coerce -nemn compile -- will need to become hard later -n pn complex -nepv copyright -nepv credits -deon delattr -n tn dict -nhpn dir -nepn divmod -- maybe should do more later -n pi eval -n pn execfile -n v exit -nhtu file -- ouch. maybe use Guido's sio stuff? - -- also, can probably escape to the host impl. for now -n pn filter -n tn float -deoi getattr -nepn globals -depn hasattr -- err, maybe not easy if all exceptions are the same -deon hash -nepn help -deon hex -deon id -nepd input -n t int -n md intern -dhpi isinstance -phoi issubclass -p oi iter -deoi len -n v license -n ti list -nemn locals -- maybe will become harder later -n t long -d pn map -n pn max -n pn min -n t object -neon oct -nhtu open -- see file, they're the same -deon ord -- chr -deon pow -n t property -n v quit -- (see exit) -d pi range -nepn raw_input -n pn reduce -nhpn reload -deon repr -nepn round -deoi setattr -n t slice -n t staticmethod -d t str -n t super -n t tuple -n t type -neon unichr -n t unicode -nepn vars -n t xrange -- alias to range for now? -nepn zip From tomek at codespeak.net Sun Jun 22 14:57:08 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Sun, 22 Jun 2003 14:57:08 +0200 (MEST) Subject: [pypy-svn] rev 946 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622125708.819755A0B4@thoth.codespeak.net> Author: tomek Date: Sun Jun 22 14:57:08 2003 New Revision: 946 Removed: pypy/trunk/src/pypy/objspace/std/rarray.py Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: Now besad the implementation on lists. Because the strings are immutable, i create always an result list (of a given size), and then fill in the chars Deleted: pypy/trunk/src/pypy/objspace/std/rarray.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/rarray.py Sun Jun 22 14:57:08 2003 +++ (empty file) @@ -1,71 +0,0 @@ -#The goal is to use a primitive array, which we -#later implement directly in c. We want to get -#rid of cpython dependencies. We wrap the original -#array module to see, which methods do we need - -import array - -def CharArrayFromStr(newstr): - b = CharArray() - b.setvalue(newstr) - return b - -def CharArraySize(size): - b = CharArray() - b.setsize(size) - return b - -class CharArray: - def __init__(self): - self._value = None - - def setvalue(self, value): - self._value = array.array('c', value) - self.len = len(value) - - def __repr__(self): - return self._value.tostring() - - - def hash(self): - #of cource, it doesn't make much sense hier, but the hash function - #also has to be implemented in c - return hash(self.value()) - - def value(self): - """returns back the string""" - return self._value.tostring() - - def getsubstring(self, startat, length): - """returns back the substring""" - return self._value[startat:startat+length].tostring() - - def charat(self, idx): - """returns char at the index""" - return self._value[idx] - - def setcharat(self, idx, ch): - """sets char at the index""" - self._value[idx] = ch - - def setsize(self, size): - """set size of the buffer to size""" - self._value = array.array('c', ' ' * size) - self.len = size - - def append(self, newstr): - """append the new string to the buffer""" - newstr = self._value.tostring() + newstr - self._value = array.array('c', newstr) - self.len = len(newstr) - - def setsubstring(self, idx, substr): - """set the buffer to substr at the idx""" - #it's a hack, but this is not very important, while - #we are going to reimplement this stuff in c - list = self._value.tolist() - for char in substr: - list[idx] = char - idx = idx + 1 - self._value = array.array('c', "".join(list)) - Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 14:57:08 2003 @@ -7,8 +7,6 @@ from noneobject import W_NoneObject from tupleobject import W_TupleObject -from rarray import CharArrayFromStr, CharArraySize - applicationfile = StdObjSpace.AppFile(__name__) class W_StringObject(W_Object): @@ -16,11 +14,11 @@ def __init__(w_self, space, str): W_Object.__init__(w_self, space) - w_self._value = CharArrayFromStr(str) + w_self._value = str def __repr__(w_self): """ representation for debugging purposes """ - return "%s(%r)" % (w_self.__class__.__name__, w_self._value.value()) + return "%s(%r)" % (w_self.__class__.__name__, w_self._value) registerimplementation(W_StringObject) @@ -50,18 +48,18 @@ return (o>=97 and o<=122) -def _is_generic(w_self, fun): +def _is_generic(self, fun): space = w_self.space - v = w_self._value - if v.len == 0: + v = space.unwrap(w_self) + if len(v) == 0: return space.w_False - if v.len == 1: - c = v.charat(0) + if len(v) == 1: + c = v[0] return space.newbool(fun(c)) else: res = 1 - for idx in range(v.len): - if not fun(v.charat(idx)): + for idx in range(len(v)): + if not fun(v[idx]): return space.w_False return space.w_True @@ -87,32 +85,39 @@ pass def str_upper__String(space, w_self): - up = W_StringObject(space, w_self._value.value()) - for i in range(up._value.len): - ch = up._value.charat(i) + self = space.unwrap(w_self) + res = [' '] * len(self) + for i in range(len(self)): + ch = self[i] if _islower(ch): o = ord(ch) - 32 - up._value.setcharat(i, chr(o)) + buf[i] = chr(o) + else: + buf[i] = ch - return up + return space.wrap("".join(res)) def str_capitalize__String(space, w_self): - w_str = W_StringObject(space, space.unwrap(w_self)) - buffer = w_str._value - if buffer.len > 0: - ch = buffer.charat(0) + input = space.unwrap(w_self) + buffer = [' '] * len(input) + if len(input) > 0: + ch = input[0] if _islower(ch): o = ord(ch) - 32 - buffer.setcharat(0, chr(o)) - return w_str + buffer[0] = chr(o) + for i in range(1, len(input)): + buffer[i] = input[i] + return space.wrap("".join(buffer)) def str_title__String(space, w_self): - w_str = W_StringObject(space, space.unwrap(w_self)) - buffer = w_str._value + u = space.unwrap + input = u(w_self) + buffer = [' '] * len(input) inword = 0 - for pos in range(0, buffer.len): - ch = buffer.charat(pos) + for pos in range(0, len(input)): + ch = input[pos] + buffer[pos] = ch if ch.isspace(): if inword: inword = 0 @@ -120,15 +125,16 @@ if not inword: if _islower(ch): o = ord(ch) - 32 - buffer.setcharat(pos, chr(o)) + buffer[pos] = chr(o) inword = 1 - return w_str + return space.wrap("".join(buffer)) def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1): res = [] inword = 0 - value = w_self._value.value() - maxsplit = space.unwrap(w_maxsplit) + u = space.unwrap + value = u(w_self) + maxsplit = u(w_maxsplit) pos = 0 for ch in value: @@ -153,12 +159,13 @@ return W_ListObject(space, res) def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): + u = space.unwrap res = [] start = 0 - value = w_self._value.value() - by = w_by._value.value() - bylen = space.unwrap(space.len(w_by)) - maxsplit = space.unwrap(w_maxsplit) + value = u(w_self) + by = u(w_by) + bylen = len(by) + maxsplit = u(w_maxsplit) #if maxsplit is default, then you have no limit #of the length of the resulting array @@ -171,7 +178,7 @@ next = value.find(by, start) if next < 0: res.append(value[start:]) - start = w_self._value.len + 1 + start = len(value) + 1 break res.append(value[start:next]) start = next + bylen @@ -180,7 +187,7 @@ if maxsplit > -1: splitcount = splitcount - 1 - if start < w_self._value.len: + if start < len(value): res.append(value[start:]) for i in range(len(res)): @@ -188,36 +195,44 @@ return W_ListObject(w_self.space, res) def str_join__String_ANY(space, w_self, w_list): + u = space.unwrap list = space.unpackiterable(w_list) if list: + self = u(w_self) firstelem = 1 listlen = 0 reslen = 0 #compute the length of the resulting string for w_item in list: - reslen = reslen + w_item._value.len + reslen = reslen + len(u(w_item)) listlen = listlen + 1 - reslen = reslen + (listlen - 1) * w_self._value.len + reslen = reslen + (listlen - 1) * len(self) #allocate the string buffer - res = CharArraySize(reslen) + res = [' '] * reslen pos = 0 #fill in the string buffer" for w_item in list: + item = u(w_item) if firstelem: - res.setsubstring(pos, w_item._value.value()) - pos = pos + w_item._value.len + for i in range(len(item)): + res[i+pos] = item[i] firstelem = 0 + pos = pos + len(item) else: - res.setsubstring(pos, w_self._value.value()) - pos = pos + w_self._value.len - res.setsubstring(pos, w_item._value.value()) - pos = pos + w_item._value.len - return W_StringObject(space, res.value()) + for i in range(len(self)): + res[i+pos] = item[i] + pos = pos + len(self) + + for i in range(len(item)): + res[i+pos] = item[i] + pos = pos + len(item) + + return space.wrap("".join(res)) else: - return W_StringObject(space, "") + return space.wrap("") def str_rjust__String_ANY(space, w_self, w_arg): @@ -245,6 +260,36 @@ return W_StringObject(space, u_self) +def str_find__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): + start = space.unwrap(w_start) + end = space.unwrap(w_end) + + self = space.unwrap(w_self) + sub = space.unwrap(w_sub) + + if start is None: + start = 0 + + if end is None: + end = self.len + + maxend = self.len - sub.len + + if end > maxend: + end = maxend + + if sub.len == 0 and start < end: + return start + + for i in range(start, end): + match = 1 + for idx in range(sub.len): + if not sub[idx] == self[idx+i]: + match = 0 + break + return i + return -1 + def str_strip__String(space, w_self): u = space.unwrap @@ -285,13 +330,13 @@ def unwrap__String(space, w_str): - return w_str._value.value() + return w_str._value def is_true__String(space, w_str): - return w_str._value.len != 0 + return len(space.unwrap(w_str)) != 0 def hash__String(space, w_str): - return W_IntObject(space, w_str._value.hash()) + return W_IntObject(space, hash(space.unwrap(w_str))) EQ = 1 @@ -301,9 +346,11 @@ LT = 5 NE = 6 + def string_richcompare(space, w_str1, w_str2, op): - str1 = w_str1._value - str2 = w_str2._value + u = space.unwrap + str1 = u(w_str1) + str2 = u(w_str2) if space.is_true(space.is_(w_str1, w_str2)): if op == EQ or op == LE or op == GE: @@ -314,32 +361,32 @@ pass else: if op == EQ: - if str1.len == str2.len: - for i in range(str1.len): - if ord(str1.charat(i)) != ord(str2.charat(i)): + if len(str1) == len(str2): + for i in range(len(str1)): + if ord(str1[i]) != ord(str2[i]): return space.w_False return space.w_True else: return space.w_False else: - if str1.len > str2.len: - min_len = str2.len + if len(str1) > len(str2): + min_len = len(str2) else: - min_len = str1.len + min_len = len(str1) c = 0 idx = 0 if (min_len > 0): while (c == 0) and (idx < min_len): - c = ord(str1.charat(idx)) - ord(str2.charat(idx)) + c = ord(str1[idx]) - ord(str2[idx]) idx = idx + 1 else: c = 0 if (c == 0): - if str1.len < str2.len: + if len(str1) < len(str2): c = -1 - elif str1.len > str2.len: + elif len(str1) > len(str2): c = 1 else: c = 0 @@ -376,22 +423,24 @@ return string_richcompare(space, w_str1, w_str2, GE) def getitem__String_Int(space, w_str, w_int): + u = space.unwrap ival = w_int.intval - slen = w_str._value.len + str = u(w_str) + slen = len(u(w_str)) if ival < 0: ival += slen if ival < 0 or ival >= slen: exc = space.call_function(space.w_IndexError, space.wrap("string index out of range")) raise OperationError(space.w_IndexError, exc) - return W_StringObject(space, w_str._value.charat(ival)) + return W_StringObject(space, str[ival]) def getitem__String_Slice(space, w_str, w_slice): return space.gethelper(applicationfile).call( "getitem_string_slice", [w_str, w_slice]) w = space.wrap u = space.unwrap - w_start, w_stop, w_step, w_sl = w_slice.indices(w(w_str._value.len)) + w_start, w_stop, w_step, w_sl = w_slice.indices(w(len(u(w_str._value)))) start = u(w_start) stop = u(w_stop) step = u(w_step) @@ -404,20 +453,27 @@ return str_join(space, w_empty, w_r) def add__String_String(space, w_left, w_right): - buf = CharArraySize(w_left._value.len + w_right._value.len) - buf.setsubstring(0, w_left._value.value()) - buf.setsubstring(w_left._value.len, w_right._value.value()) - return W_StringObject(space, buf.value()) + u = space.unwrap + right = u(w_right) + left = u(w_left) + buf = [' '] * (len(left) + len(right)) + for i in range(len(left)): + buf[i] = left[i] + for i in range(len(right)): + buf[i+len(left)] = right[i] + return space.wrap("".join(buf)) def mod_str_tuple(space, w_format, w_args): raise NotImplementedError def len__String(space, w_str): - return space.wrap(w_str._value.len) + return space.wrap(len(space.unwrap(w_str))) def str__String(space, w_str): return w_str + + def repr__String(space, w_str): # XXX this is bogus -- mwh return space.wrap(repr(space.unwrap(w_str))) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sun Jun 22 14:57:08 2003 @@ -21,6 +21,9 @@ str_upper = MultiMethod('upper', 1) str_capitalize = MultiMethod('capitalize', 1) str_title = MultiMethod('title', 1) + #XXX we need to have the possibility to specify, if the a parameter + #was given + str_find = MultiMethod('find', 4, defaults=(0, 0)) str_strip = MultiMethod('strip', 1) str_rstrip = MultiMethod('rstrip', 1) str_lstrip = MultiMethod('lstrip', 1) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sun Jun 22 14:57:08 2003 @@ -59,7 +59,10 @@ def lookup_exactly_here(w_self, w_key): space = w_self.space key = space.unwrap(w_key) - assert isinstance(key, str) + #assert isinstance(key, str) + #XXX it's actually not true, because the unwraped string is + #a CharArray - a structure with length and char buffer, + #which can be quite simple mapped to a C implementation try: code = w_self.multimethods[key] except KeyError: From anna at codespeak.net Sun Jun 22 15:04:21 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 15:04:21 +0200 (MEST) Subject: [pypy-svn] rev 947 - in pypy/trunk/doc: . sprintinfo Message-ID: <20030622130421.E34D35A243@thoth.codespeak.net> Author: anna Date: Sun Jun 22 15:04:21 2003 New Revision: 947 Added: pypy/trunk/doc/sprintinfo/ Removed: pypy/trunk/doc/pypy-brainstorming-sprint.txt pypy/trunk/doc/sprint-planning.txt Log: created sprintinfo directory and moved files into it, removed extra copies of files Deleted: pypy/trunk/doc/pypy-brainstorming-sprint.txt ============================================================================== --- pypy/trunk/doc/pypy-brainstorming-sprint.txt Sun Jun 22 15:04:21 2003 +++ (empty file) @@ -1,95 +0,0 @@ - -General ideas of what PyPy should achieve for us - -- Python interpreter written in python - - loads bytecode - - delegates/dispatches to ObjectSpaces to implement operations - on the objects - - there can be more than one ObjectSpace - - for example: BorrowingObjectSpace (from CPython) - - define/implement a class that emulates the Python - Execution Frame - -- use the main-loop of the interpreter to do a lot of - things (e.g. do type inference during running the bytecode - or not even run the bytecodes, but interpret various attributes of the code) - -- working together, producing something real - -- saving interpreter state to an image (following the smalltalk model) - process-migration / persistence - -- looking at the entire code base (living in an image), browsing - objects interactively - -- interactive environment, trying code snippets, introspection - -- deploying python made easy, integrate version control systems - -- integrate the various technologies on the web site, issue tracking, - Wiki... - -- seperate exception handling from the mainline code, avoid peppering - your code with try :-), put exception handling into objects. - -- import python code from the version control store directly, give - imported code also a time dimension - -- combining python interpreters from multiple machines (cluster) into a - virtual sandbox (agent space?) - -- get a smaller (maybe faster) python with very few C-code - -- (hoping for Psyc) to render fast code from Python code (instead of - hard-c) - -- go to a higher level python core (and write out/generate interpreters - in different languages), e.g. the former P-to-C resolved the evalframe-loop - but still called into the Python-C-library which is statically coded - -- very far fetched: PyPython becomes a/the reference implementation - -- have enough flexibility to make a separate stackless obsolete - -- have a language that is high-level/easy enough to program - but with the same performance as statically compiled languages - (e.g. C++) - - -what is the difference between a compiler and an interpreter ------------------------------------------------------------- - -f = bytecode interpreter -p = program -a = arguments - -c = compiler - -assert f(p, a) == c(p)(a) == r - - -- architecture overview - * byte code interp loop - plan how the interp loop should look like from a hi level - map that structure in descriptions that can be used to generate interpreters/compilers - define the frame structure - - * define a object/type model that maps into python data structures - wrap cpython objects into the new object model so we can continue - to use cpython modules - - * rewrite c python modules and the builtin object library in python - optimzation for a potential global python optimizer, until that - exists it will be slower than the corresponding cpython implementation - -- import the cpython distribution so we can use parts of it in our - repository, make it easy to follow the cpython development - -- finish the python to byte code compiler in python project (this is - already part of the cpython distribution, needs a python lexer) - -- doing other things than interpreting byte code from the python interp - loop, for example generate C code, implement other object spaces in our - terminlogy other far fetched things with execution - -- how to enter c ysystem calls into the python object space (ctypes) Deleted: pypy/trunk/doc/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprint-planning.txt Sun Jun 22 15:04:21 2003 +++ (empty file) @@ -1,77 +0,0 @@ -LouvainLaNeuveSprint planning - ---> join this screen: ssh codespeak.net "and" screen -x hpk/hpk - -eternal goals: -- do more tests (eternal goal) -- Fix XXX-marked things - -- enhance StdObjSpace, define goals and achieve them - http://codespeak.net/svn/pypy/trunk/src/goals/ - - - Being able to run main.py dis.dis(dis.dis) - - Unbound methods. - - support the objects we see falling back to CPython. - - more builtins. - - more things from sys. - - dict object/type - - Hash table based implementation of dictionaries? - - list object/type - - check all other type implementation and document their state: - - alex, christian - - boolobject done - cpythonobject done - instmethobject done - longobject done - sliceobject done - userobject done - dictobject - intobject - listobject - floatobject - iterobject - tupleobject - - tomek, holger, guenter - - moduleobject done - stringobject - noneobject - - - write a small tool that checks a type's methods of - CPython against PyPy - (Jacob, Laura) done - -- improve "main.py" tool and rename it to "py.py" :-) - with a subset of the options of "python". This - should allow executing commands (-c), going - interactive (-i) and executing files (argv[1]) - - - Fix the way an OBJECTSPACE is selected. ? - - main.py doesn't handle exceptions very well. - - (michael) - -- move design documentation from wiki to subversion - (doc/design) to make it locally editable (instead - of html-textfields) and keep everyone up-to-date - maybe rearrange the doc-directory to be into src/pypy - - (Anna, Laura) - -- go through the wiki and clean up "stale" or old pages - -- implement AnnotationObjSpace and the beginnings - of a C code generator. the basic idea is "abstract - interpretation".... - - - getting the translator to understand RPython, handling the - constructions it can and delegating the things it doesn't - understand to CPython (Mimicking Python2C) - - (Armin, Guido) - -- discuss funding and future organization issues - From anna at codespeak.net Sun Jun 22 15:17:51 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 15:17:51 +0200 (MEST) Subject: [pypy-svn] rev 948 - pypy/trunk/doc/sprintinfo Message-ID: <20030622131751.739275A243@thoth.codespeak.net> Author: anna Date: Sun Jun 22 15:17:51 2003 New Revision: 948 Added: pypy/trunk/doc/sprintinfo/llnsprint-brainstorming.txt pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: added files to directory Added: pypy/trunk/doc/sprintinfo/llnsprint-brainstorming.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/sprintinfo/llnsprint-brainstorming.txt Sun Jun 22 15:17:51 2003 @@ -0,0 +1,95 @@ + +General ideas of what PyPy should achieve for us + +- Python interpreter written in python + - loads bytecode + - delegates/dispatches to ObjectSpaces to implement operations + on the objects + - there can be more than one ObjectSpace + - for example: BorrowingObjectSpace (from CPython) + - define/implement a class that emulates the Python + Execution Frame + +- use the main-loop of the interpreter to do a lot of + things (e.g. do type inference during running the bytecode + or not even run the bytecodes, but interpret various attributes of the code) + +- working together, producing something real + +- saving interpreter state to an image (following the smalltalk model) + process-migration / persistence + +- looking at the entire code base (living in an image), browsing + objects interactively + +- interactive environment, trying code snippets, introspection + +- deploying python made easy, integrate version control systems + +- integrate the various technologies on the web site, issue tracking, + Wiki... + +- seperate exception handling from the mainline code, avoid peppering + your code with try :-), put exception handling into objects. + +- import python code from the version control store directly, give + imported code also a time dimension + +- combining python interpreters from multiple machines (cluster) into a + virtual sandbox (agent space?) + +- get a smaller (maybe faster) python with very few C-code + +- (hoping for Psyc) to render fast code from Python code (instead of + hard-c) + +- go to a higher level python core (and write out/generate interpreters + in different languages), e.g. the former P-to-C resolved the evalframe-loop + but still called into the Python-C-library which is statically coded + +- very far fetched: PyPython becomes a/the reference implementation + +- have enough flexibility to make a separate stackless obsolete + +- have a language that is high-level/easy enough to program + but with the same performance as statically compiled languages + (e.g. C++) + + +what is the difference between a compiler and an interpreter +------------------------------------------------------------ + +f = bytecode interpreter +p = program +a = arguments + +c = compiler + +assert f(p, a) == c(p)(a) == r + + +- architecture overview + * byte code interp loop + plan how the interp loop should look like from a hi level + map that structure in descriptions that can be used to generate interpreters/compilers + define the frame structure + + * define a object/type model that maps into python data structures + wrap cpython objects into the new object model so we can continue + to use cpython modules + + * rewrite c python modules and the builtin object library in python + optimzation for a potential global python optimizer, until that + exists it will be slower than the corresponding cpython implementation + +- import the cpython distribution so we can use parts of it in our + repository, make it easy to follow the cpython development + +- finish the python to byte code compiler in python project (this is + already part of the cpython distribution, needs a python lexer) + +- doing other things than interpreting byte code from the python interp + loop, for example generate C code, implement other object spaces in our + terminlogy other far fetched things with execution + +- how to enter c ysystem calls into the python object space (ctypes) Added: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Sun Jun 22 15:17:51 2003 @@ -0,0 +1,77 @@ +LouvainLaNeuveSprint planning + +--> join this screen: ssh codespeak.net "and" screen -x hpk/hpk + +eternal goals: +- do more tests (eternal goal) +- Fix XXX-marked things + +- enhance StdObjSpace, define goals and achieve them + http://codespeak.net/svn/pypy/trunk/src/goals/ + + - Being able to run main.py dis.dis(dis.dis) + - Unbound methods. + - support the objects we see falling back to CPython. + - more builtins. + - more things from sys. + - dict object/type + - Hash table based implementation of dictionaries? + - list object/type + - check all other type implementation and document their state: + + alex, christian + + boolobject done + cpythonobject done + instmethobject done + longobject done + sliceobject done + userobject done + dictobject + intobject + listobject + floatobject + iterobject + tupleobject + + tomek, holger, guenter + + moduleobject done + stringobject + noneobject + + - write a small tool that checks a type's methods of + CPython against PyPy + (Jacob, Laura) done + +- improve "main.py" tool and rename it to "py.py" :-) + with a subset of the options of "python". This + should allow executing commands (-c), going + interactive (-i) and executing files (argv[1]) + + - Fix the way an OBJECTSPACE is selected. ? + - main.py doesn't handle exceptions very well. + + (michael) + +- move design documentation from wiki to subversion + (doc/design) to make it locally editable (instead + of html-textfields) and keep everyone up-to-date + maybe rearrange the doc-directory to be into src/pypy + + (Anna, Laura) + +- go through the wiki and clean up "stale" or old pages + +- implement AnnotationObjSpace and the beginnings + of a C code generator. the basic idea is "abstract + interpretation".... + + - getting the translator to understand RPython, handling the + constructions it can and delegating the things it doesn't + understand to CPython (Mimicking Python2C) + + (Armin, Guido) + +- discuss funding and future organization issues + From tomek at codespeak.net Sun Jun 22 15:19:42 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Sun, 22 Jun 2003 15:19:42 +0200 (MEST) Subject: [pypy-svn] rev 949 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622131942.393435A243@thoth.codespeak.net> Author: tomek Date: Sun Jun 22 15:19:41 2003 New Revision: 949 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: I reverted the changes on typeobject.py, so there are no changes of my on typeobject.py Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 15:19:41 2003 @@ -213,7 +213,7 @@ res = [' '] * reslen pos = 0 - #fill in the string buffer" + #fill in the string buffer for w_item in list: item = u(w_item) if firstelem: @@ -245,7 +245,7 @@ if d>0: u_self = d * ' ' + u_self - return W_StringObject(space, u_self) + return space.wrap(u_self) def str_ljust__String_ANY(space, w_self, w_arg): @@ -258,7 +258,7 @@ if d>0: u_self += d * ' ' - return W_StringObject(space, u_self) + return space.wrap(u_self) def str_find__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): start = space.unwrap(w_start) @@ -302,7 +302,7 @@ while u_self[rpos - 1] == ' ': rpos -= 1 - return W_StringObject(space, u_self[lpos:rpos]) + return space.wrap(u_self[lpos:rpos]) @@ -314,7 +314,7 @@ while u_self[rpos - 1] == ' ': rpos -= 1 - return W_StringObject(space, u_self[:rpos]) + return space.wrap(u_self[:rpos]) @@ -325,7 +325,7 @@ while u_self[lpos] == ' ': lpos += 1 - return W_StringObject(space, u_self[lpos:]) + return space.wrap(u_self[lpos:]) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sun Jun 22 15:19:41 2003 @@ -59,10 +59,7 @@ def lookup_exactly_here(w_self, w_key): space = w_self.space key = space.unwrap(w_key) - #assert isinstance(key, str) - #XXX it's actually not true, because the unwraped string is - #a CharArray - a structure with length and char buffer, - #which can be quite simple mapped to a C implementation + assert isinstance(key, str) try: code = w_self.multimethods[key] except KeyError: From mwh at codespeak.net Sun Jun 22 15:36:19 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 15:36:19 +0200 (MEST) Subject: [pypy-svn] rev 950 - pypy/trunk/src/pypy/objspace Message-ID: <20030622133619.B298C5A266@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 15:36:19 2003 New Revision: 950 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: add set, delete Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Sun Jun 22 15:36:19 2003 @@ -340,6 +340,11 @@ def init(self, type, args, kw): pass + def set(self, descr, ob, val): + descr.__set__(ob, val) + + def delete(self, descr, ob): + descr.__delete__(ob) for m in ObjSpace.MethodTable: if not hasattr(TrivialObjSpace, m[0]): From hpk at codespeak.net Sun Jun 22 15:43:50 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 15:43:50 +0200 (MEST) Subject: [pypy-svn] rev 951 - pypy/trunk/doc/objspace Message-ID: <20030622134350.DDEED5A268@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 15:43:50 2003 New Revision: 951 Modified: pypy/trunk/doc/objspace/multimethod.txt Log: pypythobn to pypy Modified: pypy/trunk/doc/objspace/multimethod.txt ============================================================================== --- pypy/trunk/doc/objspace/multimethod.txt (original) +++ pypy/trunk/doc/objspace/multimethod.txt Sun Jun 22 15:43:50 2003 @@ -1,5 +1,5 @@ ======================== -PyPython MultiMethod +PyPy MultiMethod ======================== Notes on Multimethods From jacob at codespeak.net Sun Jun 22 16:34:44 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sun, 22 Jun 2003 16:34:44 +0200 (MEST) Subject: [pypy-svn] rev 952 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622143444.6066B5A22F@thoth.codespeak.net> Author: jacob Date: Sun Jun 22 16:34:43 2003 New Revision: 952 Modified: pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py pypy/trunk/src/pypy/objspace/std/tupleobject.py Log: Added tuple __ne__, __gt__, __ge__, __le__ plus tests. Modified: pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_tupleobject.py Sun Jun 22 16:34:43 2003 @@ -115,5 +115,129 @@ test1((5,7,1,4), -3, 11, 2, (7, 4)) test1((5,7,1,4), -5, 11, 2, (5, 1)) + def test_eq(self): + w = self.space.wrap + + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + + self.assertEqual_w(self.space.eq(w_tuple0, w_tuple1), + self.space.w_False) + self.assertEqual_w(self.space.eq(w_tuple1, w_tuple0), + self.space.w_False) + self.assertEqual_w(self.space.eq(w_tuple1, w_tuple1), + self.space.w_True) + self.assertEqual_w(self.space.eq(w_tuple1, w_tuple2), + self.space.w_True) + self.assertEqual_w(self.space.eq(w_tuple2, w_tuple3), + self.space.w_False) + def test_ne(self): + w = self.space.wrap + + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + + self.assertEqual_w(self.space.ne(w_tuple0, w_tuple1), + self.space.w_True) + self.assertEqual_w(self.space.ne(w_tuple1, w_tuple0), + self.space.w_True) + self.assertEqual_w(self.space.ne(w_tuple1, w_tuple1), + self.space.w_False) + self.assertEqual_w(self.space.ne(w_tuple1, w_tuple2), + self.space.w_False) + self.assertEqual_w(self.space.ne(w_tuple2, w_tuple3), + self.space.w_True) + def test_lt(self): + w = self.space.wrap + + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.lt(w_tuple0, w_tuple1), + self.space.w_True) + self.assertEqual_w(self.space.lt(w_tuple1, w_tuple0), + self.space.w_False) + self.assertEqual_w(self.space.lt(w_tuple1, w_tuple1), + self.space.w_False) + self.assertEqual_w(self.space.lt(w_tuple1, w_tuple2), + self.space.w_False) + self.assertEqual_w(self.space.lt(w_tuple2, w_tuple3), + self.space.w_True) + self.assertEqual_w(self.space.lt(w_tuple4, w_tuple3), + self.space.w_True) + + def test_ge(self): + w = self.space.wrap + + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.ge(w_tuple0, w_tuple1), + self.space.w_False) + self.assertEqual_w(self.space.ge(w_tuple1, w_tuple0), + self.space.w_True) + self.assertEqual_w(self.space.ge(w_tuple1, w_tuple1), + self.space.w_True) + self.assertEqual_w(self.space.ge(w_tuple1, w_tuple2), + self.space.w_True) + self.assertEqual_w(self.space.ge(w_tuple2, w_tuple3), + self.space.w_False) + self.assertEqual_w(self.space.ge(w_tuple4, w_tuple3), + self.space.w_False) + + def test_gt(self): + w = self.space.wrap + + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.gt(w_tuple0, w_tuple1), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_tuple1, w_tuple0), + self.space.w_True) + self.assertEqual_w(self.space.gt(w_tuple1, w_tuple1), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_tuple1, w_tuple2), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_tuple2, w_tuple3), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_tuple4, w_tuple3), + self.space.w_False) + + def test_le(self): + w = self.space.wrap + + w_tuple0 = W_TupleObject(self.space, []) + w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.le(w_tuple0, w_tuple1), + self.space.w_True) + self.assertEqual_w(self.space.le(w_tuple1, w_tuple0), + self.space.w_False) + self.assertEqual_w(self.space.le(w_tuple1, w_tuple1), + self.space.w_True) + self.assertEqual_w(self.space.le(w_tuple1, w_tuple2), + self.space.w_True) + self.assertEqual_w(self.space.le(w_tuple2, w_tuple3), + self.space.w_True) + self.assertEqual_w(self.space.le(w_tuple4, w_tuple3), + self.space.w_True) + if __name__ == '__main__': test.main() Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Sun Jun 22 16:34:43 2003 @@ -72,6 +72,9 @@ def mul__Int_Tuple(space, w_int, w_tuple): return mul__Tuple_Int(space, w_tuple, w_int) +def ne__Tuple_Tuple(space, w_tuple1, w_tuple2): + return space.not_(eq__Tuple_Tuple(space, w_tuple1, w_tuple2)) + def eq__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems @@ -88,7 +91,6 @@ return b def lt__Tuple_Tuple(space, w_tuple1, w_tuple2): - # XXX tuple_le, tuple_gt, tuple_ge, tuple_ne must also be explicitely done items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems ncmp = _min(len(items1), len(items2)) @@ -99,6 +101,23 @@ # No more items to compare -- compare sizes return space.newbool(len(items1) < len(items2)) +def ge__Tuple_Tuple(space, w_tuple1, w_tuple2): + return space.not_(lt__Tuple_Tuple(space, w_tuple1, w_tuple2)) + +def gt__Tuple_Tuple(space, w_tuple1, w_tuple2): + items1 = w_tuple1.wrappeditems + items2 = w_tuple2.wrappeditems + ncmp = _min(len(items1), len(items2)) + # Search for the first index where items are different + for p in range(ncmp): + if not space.is_true(space.eq(items1[p], items2[p])): + return space.gt(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(len(items1) > len(items2)) + +def le__Tuple_Tuple(space, w_tuple1, w_tuple2): + return space.not_(gt__Tuple_Tuple(space, w_tuple1, w_tuple2)) + def repr__Tuple(space, w_tuple): # XXX slimy! --mwh return space.wrap(repr(space.unwrap(w_tuple))) From mwh at codespeak.net Sun Jun 22 16:45:25 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 16:45:25 +0200 (MEST) Subject: [pypy-svn] rev 953 - in pypy/trunk/src/pypy: interpreter objspace/std objspace/std/test Message-ID: <20030622144525.926095A22F@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 16:45:24 2003 New Revision: 953 Added: pypy/trunk/src/pypy/objspace/std/test/test_floatobject.py (contents, props changed) Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/objspace/std/floatobject.py pypy/trunk/src/pypy/objspace/std/floattype.py pypy/trunk/src/pypy/objspace/std/intobject.py pypy/trunk/src/pypy/objspace/std/inttype.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/test/test_intobject.py Log: add, and use multimethods 'int', 'float' corresponding to __int__ and __float__. Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Sun Jun 22 16:45:24 2003 @@ -191,6 +191,8 @@ ('or_', '|', 2, ['__or__', '__ror__']), ('xor', '^', 2, ['__xor__', '__rxor__']), ('nonzero', 'nonzero', 1, ['__nonzero__']), + ('int', 'int', 1, ['__int__']), + ('float', 'float', 1, ['__float__']), ('inplace_add', '+=', 2, ['__iadd__']), ('inplace_sub', '-=', 2, ['__isub__']), ('inplace_mul', '*=', 2, ['__imul__']), Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/floatobject.py Sun Jun 22 16:45:24 2003 @@ -31,13 +31,11 @@ delegate__Int.priority = PRIORITY_CHANGE_TYPE -def float_float(space,w_value): - if w_value.__class__ == W_FloatObject: - return w_value - else: - return W_FloatObject(space, w_value.floatval) +def float__Float(space, w_value): + return w_value -#?StdObjSpace.float.register(float_float, W_FloatObject) +def int__Float(space, w_value): + return space.newint(int(w_value.floatval)) def unwrap__Float(space, w_float): return w_float.floatval Modified: pypy/trunk/src/pypy/objspace/std/floattype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floattype.py (original) +++ pypy/trunk/src/pypy/objspace/std/floattype.py Sun Jun 22 16:45:24 2003 @@ -5,3 +5,27 @@ class W_FloatType(W_TypeObject): typename = 'float' + +def new__FloatType_ANY_ANY(space, w_inttype, w_args, w_kwds): + if space.is_true(w_kwds): + raise OperationError(space.w_TypeError, + space.wrap("no keyword arguments expected")) + args = space.unpackiterable(w_args) + if len(args) == 0: + return space.newint(0) + elif len(args) == 1: + arg = args[0] + if space.is_true(space.issubtype(space.type(arg), + space.w_str)): + try: + return space.newfloat(float(space.unwrap(arg))) + except TypeError: + raise OperationError(space.w_TypeError, + space.wrap("invalid literal for float()")) + else: + return space.float(args[0]) + else: + raise OperationError(space.w_TypeError, + space.wrap("float() takes at most 1 argument")) + +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/intobject.py Sun Jun 22 16:45:24 2003 @@ -423,7 +423,7 @@ def int_int(space, w_int1): return w_int1 -#?StdObjSpace.int.register(int_int, W_IntObject) +StdObjSpace.int.register(int_int, W_IntObject) def int_long(space, w_int1): a = w_int1.intval @@ -435,9 +435,9 @@ def int_float(space, w_int1): a = w_int1.intval x = float(a) - return space.newdouble(x) + return space.newfloat(x) -#?StdObjSpace.float.register(int_float, W_IntObject) +StdObjSpace.float.register(int_float, W_IntObject) def int_oct(space, w_int1): x = w_int1.intval Modified: pypy/trunk/src/pypy/objspace/std/inttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/inttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/inttype.py Sun Jun 22 16:45:24 2003 @@ -16,7 +16,16 @@ if len(args) == 0: return space.newint(0) elif len(args) == 1: - return space.newint(space.unwrap(args[0])) + arg = args[0] + if space.is_true(space.issubtype(space.type(arg), + space.w_str)): + try: + return space.newint(int(space.unwrap(arg))) + except TypeError: + raise OperationError(space.w_TypeError, + space.wrap("invalid literal for int()")) + else: + return space.int(args[0]) else: raise OperationError(space.w_TypeError, space.wrap("int() takes at most 1 argument")) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Sun Jun 22 16:45:24 2003 @@ -228,6 +228,10 @@ import intobject return intobject.W_IntObject(self, int_w) + def newfloat(self, int_w): + import floatobject + return floatobject.W_FloatObject(self, int_w) + def newtuple(self, list_w): import tupleobject return tupleobject.W_TupleObject(self, list_w) Added: pypy/trunk/src/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/test/test_floatobject.py Sun Jun 22 16:45:24 2003 @@ -0,0 +1,17 @@ +import autopath +from pypy.tool import test + +class FloatTestCase(test.AppTestCase): + def test_float_callable(self): + self.assertEquals(0.125, float(0.125)) + + def test_float_int(self): + self.assertEquals(42.0, float(42)) + + def test_float_string(self): + self.assertEquals(42.0, float("42")) + + +if __name__ == '__main__': + test.main() + Modified: pypy/trunk/src/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_intobject.py Sun Jun 22 16:45:24 2003 @@ -286,5 +286,16 @@ result = iobj.int_hex(self.space, f1) self.assertEquals(self.space.unwrap(result), hex(x)) +class AppIntTest(test.AppTestCase): + def test_int_callable(self): + self.assertEquals(42, int(42)) + + def test_int_string(self): + self.assertEquals(42, int("42")) + + def test_int_float(self): + self.assertEquals(4, int(4.2)) + + if __name__ == '__main__': test.main() From guenter at codespeak.net Sun Jun 22 17:09:31 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Sun, 22 Jun 2003 17:09:31 +0200 (MEST) Subject: [pypy-svn] rev 954 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622150931.D30975A0B4@thoth.codespeak.net> Author: guenter Date: Sun Jun 22 17:09:31 2003 New Revision: 954 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: String methods count and center implemented Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 17:09:31 2003 @@ -1,3 +1,78 @@ +""" +stringobject.py + +Syopsis of implemented methods (* marks work in progress) + +Py PyPy + + def _is_generic(w_self, fun): + def is_true__String(space, w_str): + def mod__String_ANY(space, w_str, w_item):def mod__String_Tuple(space, w_str, w_tuple):def mod_str_tuple(space, w_format, w_args): + def ord__String(space, w_str): + def string_richcompare(space, w_str1, w_str2, op): + def unwrap__String(space, w_str): +__add__ def add__String_String(space, w_left, w_right): +__class__ +__contains__ +__delattr__ +__doc__ +__eq__ def eq__String_String(space, w_str1, w_str2): +__ge__ def ge__String_String(space, w_str1, w_str2): +__getattribute__ +__getitem__ def getitem__String_Int(space, w_str, w_int): def getitem__String_Slice(space, w_str, w_slice): +__getslice__ +__gt__ def gt__String_String(space, w_str1, w_str2): +__hash__ def hash__String(space, w_str): +__init__ +__le__ def le__String_String(space, w_str1, w_str2): +__len__ def len__String(space, w_str): +__lt__ def lt__String_String(space, w_str1, w_str2): +__mul__ +__ne__ def ne__String_String(space, w_str1, w_str2): +__new__ +__reduce__ +__repr__ def repr__String(space, w_str): +__rmul__ +__setattr__ +__str__ def str__String(space, w_str): +capitalize def str_capitalize__String(space, w_self): +center def str_center__String_Int(space, w_self): +count G?nter def str_count__String_String(space, w_self): +decode !Unicode not supported now +encode !Unicode not supported now +endswith *Guenter +expandtabs *Guenter +find *Tomek +index *Tomek +isalnum def str_isalnum__String(space, w_self): def _isalnum(ch): +isalpha def str_isalpha__String(space, w_self): def _isalpha(ch): +isdigit def str_isdigit__String(space, w_self): def _isdigit(ch): +islower def str_islower__String(space, w_self): def _islower(ch): +isspace def str_isspace__String(space, w_self): def _isspace(ch): +istitle def str_istitle(space, w_self): +isupper def str_isupper__String(space, w_self): def _isupper(ch): +join def str_join__String_ANY(space, w_self, w_list): +ljust def str_ljust__String_ANY(space, w_self, w_arg): +lower +lstrip def str_lstrip__String(space, w_self): +replace *Tomek +rfind *Tomek +rindex *Tomek +rjust def str_rjust__String_ANY(space, w_self, w_arg): +rstrip def str_rstrip__String(space, w_self): +split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): +splitlines +startswith +strip def str_strip__String(space, w_self): +swapcase +title def str_title__String(space, w_self): +translate +upper def str_upper__String(space, w_self): +zfill +""" + + + from pypy.objspace.std.objspace import * from stringtype import W_StringType from intobject import W_IntObject @@ -305,10 +380,8 @@ return space.wrap(u_self[lpos:rpos]) - def str_rstrip__String(space, w_self): - u = space.unwrap - u_self = u(w_self) + u_self = space.unwrap(w_self) rpos = len(u_self) while u_self[rpos - 1] == ' ': @@ -316,19 +389,51 @@ return space.wrap(u_self[:rpos]) - - + def str_lstrip__String(space, w_self): - u = space.unwrap - u_self = u(w_self) + u_self = space.unwrap(w_self) lpos = 0 while u_self[lpos] == ' ': lpos += 1 return space.wrap(u_self[lpos:]) - +def str_center__String_Int(space, w_self, w_arg): + u_self = space.unwrap(w_self) + u_arg = space.unwrap(w_arg) + + d = u_arg - len(u_self) + if d>0: + offset = d//2 + u_centered = offset * ' ' + u_self + (d - offset) * ' ' + else: + u_centered = u_self + + return W_StringObject(space, u_centered) + + +def str_count__String_String(space, w_self, w_arg): + u_self = space.unwrap(w_self) + u_arg = space.unwrap(w_arg) + + count = 0 + if u_arg == "": + count = len(u_self) +1 #as in CPytnon + elif u_self == "": + pass #as in CPython + else: + pos = 0 + while 1: + count += 1 + pos = u_self.find(u_arg, pos+1) + if pos == -1: + break + + + return W_IntObject(space, count) + + def unwrap__String(space, w_str): return w_str._value Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sun Jun 22 17:09:31 2003 @@ -27,6 +27,9 @@ str_strip = MultiMethod('strip', 1) str_rstrip = MultiMethod('rstrip', 1) str_lstrip = MultiMethod('lstrip', 1) + str_center = MultiMethod('center', 2) + str_count = MultiMethod('count', 2) + # XXX we'll worry about the __new__/__init__ distinction later Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sun Jun 22 17:09:31 2003 @@ -161,6 +161,25 @@ self.assertEquals(s.rstrip(), " a b") self.assertEquals(s.lstrip(), "a b ") + def test_center(self): + s="a b" + self.assertEquals(s.center(0), "a b") + self.assertEquals(s.center(1), "a b") + self.assertEquals(s.center(2), "a b") + self.assertEquals(s.center(3), "a b") + self.assertEquals(s.center(4), "a b ") + self.assertEquals(s.center(5), " a b ") + self.assertEquals(s.center(6), " a b ") + self.assertEquals(s.center(7), " a b ") + self.assertEquals(s.center(8), " a b ") + self.assertEquals(s.center(9), " a b ") + + def test_count(self): + self.assertEquals("".count("x"),0) + self.assertEquals("".count(""),1) + self.assertEquals("Python".count(""),7) + self.assertEquals("ab aaba".count("ab"),2) + def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) self.assertEquals(" a ".split(None, 0), ['a ']) From mwh at codespeak.net Sun Jun 22 17:22:00 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 22 Jun 2003 17:22:00 +0200 (MEST) Subject: [pypy-svn] rev 955 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622152200.A55935A0B4@thoth.codespeak.net> Author: mwh Date: Sun Jun 22 17:22:00 2003 New Revision: 955 Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/test/test_userobject.py pypy/trunk/src/pypy/objspace/std/userobject.py Log: support for descriptors defining __set__ Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Sun Jun 22 17:22:00 2003 @@ -98,24 +98,37 @@ # a more declarative way to define attributes would be welcome def object_setattr__ANY_ANY_ANY(space, w_obj, w_attr, w_value): + + # 1) look for descriptor + # 2) if data descriptor, call it + # 3) try to set item in __dict__ + + w_type = space.type(w_obj) if space.is_true(space.eq(w_attr, space.wrap('__class__'))): raise OperationError(space.w_AttributeError, space.wrap("read-only attribute")) + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + + from typeobject import W_TypeObject + if isinstance(w_type, W_TypeObject): + try: + w_descr = w_type.lookup(w_attr) + except KeyError: + pass + else: + if space.is_data_descr(w_descr): + return space.set(w_descr, w_obj, w_value) + try: w_dict = space.getdict(w_obj) except OperationError, e: - # catch TypeError("unsupported type for getdict") - if not e.match(space, space.w_TypeError): + if not e.match(space, space.w_TypeError): # "unsupported type for getdict" raise + raise OperationError(space.w_AttributeError, w_attr) else: - if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): - raise OperationError(space.w_AttributeError, - space.wrap("read-only attribute")) space.setitem(w_dict, w_attr, w_value) - return - - raise OperationError(space.w_AttributeError, w_attr) - def object_delattr__ANY_ANY(space, w_obj, w_attr): if space.is_true(space.eq(w_attr, space.wrap('__class__'))): Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Sun Jun 22 17:22:00 2003 @@ -48,6 +48,26 @@ prop = desc() self.assertEquals(C().prop, 42) + def test_descr_set(self): + class C: + class desc: + def __set__(self, ob, val): + ob.wibble = val + prop = desc() + c = C() + c.prop = 32 + self.assertEquals(c.wibble, 32) + + def dont_test_descr_delete(self): + class C: + class desc: + def __delete__(self, ob): + ob.wibble = 22 + prop = desc() + c = C() + del c.prop + self.assertEquals(c.wibble, 22) + def test_class_setattr(self): class C: pass Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Sun Jun 22 17:22:00 2003 @@ -65,6 +65,12 @@ # XXX check getdict() of the base built-in implementation return w_userobj.w_dict +def is_data_descr__User(space, w_userobj): + try: + space.type(w_userobj).lookup(space.wrap("__set__")) + return 1 + except: + return 0 # register an implementation for all multimethods that define special names def user_specialmethod(space, *args_w): From gvanrossum at codespeak.net Sun Jun 22 17:45:32 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 17:45:32 +0200 (MEST) Subject: [pypy-svn] rev 956 - in pypy/trunk/src/pypy: interpreter objspace/ann objspace/ann/test Message-ID: <20030622154532.769CB5A0B4@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 17:45:31 2003 New Revision: 956 Modified: pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/objspace/ann/cloningcontext.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py pypy/trunk/src/pypy/objspace/ann/wrapper.py Log: We now handle loops!!! Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Sun Jun 22 17:45:31 2003 @@ -313,7 +313,7 @@ class ExitFrame(Exception): """Signals the end of the frame execution. - The argument is the returned or yielded value.""" + The argument is the returned or yielded value, already wrapped.""" class BytecodeCorruption(ValueError): """Detected bytecode corruption. Never caught; it's an error.""" Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Sun Jun 22 17:45:31 2003 @@ -1,6 +1,7 @@ from pypy.interpreter.executioncontext import ExecutionContext -from pypy.interpreter.pyframe import ControlFlowException -from pypy.objspace.ann.wrapper import union +from pypy.interpreter.pyframe import ControlFlowException, ExitFrame +from pypy.objspace.ann.wrapper \ + import union, compatible_frames, unite_frames, W_Anything, W_Constant class IndeterminateCondition(ControlFlowException): @@ -9,33 +10,53 @@ self.w_obj = w_obj def action(self, frame, last_instr): - frame.next_instr = last_instr - f2 = frame.clone() - clones = frame.clones - clones.append(f2) - f2.clones = clones # Share the joy - f2.force_w_obj = self.w_obj - self.w_obj.force = True + frame.next_instr = last_instr # Restart failed opcode (!) + frame.restarting = (self.w_obj, True) # For bytecode_trace() below class CloningExecutionContext(ExecutionContext): + def __init__(self, space): + ExecutionContext.__init__(self, space) + self.knownframes = {} + # {(bytecode, w_globals): (result, clones, {next_instr: [frame, ...], ...}), ...} + + def bytecode_trace(self, frame): + assert isinstance(frame.w_globals, W_Constant) + key = (frame.bytecode, id(frame.w_globals.value)) + result, clones, subdict = self.knownframes[key] + + if frame.restarting is not None: + w_obj, flag = frame.restarting + frame.restarting = None + w_obj.force = flag + if flag: + f2 = frame.clone() + f2.restarting = (w_obj, False) + clones.append(f2) + return + + frames = subdict.setdefault(frame.next_instr, []) + assert len(frames) <= 1 # We think this is true + for f in frames: + if compatible_frames(frame, f): + c1, c2 = unite_frames(frame, f) + if not c2: + # A fixpoint + raise ExitFrame(None) + return + frames.append(frame.clone()) def eval_frame(self, frame): - from pypy.objspace.ann.objspace import W_Anything assert not hasattr(frame, "clones") - space = frame.space - clones = [frame] - frame.clones = clones - frame.force_w_obj = None - result = None # W_Impossible + assert self.space == frame.space + frame.restarting = None + key = (frame.bytecode, id(frame.w_globals.value)) + result, clones, subdict = self.knownframes.setdefault(key, (None, [], {})) + clones.append(frame) while clones: f = clones.pop() - w_obj = f.force_w_obj - if w_obj is not None: - assert w_obj.force == True - w_obj.force = False r = ExecutionContext.eval_frame(self, f) + result, clones, subdict = self.knownframes[key] result = union(result, r) - if isinstance(result, W_Anything): - break + self.knownframes[key] = result, clones, subdict return result Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sun Jun 22 17:45:31 2003 @@ -21,6 +21,7 @@ class AnnotationObjSpace(ObjSpace): def initialize(self): + self.bytecodecache = {} self.w_None = self.wrap(None) self.w_True = self.wrap(True) self.w_False = self.wrap(False) @@ -115,11 +116,40 @@ else: return W_Anything() + def sub(self, w_left, w_right): + try: + left = self.unwrap(w_left) + right = self.unwrap(w_right) + except UnwrapException: + pass + else: + return self.wrap(left - right) + if is_int(w_left) and is_int(w_right): + return W_Integer() + else: + return W_Anything() + + def mul(self, w_left, w_right): + try: + left = self.unwrap(w_left) + right = self.unwrap(w_right) + except UnwrapException: + pass + else: + return self.wrap(left * right) + if is_int(w_left) and is_int(w_right): + return W_Integer() + else: + return W_Anything() + def call(self, w_func, w_args, w_kwds): func = self.unwrap(w_func) # Would be bad it it was W_Anything code = func.func_code - bytecode = PyByteCode() - bytecode._from_code(code) + bytecode = self.bytecodecache.get(code) + if bytecode is None: + bytecode = PyByteCode() + bytecode._from_code(code) + self.bytecodecache[code] = bytecode w_locals = bytecode.build_arguments(self, w_args, w_kwds, Modified: pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Sun Jun 22 17:45:31 2003 @@ -41,6 +41,12 @@ 'f', [self.space.wrap(5), W_Anything()]) self.assertEquals(self.space.unwrap(x), 6) + def test_constplusstr2any(self): + x = self.codetest("def f(i, j):\n" + " return i+j\n", + 'f', [W_Integer(), self.space.wrap(3.5)]) + self.assertEquals(type(x), W_Anything) + def test_int2int(self): x = self.codetest("def f(i):\n" " return i+1\n", @@ -73,7 +79,7 @@ 'f', [W_Integer()]) self.assertEquals(self.space.unwrap(x), 0) - def dont_test_while(self): + def test_while(self): x = self.codetest("def f(i):\n" " while i > 0:\n" " i = i-1\n" @@ -81,8 +87,16 @@ 'f', [W_Integer()]) self.assertEquals(type(x), W_Integer) + def test_factorial(self): + x = self.codetest("def f(i):\n" + " if i > 1:\n" + " return i*f(i-1)\n" + " return 1\n", + 'f', [self.space.wrap(5)]) + self.assertEquals(type(x), W_Integer) + def dont_test_global(self): - # XXX This doesn't work because we don't handle mutating globals + # XXX This will never work, because we don't handle mutating globals x = self.codetest("def f(i, j):\n" " global x\n" " x = i\n" Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Sun Jun 22 17:45:31 2003 @@ -9,23 +9,50 @@ """ class W_Object(object): + """Abstract base class. do not instantiate.""" + def __new__(cls, *args, **kwd): + assert cls is not W_Object + return object.__new__(cls) + def __init__(self): + pass + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, self.argsrepr()) + def argsrepr(self): + return "" + def __eq__(self, other): + return type(other) is type(self) + def __ne__(self, other): + return not self.__eq__(other) + +class W_Undefined(W_Object): + """May be undefined. This is the most contagious type.""" pass class W_Anything(W_Object): + """Any (defined) value. This is the next most contagious type.""" pass class W_Integer(W_Object): + """An integer value (int or long).""" pass class W_Constant(W_Object): + """A specific constant value.""" def __init__(self, value): self.value = value - def __repr__(self): - return '' % self.value + def argsrepr(self): + return repr(self.value)[:50] + def __eq__(self, other): + return type(other) is type(self) and self.value == other.value class W_KnownKeysContainer(W_Object): + """A dict with constant set of keys or a tuple with known length.""" def __init__(self, args_w): self.args_w = args_w + def argsrepr(self): + return repr(self.args_w) + def __eq__(self, other): + return type(other) is type(self) and self.args_w == other.args_w def __len__(self): return len(self.args_w) def __getitem__(self, i): @@ -37,14 +64,99 @@ # XXX Recurse down the values? return W_KnownKeysContainer(args_w) +def unite_frames(f1, f2): + """Given two compatible frames, make them the same. + + This changes both f1 and f2 in-place to change all the values into + their union. It returns two booleans, indicating whether the + frames were changed. + + This requires that the frames are compatible. + + """ + assert compatible_frames(f1, f2) + + # Compare value stacks + # XXX uses stack internals + s1 = f1.valuestack.items + s2 = f2.valuestack.items + c1 = c2 = False # changed flags + n = len(s1) + assert n == len(s2) + for i in range(n): + v1 = s1[i] + v2 = s2[i] + if v1 != v2: + u = union(v1, v2) + if v1 != u: + c1 = True + s1[i] = u + if v2 != u: + c2 = True + s2[i] = u + + # Compare locals + # XXX uses W_KnownKeysContainer internals + assert isinstance(f1.w_locals, W_KnownKeysContainer) + assert isinstance(f2.w_locals, W_KnownKeysContainer) + l1 = f1.w_locals.args_w + l2 = f2.w_locals.args_w + keydict = {} # compute set of keys + for key in l1.iterkeys(): + keydict[key] = 1 + for key in l2.iterkeys(): + keydict[key] = 1 + for key in keydict.iterkeys(): + v1 = l1.get(key, W_Undefined()) + v2 = l2.get(key, W_Undefined()) + u = union(v1, v2) + if v1 != u: + c1 = True + l1[key] = u + if v2 != u: + c2 = True + l2[key] = u + return c1, c2 + +def compatible_frames(f1, f2): + """Return whether two frames are compatible. + + Informally, this means that they represent different states + at the same point in the program. + + """ + if f1 is f2: + return True + return (f1.next_instr == f2.next_instr and + f1.space is f2.space and + f2.bytecode is f2.bytecode and + f1.valuestack.depth() == f2.valuestack.depth() and + equivalent(f1.w_globals, f2.w_globals) and + equivalent(f1.w_builtins, f2.w_builtins) and + f1.blockstack.items == f2.blockstack.items) + +def equivalent(w1, w2): + """Return whether two wrappers are equivalent + + (Helper for compatible_frames.) + + They must be constant wrappers for the same object. + + """ + return (isinstance(w1, W_Constant) and + isinstance(w2, W_Constant) and + w1.value is w2.value) + def union(r1, r2): - # Unite two results + """Return the union of two wrappers.""" if r1 is r2: return r1 if r1 is None: return r2 if r2 is None: return r1 + if isinstance(r1, W_Undefined) or isinstance(r2, W_Undefined): + return W_Undefined() if isinstance(r1, W_Anything) or isinstance(r2, W_Anything): return W_Anything() if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and @@ -61,5 +173,10 @@ return W_Anything() def is_int(w_obj): + """Return whether a wrapped object is an integer. + + It could either be W_Integer or an constant integer. + """ return (isinstance(w_obj, W_Integer) or - isinstance(w_obj, W_Constant) and isinstance(w_obj.value, int)) + (isinstance(w_obj, W_Constant) and + isinstance(w_obj.value, (int, long)))) From anna at codespeak.net Sun Jun 22 18:01:29 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 18:01:29 +0200 (MEST) Subject: [pypy-svn] rev 957 - pypy/trunk/doc Message-ID: <20030622160129.8B2CE5A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 18:01:29 2003 New Revision: 957 Added: pypy/trunk/doc/readme.txt Log: readme for new documentation procedures Added: pypy/trunk/doc/readme.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/readme.txt Sun Jun 22 18:01:29 2003 @@ -0,0 +1,29 @@ +===================== +PyPy Documentation +===================== + +All PyPy documentation has been converted to reST textfiles in the /doc directory. This way, everyone will be notified of new (or updated) documentation. + +To see all documentation, you can browse here: http://codespeak.net/pypy/doc + +Please add new or updated documentation by checking it in to the appropriate directory in subversion: http://codespeak.net/svn/pypy/trunk/doc/. + ++ Remember to run ``svn up`` **before** doing any commit. ++ All filenames should be lowercase, and documentation should be .txt files. ++ Mark-up the documentation with reST so it can generate a pretty html version. ++ A script will automagically generate html pages for the pypy website when you do a commit to the /doc directory. + +*Note* If you don't markup the textfile, it'll still be checked in, but when docutils runs the parser, it'll look ugly on the website. + +You can get more info on reST markup at http://docutils.sourceforge.net/docs/rst/quickref.html + + +Here are some sample textfiles: + ++ ObjectSpace_ ++ ObjectSpaceInterface_ + +--------------------------------------------------------------------------------- + +.. _ObjectSpace: objspace/objspace.txt +.. _ObjectSpaceInterface: objspace/objspaceinterface.txt \ No newline at end of file From gvanrossum at codespeak.net Sun Jun 22 18:02:51 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Sun, 22 Jun 2003 18:02:51 +0200 (MEST) Subject: [pypy-svn] rev 958 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030622160251.22E995A0B4@thoth.codespeak.net> Author: gvanrossum Date: Sun Jun 22 18:02:50 2003 New Revision: 958 Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Log: Introduce a FunctionInfo object. Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Sun Jun 22 18:02:50 2003 @@ -13,17 +13,47 @@ frame.next_instr = last_instr # Restart failed opcode (!) frame.restarting = (self.w_obj, True) # For bytecode_trace() below +class FunctionInfo(object): + + def __init__(self): + self.result = None + self.clones = [] # List of frames + self.knownframes = {} # Mapping from next_instr to list of frames + + def addresult(self, result): + self.result = union(self.result, result) + + def addclone(self, frame): + self.clones.append(frame) + + def addknown(self, frame): + frames = self.knownframes.setdefault(frame.next_instr, []) + frames.append(frame) + assert len(frames) <= 1 # We think this is true + + def iterknown(self, frame): + return iter(self.knownframes.get(frame.next_instr, [])) + + def todo(self): + return len(self.clones) + + def getframe(self): + return self.clones.pop() + + def getresult(self): + return self.result + class CloningExecutionContext(ExecutionContext): def __init__(self, space): ExecutionContext.__init__(self, space) - self.knownframes = {} - # {(bytecode, w_globals): (result, clones, {next_instr: [frame, ...], ...}), ...} + self.functioninfos = {} + # {(bytecode, w_globals): FunctionInfo(), ...} def bytecode_trace(self, frame): assert isinstance(frame.w_globals, W_Constant) key = (frame.bytecode, id(frame.w_globals.value)) - result, clones, subdict = self.knownframes[key] + info = self.functioninfos[key] if frame.restarting is not None: w_obj, flag = frame.restarting @@ -32,31 +62,28 @@ if flag: f2 = frame.clone() f2.restarting = (w_obj, False) - clones.append(f2) + info.addclone(f2) return - frames = subdict.setdefault(frame.next_instr, []) - assert len(frames) <= 1 # We think this is true - for f in frames: + for f in info.iterknown(frame): if compatible_frames(frame, f): c1, c2 = unite_frames(frame, f) if not c2: # A fixpoint raise ExitFrame(None) return - frames.append(frame.clone()) + info.addknown(frame.clone()) def eval_frame(self, frame): - assert not hasattr(frame, "clones") - assert self.space == frame.space + assert self.space is frame.space frame.restarting = None key = (frame.bytecode, id(frame.w_globals.value)) - result, clones, subdict = self.knownframes.setdefault(key, (None, [], {})) - clones.append(frame) - while clones: - f = clones.pop() + info = self.functioninfos.get(key) + if info is None: + self.functioninfos[key] = info = FunctionInfo() + info.addclone(frame) + while info.todo(): + f = info.getframe() r = ExecutionContext.eval_frame(self, f) - result, clones, subdict = self.knownframes[key] - result = union(result, r) - self.knownframes[key] = result, clones, subdict - return result + info.addresult(r) + return info.getresult() From lac at codespeak.net Sun Jun 22 18:05:03 2003 From: lac at codespeak.net (lac at codespeak.net) Date: Sun, 22 Jun 2003 18:05:03 +0200 (MEST) Subject: [pypy-svn] rev 959 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030622160503.27ED85A0B4@thoth.codespeak.net> Author: lac Date: Sun Jun 22 18:05:02 2003 New Revision: 959 Modified: pypy/trunk/src/pypy/objspace/std/test/test_listobject.py Log: Cloned the tuple tests for lists so that gt, eq and friends are tested. In the process we have found an interesting bug, in the lt gt are defined in terms of each other. But hasattr isn't finding them all despite the fact that they are there. Modified: pypy/trunk/src/pypy/objspace/std/test/test_listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_listobject.py Sun Jun 22 18:05:02 2003 @@ -30,20 +30,7 @@ self.assertEqual_w(self.space.len(w_list), w(1)) w_list = W_ListObject(self.space, [w(5), w(3), w(99)]*111) self.assertEqual_w(self.space.len(w_list), w(333)) - - def test_mul(self): - # only testing right mul at the moment - w = self.space.wrap - arg = w(2) - n = 3 - w_lis = W_ListObject(self.space, [arg]) - w_lis3 = W_ListObject(self.space, [arg]*n) - w_res = self.space.mul(w_lis, w(n)) - self.assertEqual_w(w_lis3, w_res) - # commute - w_res = self.space.mul(w(n), w_lis) - self.assertEqual_w(w_lis3, w_res) - + def test_getitem(self): w = self.space.wrap w_list = W_ListObject(self.space, [w(5), w(3)]) @@ -68,6 +55,39 @@ self.assertRaises(NoValue, self.space.next, w_iter) self.assertRaises(NoValue, self.space.next, w_iter) + def test_contains(self): + w = self.space.wrap + w_list = W_ListObject(self.space, [w(5), w(3), w(99)]) + self.assertEqual_w(self.space.contains(w_list, w(5)), + self.space.w_True) + self.assertEqual_w(self.space.contains(w_list, w(99)), + self.space.w_True) + self.assertEqual_w(self.space.contains(w_list, w(11)), + self.space.w_False) + self.assertEqual_w(self.space.contains(w_list, w_list), + self.space.w_False) + + def test_getslice(self): + w = self.space.wrap + + def test1(testlist, start, stop, step, expected): + w_slice = self.space.newslice(w(start), w(stop), w(step)) + w_list = W_ListObject(self.space, [w(i) for i in testlist]) + w_result = self.space.getitem(w_list, w_slice) + self.assertEqual(self.space.unwrap(w_result), expected) + + for testlist in [[], [5,3,99], list(range(5,555,10))]: + for start in [-2, -1, 0, 1, 10]: + for end in [-1, 0, 2, 999]: + test1(testlist, start, end, 1, testlist[start:end]) + + test1([5,7,1,4], 3, 1, -2, [4,]) + test1([5,7,1,4], 3, 0, -2, [4, 7]) + test1([5,7,1,4], 3, -1, -2, []) + test1([5,7,1,4], -2, 11, 2, [1,]) + test1([5,7,1,4], -3, 11, 2, [7, 4]) + test1([5,7,1,4], -5, 11, 2, [5, 1]) + def test_add(self): w = self.space.wrap w_list0 = W_ListObject(self.space, []) @@ -82,6 +102,19 @@ self.assertEqual_w(self.space.add(w_list1, w_list0), w_list1) self.assertEqual_w(self.space.add(w_list0, w_list2), w_list2) + def test_mul(self): + # only testing right mul at the moment + w = self.space.wrap + arg = w(2) + n = 3 + w_lis = W_ListObject(self.space, [arg]) + w_lis3 = W_ListObject(self.space, [arg]*n) + w_res = self.space.mul(w_lis, w(n)) + self.assertEqual_w(w_lis3, w_res) + # commute + w_res = self.space.mul(w(n), w_lis) + self.assertEqual_w(w_lis3, w_res) + def test_getslice(self): # this takes aaagggeeesss!!! w = self.space.wrap @@ -118,6 +151,129 @@ self.assertRaises_w(self.space.w_IndexError, self.space.setitem, w_list, w(-3), w(5)) + def test_eq(self): + w = self.space.wrap + + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + + self.assertEqual_w(self.space.eq(w_list0, w_list1), + self.space.w_False) + self.assertEqual_w(self.space.eq(w_list1, w_list0), + self.space.w_False) + self.assertEqual_w(self.space.eq(w_list1, w_list1), + self.space.w_True) + self.assertEqual_w(self.space.eq(w_list1, w_list2), + self.space.w_True) + self.assertEqual_w(self.space.eq(w_list2, w_list3), + self.space.w_False) + def test_ne(self): + w = self.space.wrap + + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + + self.assertEqual_w(self.space.ne(w_list0, w_list1), + self.space.w_True) + self.assertEqual_w(self.space.ne(w_list1, w_list0), + self.space.w_True) + self.assertEqual_w(self.space.ne(w_list1, w_list1), + self.space.w_False) + self.assertEqual_w(self.space.ne(w_list1, w_list2), + self.space.w_False) + self.assertEqual_w(self.space.ne(w_list2, w_list3), + self.space.w_True) + def test_lt(self): + w = self.space.wrap + + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.lt(w_list0, w_list1), + self.space.w_True) + self.assertEqual_w(self.space.lt(w_list1, w_list0), + self.space.w_False) + self.assertEqual_w(self.space.lt(w_list1, w_list1), + self.space.w_False) + self.assertEqual_w(self.space.lt(w_list1, w_list2), + self.space.w_False) + self.assertEqual_w(self.space.lt(w_list2, w_list3), + self.space.w_True) + self.assertEqual_w(self.space.lt(w_list4, w_list3), + self.space.w_True) + + def test_ge(self): + w = self.space.wrap + + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.ge(w_list0, w_list1), + self.space.w_False) + self.assertEqual_w(self.space.ge(w_list1, w_list0), + self.space.w_True) + self.assertEqual_w(self.space.ge(w_list1, w_list1), + self.space.w_True) + self.assertEqual_w(self.space.ge(w_list1, w_list2), + self.space.w_True) + self.assertEqual_w(self.space.ge(w_list2, w_list3), + self.space.w_False) + self.assertEqual_w(self.space.ge(w_list4, w_list3), + self.space.w_False) + + def test_gt(self): + w = self.space.wrap + + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.gt(w_list0, w_list1), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_list1, w_list0), + self.space.w_True) + self.assertEqual_w(self.space.gt(w_list1, w_list1), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_list1, w_list2), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_list2, w_list3), + self.space.w_False) + self.assertEqual_w(self.space.gt(w_list4, w_list3), + self.space.w_False) + + def test_le(self): + w = self.space.wrap + + w_list0 = W_ListObject(self.space, []) + w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + + self.assertEqual_w(self.space.le(w_list0, w_list1), + self.space.w_True) + self.assertEqual_w(self.space.le(w_list1, w_list0), + self.space.w_False) + self.assertEqual_w(self.space.le(w_list1, w_list1), + self.space.w_True) + self.assertEqual_w(self.space.le(w_list1, w_list2), + self.space.w_True) + self.assertEqual_w(self.space.le(w_list2, w_list3), + self.space.w_True) + self.assertEqual_w(self.space.le(w_list4, w_list3), + self.space.w_True) if __name__ == '__main__': test.main() From hpk at codespeak.net Sun Jun 22 18:59:05 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 18:59:05 +0200 (MEST) Subject: [pypy-svn] rev 960 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030622165905.A32125A0B4@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 18:59:05 2003 New Revision: 960 Modified: pypy/trunk/src/pypy/objspace/std/typetype.py Log: new style registration Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Sun Jun 22 18:59:05 2003 @@ -10,7 +10,7 @@ # XXX we'll worry about the __new__/__init__ distinction later -def typetype_new(space, w_typetype, w_args, w_kwds): +def new__TypeType_ANY_ANY(space, w_typetype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) @@ -26,4 +26,4 @@ raise OperationError(space.w_TypeError, space.wrap("type() takes 1 or 3 arguments")) -StdObjSpace.new.register(typetype_new, W_TypeType, W_ANY, W_ANY) +register_all(vars()) From hpk at codespeak.net Sun Jun 22 19:08:32 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 22 Jun 2003 19:08:32 +0200 (MEST) Subject: [pypy-svn] rev 961 - in pypy/trunk/src/pypy: interpreter interpreter/test objspace/std Message-ID: <20030622170832.CF45D5A0B4@thoth.codespeak.net> Author: hpk Date: Sun Jun 22 19:08:32 2003 New Revision: 961 Modified: pypy/trunk/src/pypy/interpreter/opcode.py pypy/trunk/src/pypy/interpreter/opcode_app.py pypy/trunk/src/pypy/interpreter/pycode.py pypy/trunk/src/pypy/interpreter/pycode_app.py pypy/trunk/src/pypy/interpreter/test/test_interpreter.py pypy/trunk/src/pypy/objspace/std/dictobject.py Log: - implemented NestedScopes together with some tests - added an _appendcell method to W_Dictobject-instances - cleanups Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Sun Jun 22 19:08:32 2003 @@ -442,8 +442,7 @@ # syntactically nested frames? varname = f.getfreevarname(varindex) w_varname = f.space.wrap(varname) - w_value = f.space.gethelper(appfile).call("load_closure", - [f.w_locals, w_varname]) + w_value = f.w_locals.cell(f.space, w_varname) f.valuestack.push(w_value) def LOAD_DEREF(f, varindex): Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode_app.py Sun Jun 22 19:08:32 2003 @@ -125,11 +125,6 @@ except KeyError: raise NameError, "name '"+name+"' is not defined" -def load_closure(locals, name): - # this assumes that 'locals' is an extended dictionary with a - # 'cell' method to explicitely access a cell - return locals.cell(name) - def concatenate_arguments(args, extra_args): return args + tuple(extra_args) Modified: pypy/trunk/src/pypy/interpreter/pycode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode.py Sun Jun 22 19:08:32 2003 @@ -61,9 +61,13 @@ w_bytecode = space.wrap(co) w_arguments = space.gethelper(appfile).call( "decode_code_arguments", [w_arguments, w_kwargs, w_defaults, - w_closure, w_bytecode]) + w_bytecode]) # we assume that decode_code_arguments() gives us a dictionary # of the correct length. + if space.is_true(w_closure): + l = zip(co.co_freevars, space.unpackiterable(w_closure)) + for key,cell in l: + w_arguments._appendcell(space, space.wrap(key), cell) return w_arguments class PyByteCode(PyBaseCode): Modified: pypy/trunk/src/pypy/interpreter/pycode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode_app.py Sun Jun 22 19:08:32 2003 @@ -13,7 +13,7 @@ # (I wonder if the pain of writing this at interpreter level might be # worth it...) -def decode_code_arguments(args, kws, defs, closure, codeobject): +def decode_code_arguments(args, kws, defs, codeobject): """ Assumptions: args = sequence of the normal actual parameters Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Sun Jun 22 19:08:32 2003 @@ -213,6 +213,25 @@ def f(x): return x self.assertEquals(f(666), 666) + def test_nested_scope(self): + x = 42 + def f(): return x + self.assertEquals(f(), 42) + + def test_nested_scope2(self): + x = 42 + y = 3 + def f(): return x + self.assertEquals(f(), 42) + + def test_nested_scope3(self): + x = 42 + def f(): + def g(): + return x + return g + self.assertEquals(f()(), 42) + if __name__ == '__main__': test.main() Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Sun Jun 22 19:08:32 2003 @@ -63,6 +63,12 @@ def cell(self,space,w_lookup): return space.wrap(self._cell(space,w_lookup)) + def _appendcell(self, space, w_lookup, w_cell): + # there should be no w_lookup entry already! + data = self.data + lookup_hash = space.unwrap(space.hash(w_lookup)) + cell = space.unwrap(w_cell) + data.append((w_lookup, lookup_hash, cell)) registerimplementation(W_DictObject) From guenter at codespeak.net Sun Jun 22 19:17:43 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Sun, 22 Jun 2003 19:17:43 +0200 (MEST) Subject: [pypy-svn] rev 962 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622171743.6356D5A0B4@thoth.codespeak.net> Author: guenter Date: Sun Jun 22 19:17:42 2003 New Revision: 962 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: Stringobject methods endswith and expandtabs implemented Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 19:17:42 2003 @@ -1,7 +1,7 @@ """ stringobject.py -Syopsis of implemented methods (* marks work in progress) +Synopsis of implemented methods (* marks work in progress) Py PyPy @@ -31,17 +31,17 @@ __ne__ def ne__String_String(space, w_str1, w_str2): __new__ __reduce__ -__repr__ def repr__String(space, w_str): +__repr__ def repr__String(space, w_str): #fake __rmul__ __setattr__ __str__ def str__String(space, w_str): capitalize def str_capitalize__String(space, w_self): center def str_center__String_Int(space, w_self): -count G?nter def str_count__String_String(space, w_self): +count def str_count__String_String(space, w_self): [optional arguments not supported now] decode !Unicode not supported now encode !Unicode not supported now -endswith *Guenter -expandtabs *Guenter +endswith str_endswith__String_String [optional arguments not supported now] +expandtabs str_expandtabs__String_Int find *Tomek index *Tomek isalnum def str_isalnum__String(space, w_self): def _isalnum(ch): @@ -71,8 +71,6 @@ zfill """ - - from pypy.objspace.std.objspace import * from stringtype import W_StringType from intobject import W_IntObject @@ -412,27 +410,55 @@ return W_StringObject(space, u_centered) - +#[optional arguments not supported now] def str_count__String_String(space, w_self, w_arg): u_self = space.unwrap(w_self) u_arg = space.unwrap(w_arg) count = 0 if u_arg == "": - count = len(u_self) +1 #as in CPytnon + count = len(u_self) +1 #behaves as in Python elif u_self == "": - pass #as in CPython + pass #behaves as in Python else: pos = 0 while 1: count += 1 - pos = u_self.find(u_arg, pos+1) + pos = u_self.find(u_arg, pos+1) #XXX use pypy find if pos == -1: break - return W_IntObject(space, count) + +#[optional arguments not supported now] +def str_endswith__String_String(space, w_self, w_end): + u_self = space.unwrap(w_self) + u_end = space.unwrap(w_end) + found = 0 + if u_end: + endlen = len(u_end) + if endlen <= len(u_self): + found = (u_end == u_self[-endlen:]) + else: + found = 1 + + return W_IntObject(space, found) + +def str_expandtabs__String_Int(space, w_self, w_tabsize): + u_self = space.unwrap(w_self) + u_tabsize = space.unwrap(w_tabsize) + + u_expanded = "" + if u_self: + for token in u_self.split("\t"): #XXX use pypy split + if token: + u_expanded += token + else: + u_expanded += " " * u_tabsize + + return W_StringObject(space, u_expanded) + def unwrap__String(space, w_str): return w_str._value Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sun Jun 22 19:17:42 2003 @@ -28,8 +28,9 @@ str_rstrip = MultiMethod('rstrip', 1) str_lstrip = MultiMethod('lstrip', 1) str_center = MultiMethod('center', 2) - str_count = MultiMethod('count', 2) - + str_count = MultiMethod('count', 2) #[optional arguments not supported now] + str_endswith = MultiMethod('endswith', 2) #[optional arguments not supported now] + str_expandtabs = MultiMethod('expandtabs', 2, defaults=(8,)) # XXX we'll worry about the __new__/__init__ distinction later Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sun Jun 22 19:17:42 2003 @@ -179,7 +179,27 @@ self.assertEquals("".count(""),1) self.assertEquals("Python".count(""),7) self.assertEquals("ab aaba".count("ab"),2) - + + def test_endswith(self): + self.assertEquals('ab'.endswith('ab'),1) + self.assertEquals('ab'.endswith('b'),1) + self.assertEquals('ab'.endswith(''),1) + self.assertEquals('x'.endswith('a'),0) + self.assertEquals('x'.endswith('x'),1) + self.assertEquals(''.endswith(''),1) + self.assertEquals(''.endswith('a'),0) + self.assertEquals('x'.endswith('xx'),0) + self.assertEquals('y'.endswith('xx'),0) + + + def test_expandtabs(self): + s = '\txy\t' + self.assertEquals(s.expandtabs(),' xy ') + self.assertEquals(s.expandtabs(1),' xy ') + self.assertEquals('xy'.expandtabs(),'xy') + self.assertEquals(''.expandtabs(),'') + + def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) self.assertEquals(" a ".split(None, 0), ['a ']) From alex at codespeak.net Sun Jun 22 19:18:48 2003 From: alex at codespeak.net (alex at codespeak.net) Date: Sun, 22 Jun 2003 19:18:48 +0200 (MEST) Subject: [pypy-svn] rev 963 - pypy/trunk/doc Message-ID: <20030622171848.5914A5A0B4@thoth.codespeak.net> Author: alex Date: Sun Jun 22 19:18:48 2003 New Revision: 963 Added: pypy/trunk/doc/pe.txt Log: notes on gvr's chat Added: pypy/trunk/doc/pe.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/pe.txt Sun Jun 22 19:18:48 2003 @@ -0,0 +1,22 @@ +the core idea is: you have the SOS or maybe a subclass of it that +keeps lightweight instrumentation and detects when a function is +heavily used for some definition, when that happens it will +(say for a thread or process on a diff CPU) run the annotating +os for that function, so the SOS might collect info about the +types of arguments for the function already, "it's popular and +often called with 2 int args" so (AI at work) "it's a good idea +to see if we can implement it in C" so the annotating OS is +asked to do symbolic exec and later generate C (how you do the +latter is a different story -. we now build a huge data struct +about what we know about the code at each point during exec, +from that it should be possible to generate C code, currently +we don't record which variable are still alive and which ones +aren't so we'll need to add that). + +So there's a 3rd OS that lets you run functions that have bee +translated to machine code via C, still needs to interact with +the first OS so here having multiple OSs that interact makes +sense, e.g. for calls from C-speed-OS stuff back to occasional +calls to Standard OS (translate the C ints back to Python ints +before you can call the Python code, etc etc) + From alex at codespeak.net Sun Jun 22 19:19:12 2003 From: alex at codespeak.net (alex at codespeak.net) Date: Sun, 22 Jun 2003 19:19:12 +0200 (MEST) Subject: [pypy-svn] rev 964 - pypy/trunk/doc Message-ID: <20030622171912.614D95A0B4@thoth.codespeak.net> Author: alex Date: Sun Jun 22 19:19:12 2003 New Revision: 964 Modified: pypy/trunk/doc/oscon2003-paper.txt Log: notes on gvr's cmts Modified: pypy/trunk/doc/oscon2003-paper.txt ============================================================================== --- pypy/trunk/doc/oscon2003-paper.txt (original) +++ pypy/trunk/doc/oscon2003-paper.txt Sun Jun 22 19:19:12 2003 @@ -359,6 +359,7 @@ argument. For example it should not be stored in a data structure, nor be queried for type, nor be used for another multimethod dispatch -- the only thing you should do is read and write its internal data. +[[FIXME: discuss w/Samuele & Armin]] For example, 'getattr(obj, attr)' is implemented with a W_StringObject second argument when all it needs is just the name of the attr, and From anna at codespeak.net Sun Jun 22 19:51:26 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Sun, 22 Jun 2003 19:51:26 +0200 (MEST) Subject: [pypy-svn] rev 965 - pypy/trunk/doc Message-ID: <20030622175126.E625B5A0B4@thoth.codespeak.net> Author: anna Date: Sun Jun 22 19:51:26 2003 New Revision: 965 Added: pypy/trunk/doc/socialpy.txt Log: social aspects of pypy for OScon paper Added: pypy/trunk/doc/socialpy.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/socialpy.txt Sun Jun 22 19:51:26 2003 @@ -0,0 +1,12 @@ +PyPy: + +Social aspects of PyPy + +PyPy was created in a cooperative process among pythonistas across the world. The first PyPy concepts were developed by who/where? + +The Hildesheim Sprint provided a chance to meet and decide several crucial design considerations. A #pypy irc channel provided communication among participants between sprints. The sourcecode was loaded into subversion and participants given commit rights. + +At the Sprint: +Some folks did lots of handwaving and created really kewl concepts. Other pairs concentrated on coding, testing, builtin functions etc etc. We gathered for goalsetting meetings several times during the sprint, then split up to work on tasks. Much of the work was done by pair programming. Pairs were informal, developing and changing as tasks were discovered and completed. Sprints varied in amount of "discuss as a group" and "just do it" time. We spent lots of intense time together, not just coding but also social time, (meals, spending a day playing tourist, etc), which enhanced the building of relationships and understanding among sprinters. + +Some discoveries: Plan on the first morning for hardware setup and fixing system issues, (wireless is great!) Built-in private time is necessary for the sprint. Whiteboards and projectors are both necessary, as is coffee and tea. Bringing in/providing food is fine but getting people away for lunch is good to clear their minds. Leadership varied throughout the sprints and throughout the day. From tomek at codespeak.net Sun Jun 22 19:53:30 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Sun, 22 Jun 2003 19:53:30 +0200 (MEST) Subject: [pypy-svn] rev 966 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622175330.5068E5A0B4@thoth.codespeak.net> Author: tomek Date: Sun Jun 22 19:53:29 2003 New Revision: 966 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: I added following methods to the string object: lower, index, find, rindex, rfind Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Sun Jun 22 19:53:29 2003 @@ -42,8 +42,8 @@ encode !Unicode not supported now endswith str_endswith__String_String [optional arguments not supported now] expandtabs str_expandtabs__String_Int -find *Tomek -index *Tomek +find OK, nur noch tests +index OK, nur noch tests isalnum def str_isalnum__String(space, w_self): def _isalnum(ch): isalpha def str_isalpha__String(space, w_self): def _isalpha(ch): isdigit def str_isdigit__String(space, w_self): def _isdigit(ch): @@ -53,11 +53,11 @@ isupper def str_isupper__String(space, w_self): def _isupper(ch): join def str_join__String_ANY(space, w_self, w_list): ljust def str_ljust__String_ANY(space, w_self, w_arg): -lower +lower OK lstrip def str_lstrip__String(space, w_self): replace *Tomek -rfind *Tomek -rindex *Tomek +rfind OK, nur noch tests +rindex OK, nur noch tests rjust def str_rjust__String_ANY(space, w_self, w_arg): rstrip def str_rstrip__String(space, w_self): split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): @@ -164,11 +164,25 @@ ch = self[i] if _islower(ch): o = ord(ch) - 32 - buf[i] = chr(o) + res[i] = chr(o) else: - buf[i] = ch + res[i] = ch return space.wrap("".join(res)) + +def str_lower__String(space, w_self): + self = space.unwrap(w_self) + res = [' '] * len(self) + for i in range(len(self)): + ch = self[i] + if _isupper(ch): + o = ord(ch) + 32 + res[i] = chr(o) + else: + res[i] = ch + + return space.wrap("".join(res)) + def str_capitalize__String(space, w_self): input = space.unwrap(w_self) @@ -296,12 +310,12 @@ pos = pos + len(item) else: for i in range(len(self)): - res[i+pos] = item[i] - pos = pos + len(self) - + res[i+pos] = self[i] + pos = pos + len(self) + for i in range(len(item)): res[i+pos] = item[i] - pos = pos + len(item) + pos = pos + len(item) return space.wrap("".join(res)) else: @@ -334,34 +348,86 @@ return space.wrap(u_self) def str_find__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): - start = space.unwrap(w_start) - end = space.unwrap(w_end) - self = space.unwrap(w_self) - sub = space.unwrap(w_sub) + u = space.unwrap + res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), 1) + return space.wrap(res) + +def str_rfind__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): - if start is None: + u = space.unwrap + res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), -1) + return space.wrap(res) + +def str_index__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): + + u = space.unwrap + res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), 1) + if res == -1: + raise OperationError(space.w_ValueError, + space.wrap("substring not found in string.index")) + + return space.wrap(res) + + +def str_rindex__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): + + u = space.unwrap + res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), -1) + if res == -1: + raise OperationError(space.w_ValueError, + space.wrap("substring not found in string.rindex")) + + return space.wrap(res) + + +def _find(self, sub, start, end, dir): + + length = len(self) + + #adjust_indicies + if (end > length): + end = length + elif (end < 0): + end += length + if (end < 0): + end = 0 + if (start < 0): + start += length + if (start < 0): start = 0 - if end is None: - end = self.len + if dir > 0: + if len(sub) == 0 and start < end: + return start + + end = end - len(sub) + 1 + + for i in range(start, end): + match = 1 + for idx in range(len(sub)): + if sub[idx] != self[idx+i]: + match = 0 + break + if match: + return i + return -1 + else: + if len(sub) == 0 and start < end: + return last - maxend = self.len - sub.len + end = end - len(sub) - if end > maxend: - end = maxend + for j in range(end, start+1, -1): + match = 1 + for idx in range(len(sub)): + if sub[idx] != self[idx+j]: + match = 0 + break + if match: + return j + return -1 - if sub.len == 0 and start < end: - return start - - for i in range(start, end): - match = 1 - for idx in range(sub.len): - if not sub[idx] == self[idx+i]: - match = 0 - break - return i - return -1 def str_strip__String(space, w_self): Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Sun Jun 22 19:53:29 2003 @@ -19,11 +19,16 @@ str_ljust = MultiMethod('ljust', 2) str_rjust = MultiMethod('rjust', 2) str_upper = MultiMethod('upper', 1) + str_lower = MultiMethod('lower', 1) str_capitalize = MultiMethod('capitalize', 1) str_title = MultiMethod('title', 1) #XXX we need to have the possibility to specify, if the a parameter #was given - str_find = MultiMethod('find', 4, defaults=(0, 0)) + str_find = MultiMethod('find', 4, defaults=(None, None)) + str_rfind = MultiMethod('rfind', 4, defaults=(None, None)) + str_index = MultiMethod('index', 4, defaults=(None, None)) + str_rindex = MultiMethod('rindex', 4, defaults=(None, None)) + str_strip = MultiMethod('strip', 1) str_rstrip = MultiMethod('rstrip', 1) str_lstrip = MultiMethod('lstrip', 1) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Sun Jun 22 19:53:29 2003 @@ -202,11 +202,24 @@ def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) + self.assertEquals("a/b/c".split("/"), ['a', 'b', 'c']) self.assertEquals(" a ".split(None, 0), ['a ']) self.assertEquals(" a ".split(None, 1), ['a']) self.assertEquals(" a a ".split(" ", 0), [' a a ']) self.assertEquals(" a a ".split(" ", 1), ['', 'a a ']) + def test_join(self): + self.assertEquals(", ".join(['a', 'b', 'c']), "a, b, c") + self.assertEquals("".join([]), "") + self.assertEquals("-".join(['a', 'b']), 'a-b') + + def test_lower(self): + self.assertEquals("aaa AAA".lower(), "aaa aaa") + self.assertEquals("".lower(), "") + + def test_upper(self): + self.assertEquals("aaa AAA".upper(), "AAA AAA") + self.assertEquals("".upper(), "") if __name__ == '__main__': test.main() From tismer at codespeak.net Sun Jun 22 19:58:39 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 22 Jun 2003 19:58:39 +0200 (MEST) Subject: [pypy-svn] rev 967 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030622175839.04B5D5A0B4@thoth.codespeak.net> Author: tismer Date: Sun Jun 22 19:58:39 2003 New Revision: 967 Added: pypy/trunk/src/pypy/objspace/std/dictobject_app.py Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/dicttype.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: implemented missing methods, added tests, all test pass, apparently complete Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Sun Jun 22 19:58:39 2003 @@ -1,8 +1,10 @@ from pypy.objspace.std.objspace import * -from dicttype import W_DictType +from dicttype import W_DictType, _no_object from stringobject import W_StringObject from pypy.interpreter.extmodule import make_builtin_func +applicationfile = StdObjSpace.AppFile(__name__) + class _NoValueInCell: pass class Cell: @@ -157,6 +159,32 @@ return space.newbool(1) else: return space.newbool(0) + +def dict_clear__Dict(space, w_self): + w_self.data = [] + +def dict_update__Dict_Dict(space, w_self, w_other): + w_self.space.gethelper(applicationfile).call("dict_update", [w_self, w_other]) + +def dict_popitem__Dict(space, w_self): + w_item = w_self.space.gethelper(applicationfile).call("dict_popitem", [w_self]) + return w_item + +def dict_get__Dict_ANY_ANY(space, w_self, w_key, w_default): + w_value = w_self.space.gethelper(applicationfile).call("dict_get", [w_self, w_key, w_default]) + return w_value + +def dict_setdefault__Dict_ANY_ANY(space, w_self, w_key, w_default): + w_value = w_self.space.gethelper(applicationfile).call("dict_setdefault", [w_self, w_key, w_default]) + return w_value + +def dict_pop__Dict_ANY_ANY(space, w_self, w_key, w_default): + default = space.unwrap(w_default) + if default is _no_object: + w_value = w_self.space.gethelper(applicationfile).call("dict_pop", [w_self, w_key]) + else: + w_value = w_self.space.gethelper(applicationfile).call("dict_pop", [w_self, w_key, w_default]) + return w_value register_all(vars(), W_DictType) Added: pypy/trunk/src/pypy/objspace/std/dictobject_app.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/dictobject_app.py Sun Jun 22 19:58:39 2003 @@ -0,0 +1,32 @@ +#empty + +def dict_update(d,o): + for k in o.keys(): + d[k] = o[k] + +def dict_popitem(d): + k = d.keys()[0] + v = d[k] + del d[k] + return k, v + +def dict_get(d, k, v=None): + if d.has_key(k): + return d[k] + return v + +def dict_setdefault(d, k, v): + if d.has_key(k): + return d[k] + d[k] = v + return v + +class __unique: pass + +def dict_pop(d, k, v=__unique): + if d.has_key(k): + v = d[k] + del d[k] + if v is __unique: + raise KeyError, k + return v Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Sun Jun 22 19:58:39 2003 @@ -1,13 +1,24 @@ from pypy.objspace.std.objspace import * from typeobject import W_TypeObject +class _no_object: pass class W_DictType(W_TypeObject): typename = 'dict' - dict_copy = MultiMethod('copy', 1) - dict_items = MultiMethod('items', 1) - dict_keys = MultiMethod('keys', 1) - dict_values = MultiMethod('values', 1) - dict_has_key = MultiMethod('has_key', 2) + dict_copy = MultiMethod('copy', 1) + dict_items = MultiMethod('items', 1) + dict_keys = MultiMethod('keys', 1) + dict_values = MultiMethod('values', 1) + dict_has_key = MultiMethod('has_key', 2) + dict_clear = MultiMethod('clear', 1) + dict_get = MultiMethod('get', 3, defaults=(None,)) + dict_pop = MultiMethod('pop', 3, defaults=(_no_object,)) + dict_popitem = MultiMethod('popitem', 1) + dict_setdefault = MultiMethod('setdefault', 3) + dict_update = MultiMethod('update', 2) + dict_iteritems = MultiMethod('iteritems', 1) + dict_iterkeys = MultiMethod('iterkeys', 1) + dict_itervalues = MultiMethod('itervalues', 1) + Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Sun Jun 22 19:58:39 2003 @@ -78,6 +78,105 @@ self.assertNotEqual_w(wd1, wd4) wd5 = self.space.newdict([(w3, w3)]) self.assertNotEqual_w(wd1, wd4) + +class Test_DictObject(test.AppTestCase): + + + def test_clear(self): + self.d = {1:2, 3:4} + self.d.clear() + self.assertEqual(len(self.d), 0) + + def test_copy(self): + self.d = {1:2, 3:4} + dd = self.d.copy() + self.assertEqual(self.d, dd) + self.failIf(self.d is dd) + + def test_get(self): + self.d = {1:2, 3:4} + self.assertEqual(self.d.get(1), 2) + self.assertEqual(self.d.get(1,44), 2) + self.assertEqual(self.d.get(33), None) + self.assertEqual(self.d.get(33,44), 44) + + def test_pop(self): + self.d = {1:2, 3:4} + dd = self.d.copy() + result = dd.pop(1) + self.assertEqual(result, 2) + self.assertEqual(len(dd), 1) + dd = self.d.copy() + result = dd.pop(1, 44) + self.assertEqual(result, 2) + self.assertEqual(len(dd), 1) + result = dd.pop(1, 44) + self.assertEqual(result, 44) + self.assertEqual(len(dd), 1) + self.assertRaises(KeyError, dd.pop, 33) + + def test_has_key(self): + self.d = {1:2, 3:4} + self.failUnless(self.d.has_key(1)) + self.failIf(self.d.has_key(33)) + + def test_items(self): + self.d = {1:2, 3:4} + its = self.d.items() + its.sort() + self.assertEqual(its, [(1,2),(3,4)]) + + def notyet_test_iteritems(self): + pass + + def notyet_test_iterkeys(self): + pass + + def notyet_test_itervalues(self): + pass + + def test_keys(self): + self.d = {1:2, 3:4} + kys = self.d.keys() + kys.sort() + self.assertEqual(kys, [1,3]) + + def test_popitem(self): + self.d = {1:2, 3:4} + it = self.d.popitem() + self.assertEqual(len(self.d), 1) + self.failUnless(it==(1,2) or it==(3,4)) + it1 = self.d.popitem() + self.assertEqual(len(self.d), 0) + self.failUnless((it!=it1) and (it1==(1,2) or it1==(3,4))) + + def test_setdefault(self): + self.d = {1:2, 3:4} + dd = self.d.copy() + x = dd.setdefault(1, 99) + self.assertEqual(self.d, dd) + self.assertEqual(x, 2) + x = dd.setdefault(33, 99) + self.d[33] = 99 + self.assertEqual(self.d, dd) + self.assertEqual(x, 99) + + def test_update(self): + self.d = {1:2, 3:4} + dd = self.d.copy() + self.d.update({}) + self.assertEqual(self.d, dd) + self.d.update({3:5, 6:7}) + self.assertEqual(self.d, {1:2, 3:5, 6:7}) + + def test_values(self): + self.d = {1:2, 3:4} + vals = self.d.values() + vals.sort() + self.assertEqual(vals, [2,4]) + + + if __name__ == '__main__': From gvanrossum at codespeak.net Mon Jun 23 10:31:27 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 10:31:27 +0200 (MEST) Subject: [pypy-svn] rev 968 - pypy/trunk/src/pypy/interpreter Message-ID: <20030623083127.6CC075A0B4@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 10:31:26 2003 New Revision: 968 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py Log: Don't swallow KeyboardInterrupt in unqualified except clauses. (I had trouble debugging infinite loops.) Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Mon Jun 23 10:31:26 2003 @@ -127,6 +127,8 @@ try: exclst = self.unpackiterable(w_item) check_list.extend(exclst) + except KeyboardInterrupt: + raise except: #w_check_class is not iterable pass @@ -138,7 +140,10 @@ #Match subclasses. try: w_rv = self.issubtype(w_exc_type, w_item) - except: pass + except KeyboardInterrupt: + raise + except: + pass else: if self.is_true(w_rv): return w_rv From gvanrossum at codespeak.net Mon Jun 23 10:32:06 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 10:32:06 +0200 (MEST) Subject: [pypy-svn] rev 969 - pypy/trunk/src/pypy/objspace Message-ID: <20030623083206.D5FA55A0B4@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 10:32:06 2003 New Revision: 969 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: correct spelling errors in method name. Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 23 10:32:06 2003 @@ -11,7 +11,7 @@ class TrivialObjSpace(ObjSpace): - def clone_exception_heirachy(self): + def clone_exception_hierarchy(self): from pypy.interpreter.pycode import PyByteCode def __init__(self, *args): self.args = args @@ -82,7 +82,7 @@ if isinstance(c, types.TypeType): setattr(self, 'w_' + c.__name__, c) newstuff[c.__name__] = c - newstuff.update(self.clone_exception_heirachy()) + newstuff.update(self.clone_exception_hierarchy()) self.make_builtins() self.make_sys() # insert these into the newly-made builtins From gvanrossum at codespeak.net Mon Jun 23 10:32:26 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 10:32:26 +0200 (MEST) Subject: [pypy-svn] rev 970 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623083226.5B2A85A0B4@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 10:32:25 2003 New Revision: 970 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: correct spelling errors in method name. Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Mon Jun 23 10:32:25 2003 @@ -68,7 +68,7 @@ return [value for key, value in result.__dict__.items() if not key.startswith('_')] # don't look - def clone_exception_heirachy(self): + def clone_exception_hierarchy(self): from usertype import W_UserType from funcobject import W_FuncObject from pypy.interpreter.pycode import PyByteCode @@ -171,7 +171,7 @@ for_builtins[typeclass.typename] = w_type # exceptions - for_builtins.update(self.clone_exception_heirachy()) + for_builtins.update(self.clone_exception_hierarchy()) self.make_builtins() self.make_sys() From hpk at codespeak.net Mon Jun 23 10:33:03 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 23 Jun 2003 10:33:03 +0200 (MEST) Subject: [pypy-svn] rev 971 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623083303.7B2655A0B4@thoth.codespeak.net> Author: hpk Date: Mon Jun 23 10:33:03 2003 New Revision: 971 Modified: pypy/trunk/src/pypy/objspace/std/dictobject_app.py (contents, props changed) Log: fixeol Modified: pypy/trunk/src/pypy/objspace/std/dictobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject_app.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject_app.py Mon Jun 23 10:33:03 2003 @@ -1,32 +1,32 @@ -#empty - -def dict_update(d,o): - for k in o.keys(): - d[k] = o[k] - -def dict_popitem(d): - k = d.keys()[0] - v = d[k] - del d[k] - return k, v - -def dict_get(d, k, v=None): - if d.has_key(k): - return d[k] - return v - -def dict_setdefault(d, k, v): - if d.has_key(k): - return d[k] - d[k] = v - return v - -class __unique: pass - -def dict_pop(d, k, v=__unique): - if d.has_key(k): - v = d[k] - del d[k] - if v is __unique: - raise KeyError, k - return v +#empty + +def dict_update(d,o): + for k in o.keys(): + d[k] = o[k] + +def dict_popitem(d): + k = d.keys()[0] + v = d[k] + del d[k] + return k, v + +def dict_get(d, k, v=None): + if d.has_key(k): + return d[k] + return v + +def dict_setdefault(d, k, v): + if d.has_key(k): + return d[k] + d[k] = v + return v + +class __unique: pass + +def dict_pop(d, k, v=__unique): + if d.has_key(k): + v = d[k] + del d[k] + if v is __unique: + raise KeyError, k + return v From gvanrossum at codespeak.net Mon Jun 23 10:33:18 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 10:33:18 +0200 (MEST) Subject: [pypy-svn] rev 972 - in pypy/trunk/src/pypy/objspace/ann: . test Message-ID: <20030623083318.A141A5A0B4@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 10:33:18 2003 New Revision: 972 Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Log: Got for loop working!!! Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Mon Jun 23 10:33:18 2003 @@ -32,6 +32,8 @@ if isinstance(c, (types.TypeType, Exception)): setattr(self, 'w_' + c.__name__, self.wrap(c)) self.w_builtins = self.wrap(__builtin__) + # XXX This should be done differently: + self.w_KeyError = self.wrap(KeyError) # Service methods whose interface is in the abstract base class @@ -103,6 +105,15 @@ # Methods implementing Python operations # (Many missing ones are added by make_op() below) + def is_(self, w_left, w_right): + if w_left is w_right: + return self.w_True + if isinstance(w_left, W_Constant) and isinstance(w_right, W_Constant): + # XXX Is this really safe? + if w_left.value is w_right.value: + return self.w_True + return W_Integer() + def add(self, w_left, w_right): try: left = self.unwrap(w_left) @@ -142,9 +153,29 @@ else: return W_Anything() + def iter(self, w_iterable): + if isinstance(w_iterable, W_Constant): + value = w_iterable.value + try: + it = iter(value) + except: + raise OperationError(self.wrap(AttributeError), + self.wrap(AttributeError("__iter__"))) + return W_Anything() + + def next(self, w_iterator): + if hasattr(w_iterator, "force"): + if w_iterator.force: + return W_Anything() + raise NoValue + raise IndeterminateCondition(w_iterator) + def call(self, w_func, w_args, w_kwds): - func = self.unwrap(w_func) # Would be bad it it was W_Anything - code = func.func_code + func = self.unwrap(w_func) # XXX What if this fails? + try: + code = func.func_code + except AttributeError: + return W_Anything() bytecode = self.bytecodecache.get(code) if bytecode is None: bytecode = PyByteCode() Modified: pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Mon Jun 23 10:33:18 2003 @@ -95,6 +95,15 @@ 'f', [self.space.wrap(5)]) self.assertEquals(type(x), W_Integer) + def test_for(self): + x = self.codetest("def f(i):\n" + " for x in range(i):\n" + " i = i-1\n" + " return i\n", + 'f', [W_Integer()]) + self.assertEquals(type(x), W_Integer) + + def dont_test_global(self): # XXX This will never work, because we don't handle mutating globals x = self.codetest("def f(i, j):\n" From mwh at codespeak.net Mon Jun 23 10:36:24 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 10:36:24 +0200 (MEST) Subject: [pypy-svn] rev 973 - pypy/trunk/src/pypy/objspace Message-ID: <20030623083624.DFADF5A0B4@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 10:36:24 2003 New Revision: 973 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: add missing methods Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 23 10:36:24 2003 @@ -346,6 +346,15 @@ def delete(self, descr, ob): descr.__delete__(ob) + def nonzero(self, ob): + return not not ob + + def float(self, ob): + return float(ob) + + def int(self, ob): + return int(ob) + for m in ObjSpace.MethodTable: if not hasattr(TrivialObjSpace, m[0]): print m[0] From guenter at codespeak.net Mon Jun 23 10:43:23 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Mon, 23 Jun 2003 10:43:23 +0200 (MEST) Subject: [pypy-svn] rev 974 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623084323.A4C1D5A0B4@thoth.codespeak.net> Author: guenter Date: Mon Jun 23 10:43:23 2003 New Revision: 974 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: Stringobject method startswith implemented Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 23 10:43:23 2003 @@ -53,7 +53,7 @@ isupper def str_isupper__String(space, w_self): def _isupper(ch): join def str_join__String_ANY(space, w_self, w_list): ljust def str_ljust__String_ANY(space, w_self, w_arg): -lower OK +lower lstrip def str_lstrip__String(space, w_self): replace *Tomek rfind OK, nur noch tests @@ -61,8 +61,8 @@ rjust def str_rjust__String_ANY(space, w_self, w_arg): rstrip def str_rstrip__String(space, w_self): split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): -splitlines -startswith +splitlines *G?nter +startswith *G?nter strip def str_strip__String(space, w_self): swapcase title def str_title__String(space, w_self): @@ -510,6 +510,22 @@ found = 1 return W_IntObject(space, found) + + +#[optional arguments not supported now] +def str_startswith__String_String(space, w_self, w_start): + u_self = space.unwrap(w_self) + u_start = space.unwrap(w_start) + + found = 0 + if u_start: + startlen = len(u_start) + if startlen <= len(u_self): + found = (u_start == u_self[:startlen]) + else: + found = 1 + + return W_IntObject(space, found) def str_expandtabs__String_Int(space, w_self, w_tabsize): u_self = space.unwrap(w_self) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Mon Jun 23 10:43:23 2003 @@ -36,6 +36,8 @@ str_count = MultiMethod('count', 2) #[optional arguments not supported now] str_endswith = MultiMethod('endswith', 2) #[optional arguments not supported now] str_expandtabs = MultiMethod('expandtabs', 2, defaults=(8,)) + str_splitlines = MultiMethod('splitlines', 2) + str_startswith = MultiMethod('startswith', 2) #[optional arguments not supported now] # XXX we'll worry about the __new__/__init__ distinction later Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Mon Jun 23 10:43:23 2003 @@ -180,6 +180,19 @@ self.assertEquals("Python".count(""),7) self.assertEquals("ab aaba".count("ab"),2) + + def test_startswith(self): + self.assertEquals('ab'.startswith('ab'),1) + self.assertEquals('ab'.startswith('a'),1) + self.assertEquals('ab'.startswith(''),1) + self.assertEquals('x'.startswith('a'),0) + self.assertEquals('x'.startswith('x'),1) + self.assertEquals(''.startswith(''),1) + self.assertEquals(''.startswith('a'),0) + self.assertEquals('x'.startswith('xx'),0) + self.assertEquals('y'.startswith('xx'),0) + + def test_endswith(self): self.assertEquals('ab'.endswith('ab'),1) self.assertEquals('ab'.endswith('b'),1) @@ -191,7 +204,7 @@ self.assertEquals('x'.endswith('xx'),0) self.assertEquals('y'.endswith('xx'),0) - + def test_expandtabs(self): s = '\txy\t' self.assertEquals(s.expandtabs(),' xy ') From tomek at codespeak.net Mon Jun 23 11:07:32 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Mon, 23 Jun 2003 11:07:32 +0200 (MEST) Subject: [pypy-svn] rev 975 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623090732.B4C2F5A0B4@thoth.codespeak.net> Author: tomek Date: Mon Jun 23 11:07:32 2003 New Revision: 975 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: I added swapcase to stringobject Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 23 11:07:32 2003 @@ -53,7 +53,7 @@ isupper def str_isupper__String(space, w_self): def _isupper(ch): join def str_join__String_ANY(space, w_self, w_list): ljust def str_ljust__String_ANY(space, w_self, w_arg): -lower +lower OK lstrip def str_lstrip__String(space, w_self): replace *Tomek rfind OK, nur noch tests @@ -64,7 +64,7 @@ splitlines *G?nter startswith *G?nter strip def str_strip__String(space, w_self): -swapcase +swapcase OK title def str_title__String(space, w_self): translate upper def str_upper__String(space, w_self): @@ -183,6 +183,22 @@ return space.wrap("".join(res)) +def str_swapcase__String(space, w_self): + self = space.unwrap(w_self) + res = [' '] * len(self) + for i in range(len(self)): + ch = self[i] + if _isupper(ch): + o = ord(ch) + 32 + res[i] = chr(o) + elif _islower(ch): + o = ord(ch) - 32 + res[i] = chr(o) + else: + res[i] = ch + + return space.wrap("".join(res)) + def str_capitalize__String(space, w_self): input = space.unwrap(w_self) @@ -262,7 +278,9 @@ splitcount = maxsplit while splitcount: - next = value.find(by, start) + next = _find(value, by, start, len(value), 1) + #next = value.find(by, start) #of course we cannot use + #the find method, if next < 0: res.append(value[start:]) start = len(value) + 1 Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Mon Jun 23 11:07:32 2003 @@ -20,6 +20,7 @@ str_rjust = MultiMethod('rjust', 2) str_upper = MultiMethod('upper', 1) str_lower = MultiMethod('lower', 1) + str_swapcase = MultiMethod('swapcase', 1) str_capitalize = MultiMethod('capitalize', 1) str_title = MultiMethod('title', 1) #XXX we need to have the possibility to specify, if the a parameter Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Mon Jun 23 11:07:32 2003 @@ -233,6 +233,10 @@ def test_upper(self): self.assertEquals("aaa AAA".upper(), "AAA AAA") self.assertEquals("".upper(), "") + + def test_swapcase(self): + self.assertEquals("aaa AAA 111".swapcase(), "AAA aaa 111") + self.assertEquals("".swapcase(), "") if __name__ == '__main__': test.main() From pedronis at codespeak.net Mon Jun 23 11:12:42 2003 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 23 Jun 2003 11:12:42 +0200 (MEST) Subject: [pypy-svn] rev 976 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623091242.4AFE75A0B4@thoth.codespeak.net> Author: pedronis Date: Mon Jun 23 11:12:41 2003 New Revision: 976 Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py Log: start separating structural hierarchy from (multi)dispatch hierarchy Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Mon Jun 23 11:12:41 2003 @@ -26,6 +26,17 @@ # one may be automatically registered in the other one to keep # them in sync. +# for dispatching use the result of these functions instead of directly +# using .__class__ + +def dispatchtype(obj): + try: + return obj.dispatchtype + except AttributeError: + return obj.__class__ + +def todispatchtype(cls): + return getattr(cls,'dispatchtype',cls) class AbstractMultiMethod(object): """Abstract base class for MultiMethod and UnboundMultiMethod @@ -95,7 +106,7 @@ self.unbound_versions = {} def __get__(self, space, cls=object): - if issubclass(cls, self.BASE_TYPE_OBJECT): + if issubclass(todispatchtype(cls), self.BASE_TYPE_OBJECT): return self.slice(cls).get(space) elif space is None: return self # hack for "StdObjSpace.xyz" returning xyz @@ -213,7 +224,7 @@ if e.args: raise OperationError(*e.args) else: - initialtypes = [a.__class__ + initialtypes = [dispatchtype(a) for a in args[:self.multimethod.arity]] if len(initialtypes) <= 1: plural = "" @@ -232,13 +243,13 @@ if self.ASSERT_BASE_TYPE: for a in args[:arity]: - assert isinstance(a, self.ASSERT_BASE_TYPE), ( + assert issubclass(dispatchtype(a), self.ASSERT_BASE_TYPE), ( "multimethod '%s' call with non wrapped argument: %r" % (self.multimethod.operatorsymbol, a)) # look for an exact match first firstfailure = None - types = tuple([(a.__class__,) for a in args]) + types = tuple([(dispatchtype(a),) for a in args]) choicelist = self.multimethod.buildchoices(types) for signature, function in choicelist: try: @@ -276,7 +287,8 @@ else: converted = function(self.space, curobjs[t]) if not isinstance(converted, list): - converted = [(converted.__class__, converted)] + converted = [(dispatchtype(converted), + converted)] for t, a in converted: if t not in curobjs: curtypes += (t,) From gvanrossum at codespeak.net Mon Jun 23 11:14:16 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 11:14:16 +0200 (MEST) Subject: [pypy-svn] rev 977 - in pypy/trunk/src/pypy: interpreter objspace/ann Message-ID: <20030623091416.E381C5A0B4@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 11:14:16 2003 New Revision: 977 Modified: pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/objspace/ann/cloningcontext.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/wrapper.py Log: Wnen IndeterminateCondition is raised, don't reuse the frame; throw it away and create two clones of the pristine frame saved at the start of the current instruction. M interpreter\pyframe.py change signature of action() to add execution context M objspace\ann\cloningcontext.py move IndeterminateCondition exception to after FunctionInfo class list of clones changed to list of (next_instr, w_obj, force) tuples other changes needed to implement what we want M objspace\ann\objspace.py force attribute is always there, None if not forcing anything M objspace\ann\wrapper.py add default None for force attribute; add some whitespace Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Mon Jun 23 11:14:16 2003 @@ -71,7 +71,7 @@ except ControlFlowException, ctlflowexc: # we have a reason to change the control flow # (typically unroll the stack) - ctlflowexc.action(self, last_instr) + ctlflowexc.action(self, last_instr, executioncontext) except ExitFrame, e: # leave that frame @@ -262,7 +262,7 @@ WHY_YIELD SYieldValue """ - def action(self, frame, last_instr): + def action(self, frame, last_instr, executioncontext): "Default unroller implementation." try: while not frame.blockstack.empty(): @@ -303,7 +303,7 @@ class SYieldValue(ControlFlowException): """Signals a 'yield' statement. Argument is the wrapped object to return.""" - def action(self, frame, last_instr): + def action(self, frame, last_instr, executioncontext): # XXX generators raise OperationError(frame.space.w_Exception, frame.space.wrap("generators are not ready yet")) Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Mon Jun 23 11:14:16 2003 @@ -3,28 +3,28 @@ from pypy.objspace.ann.wrapper \ import union, compatible_frames, unite_frames, W_Anything, W_Constant -class IndeterminateCondition(ControlFlowException): - - def __init__(self, w_obj): - ControlFlowException.__init__(self) - self.w_obj = w_obj - - def action(self, frame, last_instr): - frame.next_instr = last_instr # Restart failed opcode (!) - frame.restarting = (self.w_obj, True) # For bytecode_trace() below - class FunctionInfo(object): def __init__(self): self.result = None - self.clones = [] # List of frames + self.clones = [] # List of (next_instr, w_obj, force) tuples self.knownframes = {} # Mapping from next_instr to list of frames def addresult(self, result): self.result = union(self.result, result) - def addclone(self, frame): - self.clones.append(frame) + def addclone(self, next_instr, w_obj, force): + self.clones.append((next_instr, w_obj, force)) + + def getframe(self): + if not self.clones: + return None + next_instr, w_obj, force = self.clones.pop() + frames = self.knownframes[next_instr] + assert len(frames) == 1 + f = frames[0].clone() + f.restarting = (w_obj, force) + return f def addknown(self, frame): frames = self.knownframes.setdefault(frame.next_instr, []) @@ -34,15 +34,22 @@ def iterknown(self, frame): return iter(self.knownframes.get(frame.next_instr, [])) - def todo(self): - return len(self.clones) - - def getframe(self): - return self.clones.pop() - def getresult(self): return self.result +class IndeterminateCondition(ControlFlowException): + + def __init__(self, w_obj): + ControlFlowException.__init__(self) + self.w_obj = w_obj + + def action(self, frame, last_instr, context): + info = context.getfunctioninfo(frame) + info.addclone(last_instr, self.w_obj, True) + info.addclone(last_instr, self.w_obj, False) + # Abandon this frame; the two clones will take over + raise ExitFrame(None) + class CloningExecutionContext(ExecutionContext): def __init__(self, space): @@ -50,26 +57,29 @@ self.functioninfos = {} # {(bytecode, w_globals): FunctionInfo(), ...} - def bytecode_trace(self, frame): + def getfunctioninfo(self, frame, new=False): assert isinstance(frame.w_globals, W_Constant) key = (frame.bytecode, id(frame.w_globals.value)) - info = self.functioninfos[key] + info = self.functioninfos.get(key) + if info is None: + if not new: + raise KeyError, repr(key) + self.functioninfos[key] = info = FunctionInfo() + return info + def bytecode_trace(self, frame): if frame.restarting is not None: w_obj, flag = frame.restarting frame.restarting = None w_obj.force = flag - if flag: - f2 = frame.clone() - f2.restarting = (w_obj, False) - info.addclone(f2) return + info = self.getfunctioninfo(frame) for f in info.iterknown(frame): if compatible_frames(frame, f): c1, c2 = unite_frames(frame, f) if not c2: - # A fixpoint + # A fixpoint; abandon this frame raise ExitFrame(None) return info.addknown(frame.clone()) @@ -77,13 +87,9 @@ def eval_frame(self, frame): assert self.space is frame.space frame.restarting = None - key = (frame.bytecode, id(frame.w_globals.value)) - info = self.functioninfos.get(key) - if info is None: - self.functioninfos[key] = info = FunctionInfo() - info.addclone(frame) - while info.todo(): - f = info.getframe() - r = ExecutionContext.eval_frame(self, f) - info.addresult(r) + info = self.getfunctioninfo(frame, True) + while frame is not None: + result = ExecutionContext.eval_frame(self, frame) + info.addresult(result) + frame = info.getframe() return info.getresult() Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Mon Jun 23 11:14:16 2003 @@ -53,8 +53,10 @@ raise OperationError(self.wrap(t), self.wrap(v)) def is_true(self, w_obj): - if hasattr(w_obj, "force"): - return w_obj.force # Forced by cloning machinery + if w_obj.force is not None: + force = w_obj.force + w_obj.force = None + return force # Forced by cloning machinery if isinstance(w_obj, W_KnownKeysContainer): return bool(len(w_obj)) try: @@ -164,10 +166,13 @@ return W_Anything() def next(self, w_iterator): - if hasattr(w_iterator, "force"): - if w_iterator.force: + if w_iterator.force is not None: + force = w_iterator.force + w_iterator.force = None + if force: return W_Anything() - raise NoValue + else: + raise NoValue raise IndeterminateCondition(w_iterator) def call(self, w_func, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Mon Jun 23 11:14:16 2003 @@ -10,17 +10,25 @@ class W_Object(object): """Abstract base class. do not instantiate.""" + + force = None # See cloningcontext.py + def __new__(cls, *args, **kwd): assert cls is not W_Object return object.__new__(cls) + def __init__(self): pass + def __repr__(self): return "%s(%s)" % (self.__class__.__name__, self.argsrepr()) + def argsrepr(self): return "" + def __eq__(self, other): return type(other) is type(self) + def __ne__(self, other): return not self.__eq__(other) @@ -38,25 +46,34 @@ class W_Constant(W_Object): """A specific constant value.""" + def __init__(self, value): self.value = value + def argsrepr(self): return repr(self.value)[:50] + def __eq__(self, other): return type(other) is type(self) and self.value == other.value class W_KnownKeysContainer(W_Object): """A dict with constant set of keys or a tuple with known length.""" + def __init__(self, args_w): self.args_w = args_w + def argsrepr(self): return repr(self.args_w) + def __eq__(self, other): return type(other) is type(self) and self.args_w == other.args_w + def __len__(self): return len(self.args_w) + def __getitem__(self, i): return self.args_w[i] + def clone(self): args_w = self.args_w if isinstance(args_w, dict): From pedronis at codespeak.net Mon Jun 23 11:59:21 2003 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 23 Jun 2003 11:59:21 +0200 (MEST) Subject: [pypy-svn] rev 978 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623095921.55A0C5A0B4@thoth.codespeak.net> Author: pedronis Date: Mon Jun 23 11:59:20 2003 New Revision: 978 Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py Log: get of multimethod is on W_xxxType objs Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Mon Jun 23 11:59:20 2003 @@ -26,7 +26,7 @@ # one may be automatically registered in the other one to keep # them in sync. -# for dispatching use the result of these functions instead of directly +# for dispatching use the result of this function instead of directly # using .__class__ def dispatchtype(obj): @@ -35,8 +35,8 @@ except AttributeError: return obj.__class__ -def todispatchtype(cls): - return getattr(cls,'dispatchtype',cls) +##def todispatchtype(cls): +## return getattr(cls,'dispatchtype',cls) class AbstractMultiMethod(object): """Abstract base class for MultiMethod and UnboundMultiMethod @@ -105,8 +105,8 @@ self.defaults = defaults self.unbound_versions = {} - def __get__(self, space, cls=object): - if issubclass(todispatchtype(cls), self.BASE_TYPE_OBJECT): + def __get__(self, space, cls=object): # cls is some W_xxxType + if issubclass(cls, self.BASE_TYPE_OBJECT): return self.slice(cls).get(space) elif space is None: return self # hack for "StdObjSpace.xyz" returning xyz From tomek at codespeak.net Mon Jun 23 13:05:41 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Mon, 23 Jun 2003 13:05:41 +0200 (MEST) Subject: [pypy-svn] rev 979 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623110541.6F4BD5A0B4@thoth.codespeak.net> Author: tomek Date: Mon Jun 23 13:05:40 2003 New Revision: 979 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: I added some string tests stolen from CPython, and fixed some errors found by them :-) Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 23 13:05:40 2003 @@ -208,8 +208,17 @@ if _islower(ch): o = ord(ch) - 32 buffer[0] = chr(o) + else: + buffer[0] = ch + for i in range(1, len(input)): - buffer[i] = input[i] + ch = input[i] + if _isupper(ch): + o = ord(ch) + 32 + buffer[i] = chr(o) + else: + buffer[i] = ch + return space.wrap("".join(buffer)) def str_title__String(space, w_self): @@ -365,22 +374,37 @@ return space.wrap(u_self) -def str_find__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): +def _convert_idx_params(space, w_self, w_sub, w_start, w_end): + u = space.unwrap + start = u(w_start) + end = u(w_end) + self = u(w_self) + sub = u(w_sub) + if start is None: + start = 0 + if end is None: + end = len(self) + + return (self, sub, start, end) + - u = space.unwrap - res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), 1) +def str_find__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None): + + (self, sub, start, end) = _convert_idx_params(space, w_self, w_sub, w_start, w_end) + res = _find(self, sub, start, end, 1) return space.wrap(res) -def str_rfind__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): +def str_rfind__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None): - u = space.unwrap - res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), -1) + (self, sub, start, end) = _convert_idx_params(space, w_self, w_sub, w_start, w_end) + res = _find(self, sub, start, end, -1) return space.wrap(res) -def str_index__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): +def str_index__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None): + + (self, sub, start, end) = _convert_idx_params(space, w_self, w_sub, w_start, w_end) + res = _find(self, sub, start, end, 1) - u = space.unwrap - res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), 1) if res == -1: raise OperationError(space.w_ValueError, space.wrap("substring not found in string.index")) @@ -388,10 +412,10 @@ return space.wrap(res) -def str_rindex__String_String_Int_Int(space, w_self, w_sub, w_start=None, w_end=None): +def str_rindex__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None): - u = space.unwrap - res = _find(u(w_self), u(w_sub), u(w_start), u(w_end), -1) + (self, sub, start, end) = _convert_idx_params(space, w_self, w_sub, w_start, w_end) + res = _find(self, sub, start, end, -1) if res == -1: raise OperationError(space.w_ValueError, space.wrap("substring not found in string.rindex")) @@ -432,11 +456,11 @@ return -1 else: if len(sub) == 0 and start < end: - return last + return end end = end - len(sub) - for j in range(end, start+1, -1): + for j in range(end, start-1, -1): match = 1 for idx in range(len(sub)): if sub[idx] != self[idx+j]: Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Mon Jun 23 13:05:40 2003 @@ -131,6 +131,19 @@ self.assertEquals("a".split(), ['a']) self.assertEquals(" a ".split(), ['a']) self.assertEquals("a b c".split(), ['a','b','c']) + self.assertEquals('this is the split function'.split(), ['this', 'is', 'the', 'split', 'function']) + self.assertEquals('a|b|c|d'.split('|'), ['a', 'b', 'c', 'd']) + self.assertEquals('a|b|c|d'.split('|', 2), ['a', 'b', 'c|d']) + self.assertEquals('a b c d'.split(None, 1), ['a', 'b c d']) + self.assertEquals('a b c d'.split(None, 2), ['a', 'b', 'c d']) + self.assertEquals('a b c d'.split(None, 3), ['a', 'b', 'c', 'd']) + self.assertEquals('a b c d'.split(None, 4), ['a', 'b', 'c', 'd']) + self.assertEquals('a b c d'.split(None, 0), ['a b c d']) + self.assertEquals('a b c d'.split(None, 2), ['a', 'b', 'c d']) + self.assertEquals('a b c d '.split(), ['a', 'b', 'c', 'd']) + self.assertEquals('a//b//c//d'.split('//'), ['a', 'b', 'c', 'd']) + self.assertEquals('endcase test'.split('test'), ['endcase ', '']) + def test_split_splitchar(self): self.assertEquals("/a/b/c".split('/'), ['','a','b','c']) @@ -140,6 +153,11 @@ def test_capitalize(self): self.assertEquals("brown fox".capitalize(), "Brown fox") + self.assertEquals(' hello '.capitalize(), ' hello ') + self.assertEquals('Hello '.capitalize(), 'Hello ') + self.assertEquals('hello '.capitalize(), 'Hello ') + self.assertEquals('aaaa'.capitalize(), 'Aaaa') + self.assertEquals('AaAa'.capitalize(), 'Aaaa') def test_rjust(self): s = "abc" @@ -147,6 +165,11 @@ self.assertEquals(s.rjust(3), s) self.assertEquals(s.rjust(4), " " + s) self.assertEquals(s.rjust(5), " " + s) + self.assertEquals('abc'.rjust(10), ' abc') + self.assertEquals('abc'.rjust(6), ' abc') + self.assertEquals('abc'.rjust(3), 'abc') + self.assertEquals('abc'.rjust(2), 'abc') + def test_ljust(self): s = "abc" @@ -154,12 +177,54 @@ self.assertEquals(s.ljust(3), s) self.assertEquals(s.ljust(4), s + " ") self.assertEquals(s.ljust(5), s + " ") + self.assertEquals('abc'.ljust(10), 'abc ') + self.assertEquals('abc'.ljust(6), 'abc ') + self.assertEquals('abc'.ljust(3), 'abc') + self.assertEquals('abc'.ljust(2), 'abc') + + def _test_replace(self): + self.assertEquals('one!two!three!'.replace('!', '@', 1), 'one at two!three!') + self.assertEquals('one!two!three!'.replace('!', ''), 'onetwothree') + self.assertEquals('one!two!three!'.replace('!', '@', 2), 'one at two@three!') + self.assertEquals('one!two!three!'.replace('!', '@', 3), 'one at two@three@') + self.assertEquals('one!two!three!'.replace('!', '@', 4), 'one at two@three@') + self.assertEquals('one!two!three!'.replace('!', '@', 0), 'one!two!three!') + self.assertEquals('one!two!three!'.replace('!', '@'), 'one at two@three@') + self.assertEquals('one!two!three!'.replace('x', '@'), 'one!two!three!') + self.assertEquals('one!two!three!'.replace('x', '@', 2), 'one!two!three!') + self.assertEquals('abc'.replace('', '-'), '-a-b-c-') + self.assertEquals('abc'.replace('', '-', 3), '-a-b-c') + self.assertEquals('abc'.replace('', '-', 0), 'abc') + self.assertEquals(''.replace('', ''), '') + self.assertEquals('abc'.replace('ab', '--', 0), 'abc') + self.assertEquals('abc'.replace('xy', '--'), 'abc') + self.assertEquals('123'.replace('123', ''), '') + self.assertEquals('123123'.replace(123, ''), '') + self.assertEquals('123x123'.replace(123, ''), 'x') - def test_strip(self): + + def _test_strip(self): s = " a b " self.assertEquals(s.strip(), "a b") self.assertEquals(s.rstrip(), " a b") self.assertEquals(s.lstrip(), "a b ") + self.assertEquals('xyzzyhelloxyzzy'.strip('xyz'), 'hello') + self.assertEquals('xyzzyhelloxyzzy'.lstrip('xyz'), 'helloxyzzy') + self.assertEquals('xyzzyhelloxyzzy'.rstrip('xyz'), 'xyzzyhello') + + def _test_zfill(self): + self.assertEquals('123'.zfill(2), '123') + self.assertEquals('123'.zfill(3), '123') + self.assertEquals('123'.zfill(4), '0123') + self.assertEquals('+123'.zfill(3), '+123') + self.assertEquals('+123'.zfill(4), '+123') + self.assertEquals('+123'.zfill(5), '+0123') + self.assertEquals('-123'.zfill(3), '-123') + self.assertEquals('-123'.zfill(4), '-123') + self.assertEquals('-123'.zfill(5), '-0123') + self.assertEquals(''.zfill(3), '000') + self.assertEquals('34'.zfill(1), '34') + self.assertEquals('34'.zfill(4), '0034') def test_center(self): s="a b" @@ -173,12 +238,28 @@ self.assertEquals(s.center(7), " a b ") self.assertEquals(s.center(8), " a b ") self.assertEquals(s.center(9), " a b ") + self.assertEquals('abc'.center(10), ' abc ') + self.assertEquals('abc'.center(6), ' abc ') + self.assertEquals('abc'.center(3), 'abc') + self.assertEquals('abc'.center(2), 'abc') + - def test_count(self): + def _test_count(self): self.assertEquals("".count("x"),0) self.assertEquals("".count(""),1) self.assertEquals("Python".count(""),7) self.assertEquals("ab aaba".count("ab"),2) + self.assertEquals('aaa'.count('a'), 3) + self.assertEquals('aaa'.count('b'), 0) + self.assertEquals('aaa'.count('a'), 3) + self.assertEquals('aaa'.count('b'), 0) + self.assertEquals('aaa'.count('a'), 3) + self.assertEquals('aaa'.count('b'), 0) + self.assertEquals('aaa'.count('b'), 0) + self.assertEquals('aaa'.count('a', -1), 1) + self.assertEquals('aaa'.count('a', -10), 3) + self.assertEquals('aaa'.count('a', 0, -1), 2) + self.assertEquals('aaa'.count('a', 0, -10), 0) def test_startswith(self): @@ -205,12 +286,53 @@ self.assertEquals('y'.endswith('xx'),0) - def test_expandtabs(self): + def _test_expandtabs(self): s = '\txy\t' self.assertEquals(s.expandtabs(),' xy ') self.assertEquals(s.expandtabs(1),' xy ') self.assertEquals('xy'.expandtabs(),'xy') self.assertEquals(''.expandtabs(),'') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(4), 'abc\rab def\ng hi') + self.assertEquals('abc\r\nab\tdef\ng\thi'.expandtabs(4), 'abc\r\nab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') + self.assertEquals('abc\r\nab\r\ndef\ng\r\nhi'.expandtabs(4), 'abc\r\nab\r\ndef\ng\r\nhi') + + def test_find(self): + self.assertEquals('abcdefghiabc'.find('abc'), 0) + self.assertEquals('abcdefghiabc'.find('abc', 1), 9) + self.assertEquals('abcdefghiabc'.find('def', 4), -1) + + def test_index(self): + self.assertEquals('abcdefghiabc'.index(''), 0) + self.assertEquals('abcdefghiabc'.index('def'), 3) + self.assertEquals('abcdefghiabc'.index('abc'), 0) + self.assertEquals('abcdefghiabc'.index('abc', 1), 9) + #XXX it comes UnicodeError + #self.assertRaises(ValueError, 'abcdefghiabc'.index('hib')) + #self.assertRaises(ValueError, 'abcdefghiab'.index('abc', 1)) + #self.assertRaises(ValueError, 'abcdefghi'.index('ghi', 8)) + #self.assertRaises(ValueError, 'abcdefghi'.index('ghi', -1)) + + def test_rfind(self): + self.assertEquals('abcdefghiabc'.rfind('abc'), 9) + self.assertEquals('abcdefghiabc'.rfind(''), 12) + self.assertEquals('abcdefghiabc'.rfind('abcd'), 0) + self.assertEquals('abcdefghiabc'.rfind('abcz'), -1) + + def test_rindex(self): + self.assertEquals('abcdefghiabc'.rindex(''), 12) + self.assertEquals('abcdefghiabc'.rindex('def'), 3) + self.assertEquals('abcdefghiabc'.rindex('abc'), 9) + self.assertEquals('abcdefghiabc'.rindex('abc', 0, -1), 0) + #XXX it comes UnicodeError + #self.assertRaises(ValueError, 'abcdefghiabc'.rindex('hib')) + #self.assertRaises(ValueError, 'defghiabc'.rindex('def', 1)) + #self.assertRaises(ValueError, 'defghiabc'.rindex('abc', 0, -1)) + #self.assertRaises(ValueError, 'abcdefghi'.rindex('ghi', 0, 8)) + #self.assertRaises(ValueError, 'abcdefghi'.rindex('ghi', 0, -1)) def test_split_maxsplit(self): From pedronis at codespeak.net Mon Jun 23 13:24:54 2003 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 23 Jun 2003 13:24:54 +0200 (MEST) Subject: [pypy-svn] rev 980 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623112454.E89F25A0B4@thoth.codespeak.net> Author: pedronis Date: Mon Jun 23 13:24:54 2003 New Revision: 980 Modified: pypy/trunk/src/pypy/objspace/std/userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: make UserObject -> builtin parent type delegation be identity preserving. Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Mon Jun 23 13:24:54 2003 @@ -17,22 +17,44 @@ class.""" statictype = W_UserType - def __init__(w_self, space, w_type, w_args, w_kwds): - # the restriction that a single built-in type is allowed among the - # bases is specific to our W_UserObject implementation of user - # objects, and should thus not be enforced in W_UserType. - # Note: w_type may be any object, not necessarily a W_UserType - # (in case 'type' is subclassed). - - # create an instance of the parent built-in type - w_builtintype = getsinglebuiltintype(space, w_type) - w_self.w_embedded = space.call(w_builtintype, w_args, w_kwds) - w_self.w_type = w_type - w_self.w_dict = space.newdict([]) +def make_user_object(space, w_type, w_args, w_kwds): + # the restriction that a single built-in type is allowed among the + # bases is specific to our W_UserObject implementation of user + # objects, and should thus not be enforced in W_UserType. + # Note: w_type may be any object, not necessarily a W_UserType + # (in case 'type' is subclassed). + + # create an instance of the parent built-in type + w_builtintype = getsinglebuiltintype(space, w_type) + newobj = space.call(w_builtintype, w_args, w_kwds) + + morph_into_user_object(space,w_type,newobj) + + return newobj registerimplementation(W_UserObject) +_bltin_subclass_cache = {} + +def _make_bltin_subclass(cls): + global _bltin_subclass_cache + try: + return _bltin_subclass_cache[cls] + except: + _bltin_subclass_cache[cls] = subcls = type(W_Object)("%s_sub" % cls.__name__,(cls,), + {'statictype': W_UserType, + 'bltbase': cls, + 'dispatchtype': W_UserObject}) + return subcls + +def morph_into_user_object(space,w_type,newobj): + newobj.__class__ = _make_bltin_subclass(newobj.__class__) + newobj.w_type = w_type + if not hasattr(newobj,'w_dict'): + newobj.w_dict = space.newdict([]) + return newobj + def getsinglebuiltintype(space, w_type): "Return the (asserted unique) built-in type that w_type inherits from." @@ -54,7 +76,7 @@ # So far this is the only delegation that produces a result # of a variable type. def delegate__User(space, w_userobj): - return w_userobj.w_embedded + return [(w_userobj.bltbase,w_userobj)] delegate__User.priority = PRIORITY_PARENT_TYPE Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Mon Jun 23 13:24:54 2003 @@ -52,8 +52,8 @@ # The problem is actually that, currently, several types such as # int and float just cannot be CALLED -- this needs to be fixed soon. def new__UserType_ANY_ANY(space, w_usertype, w_args, w_kwds): - from userobject import W_UserObject - newobj = W_UserObject(space, w_usertype, w_args, w_kwds) + from userobject import make_user_object + newobj = make_user_object(space, w_usertype, w_args, w_kwds) try: init = space.getattr(newobj, space.wrap('__init__')) except OperationError, err: From mwh at codespeak.net Mon Jun 23 13:36:58 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 13:36:58 +0200 (MEST) Subject: [pypy-svn] rev 982 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623113658.AD7D25A0B4@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 13:36:58 2003 New Revision: 982 Modified: pypy/trunk/src/pypy/objspace/std/userobject.py Log: a userobject is a data descriptor if it defines __set__ *or* __delete__ Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Mon Jun 23 13:36:58 2003 @@ -90,9 +90,15 @@ def is_data_descr__User(space, w_userobj): try: space.type(w_userobj).lookup(space.wrap("__set__")) - return 1 except: - return 0 + try: + space.type(w_userobj).lookup(space.wrap("__delete__")) + except: + return 0 + else: + return 1 + else: + return 1 # register an implementation for all multimethods that define special names def user_specialmethod(space, *args_w): From mwh at codespeak.net Mon Jun 23 13:37:54 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 13:37:54 +0200 (MEST) Subject: [pypy-svn] rev 983 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623113754.F38265A0B4@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 13:37:54 2003 New Revision: 983 Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Log: polish delattr Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Mon Jun 23 13:37:54 2003 @@ -129,24 +129,42 @@ raise OperationError(space.w_AttributeError, w_attr) else: space.setitem(w_dict, w_attr, w_value) + def object_delattr__ANY_ANY(space, w_obj, w_attr): + w_type = space.type(w_obj) if space.is_true(space.eq(w_attr, space.wrap('__class__'))): raise OperationError(space.w_AttributeError, space.wrap("read-only attribute")) + if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): + raise OperationError(space.w_AttributeError, + space.wrap("read-only attribute")) + + from typeobject import W_TypeObject + if isinstance(w_type, W_TypeObject): + try: + w_descr = w_type.lookup(w_attr) + except KeyError: + pass + else: + #space.type(w_descr).lookup(space.wrap('__delete__')) + if space.is_data_descr(w_descr): + return space.delete(w_descr, w_obj) + try: w_dict = space.getdict(w_obj) except OperationError, e: - # catch TypeError("unsupported type for getdict") - if not e.match(space, space.w_TypeError): + if not e.match(space, space.w_TypeError): # "unsupported type for getdict" raise + raise OperationError(space.w_AttributeError, w_attr) else: - if space.is_true(space.eq(w_attr, space.wrap('__dict__'))): - raise OperationError(space.w_AttributeError, - space.wrap("read-only attribute")) - space.delitem(w_dict, w_attr) - return - + try: + space.delitem(w_dict, w_attr) + except OperationError, e: + if not e.match(space, space.w_KeyError): + raise + raise OperationError(space.w_AttributeError, w_attr) + raise OperationError(space.w_AttributeError, w_attr) Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Mon Jun 23 13:37:54 2003 @@ -58,9 +58,11 @@ c.prop = 32 self.assertEquals(c.wibble, 32) - def dont_test_descr_delete(self): + def test_descr_delete(self): class C: class desc: + def __set__(self, ob, val): + oogabooga def __delete__(self, ob): ob.wibble = 22 prop = desc() From mwh at codespeak.net Mon Jun 23 13:39:37 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 13:39:37 +0200 (MEST) Subject: [pypy-svn] rev 984 - in pypy/trunk/src/pypy: interpreter interpreter/testobjspace objspace/std Message-ID: <20030623113937.45E1E5A0B4@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 13:39:36 2003 New Revision: 984 Added: pypy/trunk/src/pypy/objspace/std/generatorobject.py (contents, props changed) pypy/trunk/src/pypy/objspace/std/generatortype.py (contents, props changed) Modified: pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/interpreter/test/test_interpreter.py pypy/trunk/src/pypy/objspace/std/funcobject.py pypy/trunk/src/pypy/objspace/trivial.py Log: Generators! The wise man will avoid looking too closely at how this works in the trivial object space. Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Mon Jun 23 13:39:36 2003 @@ -1,7 +1,7 @@ """ PyFrame class implementation with the interpreter main loop. """ -from pypy.interpreter.executioncontext import OperationError, Stack +from pypy.interpreter.executioncontext import OperationError, Stack, NoValue from pypy.interpreter.appfile import AppFile appfile = AppFile(__name__, ["interpreter"]) @@ -57,7 +57,6 @@ opcode.dispatch_arg(self, op, oparg) else: opcode.dispatch_noarg(self, op) - except OperationError, e: e.record_application_traceback(self, last_instr) self.last_exception = e @@ -296,7 +295,8 @@ """Signals a 'return' statement. Argument is the wrapped object to return.""" def emptystack(self, frame): - # XXX do something about generators, like throw a NoValue + if frame.bytecode.co_flags & 0x0020:#CO_GENERATOR: + raise NoValue w_returnvalue = self.args[0] raise ExitFrame(w_returnvalue) @@ -304,9 +304,8 @@ """Signals a 'yield' statement. Argument is the wrapped object to return.""" def action(self, frame, last_instr, executioncontext): - # XXX generators - raise OperationError(frame.space.w_Exception, - frame.space.wrap("generators are not ready yet")) + w_returnvalue = self.args[0] + raise ExitFrame(w_returnvalue) class StopUnrolling(Exception): "Signals the end of the block stack unrolling." Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Mon Jun 23 13:39:36 2003 @@ -1,3 +1,4 @@ +from __future__ import generators import autopath from pypy.tool import test @@ -231,6 +232,32 @@ return x return g self.assertEquals(f()(), 42) + + def test_generator(self): + def f(): + yield 1 + self.assertEquals(f().next(), 1) + + def test_generator2(self): + def f(): + yield 1 + g = f() + self.assertEquals(g.next(), 1) + self.assertRaises(StopIteration, g.next) + + def test_generator3(self): + def f(): + yield 1 + g = f() + self.assertEquals(list(g), [1]) + + def test_generator_restart(self): + def g(): + i = me.next() + yield i + me = g() + self.assertRaises(ValueError, me.next) + if __name__ == '__main__': Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Mon Jun 23 13:39:36 2003 @@ -29,13 +29,21 @@ # XXX no closure implemented return proxy_function +CO_GENERATOR = 0x0020 + def call__Func_ANY_ANY(space, w_function, w_arguments, w_keywords): somecode = w_function.code w_globals = w_function.w_globals w_locals = somecode.build_arguments(space, w_arguments, w_keywords, w_defaults = w_function.w_defaultarguments, w_closure = w_function.w_closure) - w_ret = somecode.eval_code(space, w_globals, w_locals) + if somecode.co_flags & CO_GENERATOR: + from generatorobject import W_GeneratorObject + from pypy.interpreter import pyframe + frame = pyframe.PyFrame(space, somecode, w_globals, w_locals) + w_ret = W_GeneratorObject(space, frame) + else: + w_ret = somecode.eval_code(space, w_globals, w_locals) return w_ret def get__Func_ANY_ANY(space, w_function, w_instance, w_cls): Added: pypy/trunk/src/pypy/objspace/std/generatorobject.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/generatorobject.py Mon Jun 23 13:39:36 2003 @@ -0,0 +1,31 @@ +from pypy.objspace.std.objspace import * +from generatortype import W_GeneratorType + +class W_GeneratorObject(W_Object): + statictype = W_GeneratorType + + def __init__(self, space, frame): + self.frame = frame + self.running = 0 + +registerimplementation(W_GeneratorObject) + +def next__Generator(space, w_gen): + if w_gen.running: + raise OperationError(space.w_ValueError, + space.wrap("generator already executing")) + ec = space.getexecutioncontext() + + w_gen.running = 1 + try: + w_ret = ec.eval_frame(w_gen.frame) + finally: + w_gen.running = 0 + + return w_ret + + +def iter__Generator(space, w_gen): + return w_gen + +register_all(vars()) Added: pypy/trunk/src/pypy/objspace/std/generatortype.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/generatortype.py Mon Jun 23 13:39:36 2003 @@ -0,0 +1,7 @@ +from pypy.objspace.std.objspace import * +from typeobject import W_TypeObject + + +class W_GeneratorType(W_TypeObject): + + typename = 'GeneratorType' Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 23 13:39:36 2003 @@ -8,6 +8,55 @@ from pypy.interpreter.baseobjspace import * import operator, types, new, sys +class nugen(object): + def __init__(self, space, frame): + self.space = space + self.frame = frame + self.running = 0 + def next(g_self): + if g_self.running: + raise OperationError(self.w_ValueError, + "generator already executing") + ec = g_self.space.getexecutioncontext() + + g_self.running = 1 + try: + try: + ret = ec.eval_frame(g_self.frame) + except NoValue: + raise StopIteration + finally: + g_self.running = 0 + + return ret + def __iter__(self): + return self + +class nufun(object): + def __init__(self, space, code, globals, defaultarguments, closure): + self.space = space + self.__name__ = code.co_name + self.func_code = self.code = code + self.globals = globals + self.defaultarguments = defaultarguments + self.closure = closure + def do_call(self, *args, **kwds): + locals = self.code.build_arguments(self.space, args, kwds, + w_defaults = self.defaultarguments, + w_closure = self.closure) + if self.code.co_flags & 0x0020: + from pypy.interpreter import pyframe + frame = pyframe.PyFrame(self.space, self.code, + self.globals, locals) + return nugen(self.space, frame) + else: + return self.code.eval_code(self.space, self.globals, locals) + def __call__(self, *args, **kwds): + return self.do_call(*args, **kwds) + def __get__(self, ob, cls=None): + import new + return new.instancemethod(self, ob, cls) + class TrivialObjSpace(ObjSpace): @@ -258,22 +307,6 @@ assert hasattr(code, 'co_name') assert hasattr(code, 'build_arguments') assert hasattr(code, 'eval_code') - class nufun(object): - def __init__(self, space, code, globals, defaultarguments, closure): - self.space = space - self.__name__ = code.co_name - self.func_code = self.code = code - self.globals = globals - self.defaultarguments = defaultarguments - self.closure = closure - def __call__(self, *args, **kwds): - locals = self.code.build_arguments(self.space, args, kwds, - w_defaults = self.defaultarguments, - w_closure = self.closure) - return self.code.eval_code(self.space, self.globals, locals) - def __get__(self, ob, cls=None): - import new - return new.instancemethod(self, ob, cls) return nufun(self, code, globals, defaultarguments, closure) def newstring(self, asciilist): @@ -296,20 +329,14 @@ and callable.im_self is not None): args = (callable.im_self,) + args callable = callable.im_func - if isinstance(callable, types.FunctionType): - raise Exception, "shouldn't get here, methinks" - bytecode = callable.func_code - ec = self.getexecutioncontext() - w_globals = self.wrap(callable.func_globals) - w_defaults = self.wrap(callable.func_defaults) - w_locals = self.newdict([]) - frame = pyframe.PyFrame(self, bytecode, w_globals, w_locals) - # perform call - frame.setargs(args, kwds, w_defaults) - return ec.eval_frame(frame) + if callable == nugen.next.im_func: + try: + return apply(callable, args, kwds or {}) + except: + self.reraise() else: return apply(callable, args, kwds or {}) - + def hex(self, ob): try: return hex(ob) From tismer at codespeak.net Mon Jun 23 13:43:07 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 13:43:07 +0200 (MEST) Subject: [pypy-svn] rev 985 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623114307.582B55A0B4@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 13:43:06 2003 New Revision: 985 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/dictobject_app.py pypy/trunk/src/pypy/objspace/std/dicttype.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: added tests and missing methods, tested, complete (despite order comparison) Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Mon Jun 23 13:43:06 2003 @@ -1,3 +1,10 @@ +""" +Reviewed 03-06-22 +All common dictionary methods are correctly implemented, +tested, and complete. The only missing feature is support +for order comparisons. +""" + from pypy.objspace.std.objspace import * from dicttype import W_DictType, _no_object from stringobject import W_StringObject @@ -185,6 +192,17 @@ else: w_value = w_self.space.gethelper(applicationfile).call("dict_pop", [w_self, w_key, w_default]) return w_value - + +def dict_iteritems__Dict(space, w_self): + w_item = w_self.space.gethelper(applicationfile).call("dict_iteritems", [w_self]) + return w_item + +def dict_iterkeys__Dict(space, w_self): + w_item = w_self.space.gethelper(applicationfile).call("dict_iterkeys", [w_self]) + return w_item + +def dict_itervalues__Dict(space, w_self): + w_item = w_self.space.gethelper(applicationfile).call("dict_itervalues", [w_self]) + return w_item register_all(vars(), W_DictType) Modified: pypy/trunk/src/pypy/objspace/std/dictobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject_app.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject_app.py Mon Jun 23 13:43:06 2003 @@ -1,4 +1,4 @@ -#empty + def dict_update(d,o): for k in o.keys(): @@ -30,3 +30,13 @@ if v is __unique: raise KeyError, k return v + +def dict_iteritems(d): + return iter(d.items()) + +def dict_iterkeys(d): + return iter(d.keys()) + +def dict_itervalues(d): + return iter(d.values()) + Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Mon Jun 23 13:43:06 2003 @@ -1,3 +1,7 @@ +""" +Reviewed 03-06-22 +""" + from pypy.objspace.std.objspace import * from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Mon Jun 23 13:43:06 2003 @@ -83,30 +83,30 @@ def test_clear(self): - self.d = {1:2, 3:4} - self.d.clear() - self.assertEqual(len(self.d), 0) + d = {1:2, 3:4} + d.clear() + self.assertEqual(len(d), 0) def test_copy(self): - self.d = {1:2, 3:4} - dd = self.d.copy() - self.assertEqual(self.d, dd) - self.failIf(self.d is dd) + d = {1:2, 3:4} + dd = d.copy() + self.assertEqual(d, dd) + self.failIf(d is dd) def test_get(self): - self.d = {1:2, 3:4} - self.assertEqual(self.d.get(1), 2) - self.assertEqual(self.d.get(1,44), 2) - self.assertEqual(self.d.get(33), None) - self.assertEqual(self.d.get(33,44), 44) + d = {1:2, 3:4} + self.assertEqual(d.get(1), 2) + self.assertEqual(d.get(1,44), 2) + self.assertEqual(d.get(33), None) + self.assertEqual(d.get(33,44), 44) def test_pop(self): - self.d = {1:2, 3:4} - dd = self.d.copy() + d = {1:2, 3:4} + dd = d.copy() result = dd.pop(1) self.assertEqual(result, 2) self.assertEqual(len(dd), 1) - dd = self.d.copy() + dd = d.copy() result = dd.pop(1, 44) self.assertEqual(result, 2) self.assertEqual(len(dd), 1) @@ -116,68 +116,77 @@ self.assertRaises(KeyError, dd.pop, 33) def test_has_key(self): - self.d = {1:2, 3:4} - self.failUnless(self.d.has_key(1)) - self.failIf(self.d.has_key(33)) + d = {1:2, 3:4} + self.failUnless(d.has_key(1)) + self.failIf(d.has_key(33)) def test_items(self): - self.d = {1:2, 3:4} - its = self.d.items() + d = {1:2, 3:4} + its = d.items() its.sort() self.assertEqual(its, [(1,2),(3,4)]) - def notyet_test_iteritems(self): - pass - - def notyet_test_iterkeys(self): - pass - - def notyet_test_itervalues(self): - pass + def test_iteritems(self): + d = {1:2, 3:4} + dd = d.copy() + for k, v in d.iteritems(): + self.assertEqual(v, dd[k]) + del dd[k] + self.failIf(dd) + + def test_iterkeys(self): + d = {1:2, 3:4} + dd = d.copy() + for k in d.iterkeys(): + del dd[k] + self.failIf(dd) + + def test_itervalues(self): + d = {1:2, 3:4} + values = [] + for k in d.itervalues(): + values.append(k) + self.assertEqual(values, d.values()) def test_keys(self): - self.d = {1:2, 3:4} - kys = self.d.keys() + d = {1:2, 3:4} + kys = d.keys() kys.sort() self.assertEqual(kys, [1,3]) def test_popitem(self): - self.d = {1:2, 3:4} - it = self.d.popitem() - self.assertEqual(len(self.d), 1) + d = {1:2, 3:4} + it = d.popitem() + self.assertEqual(len(d), 1) self.failUnless(it==(1,2) or it==(3,4)) - it1 = self.d.popitem() - self.assertEqual(len(self.d), 0) + it1 = d.popitem() + self.assertEqual(len(d), 0) self.failUnless((it!=it1) and (it1==(1,2) or it1==(3,4))) def test_setdefault(self): - self.d = {1:2, 3:4} - dd = self.d.copy() + d = {1:2, 3:4} + dd = d.copy() x = dd.setdefault(1, 99) - self.assertEqual(self.d, dd) + self.assertEqual(d, dd) self.assertEqual(x, 2) x = dd.setdefault(33, 99) - self.d[33] = 99 - self.assertEqual(self.d, dd) + d[33] = 99 + self.assertEqual(d, dd) self.assertEqual(x, 99) def test_update(self): - self.d = {1:2, 3:4} - dd = self.d.copy() - self.d.update({}) - self.assertEqual(self.d, dd) - self.d.update({3:5, 6:7}) - self.assertEqual(self.d, {1:2, 3:5, 6:7}) + d = {1:2, 3:4} + dd = d.copy() + d.update({}) + self.assertEqual(d, dd) + d.update({3:5, 6:7}) + self.assertEqual(d, {1:2, 3:5, 6:7}) def test_values(self): - self.d = {1:2, 3:4} - vals = self.d.values() + d = {1:2, 3:4} + vals = d.values() vals.sort() self.assertEqual(vals, [2,4]) - - - - if __name__ == '__main__': test.main() From tomek at codespeak.net Mon Jun 23 13:49:40 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Mon, 23 Jun 2003 13:49:40 +0200 (MEST) Subject: [pypy-svn] rev 986 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623114940.4F8C75A0B4@thoth.codespeak.net> Author: tomek Date: Mon Jun 23 13:49:39 2003 New Revision: 986 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: I added zfill method and string x int multiplikation Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 23 13:49:39 2003 @@ -42,8 +42,8 @@ encode !Unicode not supported now endswith str_endswith__String_String [optional arguments not supported now] expandtabs str_expandtabs__String_Int -find OK, nur noch tests -index OK, nur noch tests +find OK +index OK isalnum def str_isalnum__String(space, w_self): def _isalnum(ch): isalpha def str_isalpha__String(space, w_self): def _isalpha(ch): isdigit def str_isdigit__String(space, w_self): def _isdigit(ch): @@ -68,7 +68,7 @@ title def str_title__String(space, w_self): translate upper def str_upper__String(space, w_self): -zfill +zfill *Tomek """ from pypy.objspace.std.objspace import * @@ -582,7 +582,34 @@ u_expanded += " " * u_tabsize return W_StringObject(space, u_expanded) - + +def str_zfill__String_Int(space, w_self, w_width): + u = space.unwrap + input = u(w_self) + width = u(w_width) + + if len(input) >= width: + return w_self + + b = width - len(input) + + buf = [' '] * width + if len(input) > 0 and (input[0] == '+' or input[0] == '-'): + buf[0] = input[0] + start = 1 + middle = width - len(input) + 1 + else: + start = 0 + middle = width - len(input) + + for i in range(start, middle): + buf[i] = '0' + + for i in range(middle, width): + buf[i] = input[start] + start = start + 1 + + return space.wrap("".join(buf)) def unwrap__String(space, w_str): return w_str._value @@ -707,6 +734,21 @@ w_empty = space.newstring([]) return str_join(space, w_empty, w_r) +def mul__String_Int(space, w_str, w_mul): + u = space.unwrap + input = u(w_str) + mul = u(w_mul) + + buffer = [' '] * (mul*len(input)) + + pos = 0 + for i in range(mul): + for j in range(len(input)): + buffer[pos] = input[j] + pos = pos + 1 + + return space.wrap("".join(buffer)) + def add__String_String(space, w_left, w_right): u = space.unwrap right = u(w_right) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Mon Jun 23 13:49:39 2003 @@ -29,6 +29,7 @@ str_rfind = MultiMethod('rfind', 4, defaults=(None, None)) str_index = MultiMethod('index', 4, defaults=(None, None)) str_rindex = MultiMethod('rindex', 4, defaults=(None, None)) + str_zfill = MultiMethod('zfill', 2) str_strip = MultiMethod('strip', 1) str_rstrip = MultiMethod('rstrip', 1) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Mon Jun 23 13:49:39 2003 @@ -212,7 +212,7 @@ self.assertEquals('xyzzyhelloxyzzy'.lstrip('xyz'), 'helloxyzzy') self.assertEquals('xyzzyhelloxyzzy'.rstrip('xyz'), 'xyzzyhello') - def _test_zfill(self): + def test_zfill(self): self.assertEquals('123'.zfill(2), '123') self.assertEquals('123'.zfill(3), '123') self.assertEquals('123'.zfill(4), '0123') From tismer at codespeak.net Mon Jun 23 14:22:25 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 14:22:25 +0200 (MEST) Subject: [pypy-svn] rev 987 - pypy/trunk/doc/sprintinfo Message-ID: <20030623122225.BE08D5A0B4@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 14:22:25 2003 New Revision: 987 Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: dict done Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Mon Jun 23 14:22:25 2003 @@ -21,13 +21,13 @@ alex, christian - boolobject done - cpythonobject done - instmethobject done - longobject done - sliceobject done - userobject done - dictobject + boolobject review done boolobject.py_ + cpythonobject review done + instmethobject review done + longobject review done + sliceobject review done + userobject review done + dictobject review done intobject listobject floatobject @@ -36,7 +36,7 @@ tomek, holger, guenter - moduleobject done + moduleobject review done stringobject noneobject @@ -75,3 +75,6 @@ - discuss funding and future organization issues +--------------------------------------------------------------- + +.. boolobject.py_: http://www.codespeak.net/svn/pypy/trunk/src/pypy/objspace/std/boolobject.py From mwh at codespeak.net Mon Jun 23 15:29:43 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 15:29:43 +0200 (MEST) Subject: [pypy-svn] rev 988 - pypy/trunk/src/pypy/tool Message-ID: <20030623132943.1DD8E5A22F@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 15:29:42 2003 New Revision: 988 Modified: pypy/trunk/src/pypy/tool/option.py Log: fix embarrassing bugs in option handling (multiple -S, -T options) Modified: pypy/trunk/src/pypy/tool/option.py ============================================================================== --- pypy/trunk/src/pypy/tool/option.py (original) +++ pypy/trunk/src/pypy/tool/option.py Mon Jun 23 15:29:42 2003 @@ -31,6 +31,8 @@ return options def process_options(optionlist, input_options, argv=None): + global Options + Options = input_options op = optik.OptionParser() op.add_options(optionlist) options, args = op.parse_args(argv, input_options) @@ -43,7 +45,11 @@ this is configured via the environment variable OBJSPACE """ - name = name or Options.spaces[-1] + if not name: + if hasattr(Options, 'spacename'): + name = Options.spacename + else: + name = Options.spaces[-1] if name == 'std': from pypy.objspace.std import Space elif name == 'trivial': From anna at codespeak.net Mon Jun 23 15:37:33 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 15:37:33 +0200 (MEST) Subject: [pypy-svn] rev 989 - pypy/trunk/doc/sprintinfo Message-ID: <20030623133733.921E65A22F@thoth.codespeak.net> Author: anna Date: Mon Jun 23 15:37:33 2003 New Revision: 989 Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: minor formatting changes Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Mon Jun 23 15:37:33 2003 @@ -21,18 +21,18 @@ alex, christian - boolobject review done boolobject.py_ - cpythonobject review done - instmethobject review done - longobject review done - sliceobject review done - userobject review done - dictobject review done - intobject - listobject - floatobject - iterobject - tupleobject +- boolobject review done boolobject.py_ +- cpythonobject review done +- instmethobject review done +- longobject review done +- sliceobject review done +- userobject review done +- dictobject review done +- intobject +- listobject +- floatobject +- iterobject +- tupleobject tomek, holger, guenter From gvanrossum at codespeak.net Mon Jun 23 15:56:12 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 15:56:12 +0200 (MEST) Subject: [pypy-svn] rev 990 - in pypy/trunk/src/pypy: interpreter interpreter/testobjspace/ann objspace/std Message-ID: <20030623135612.AC7625A243@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 15:56:12 2003 New Revision: 990 Modified: pypy/trunk/src/pypy/interpreter/opcode.py pypy/trunk/src/pypy/interpreter/pycode.py pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/interpreter/test/test_interpreter.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/std/stringobject.py Log: Introduced "almost real" fast locals. A frame has two new attributes, localcells and nestedcells, both of which are fixed-length lists of unwrapped cells, containing wrapped values. (These are not the same cells as the std objspace, although the code was cloned from there.) When a frame is created, the "fast" local variables are copied from w_locals into localcells, and the incoming free cells are copied into nestedcells. There are also helper routines fast2locals() and locals2fast() which move values around. (XXX I think these are not treating missing values correctly in all cases.) All tests pass in both object spaces (except that test_generator_restart() fails in -T; not our fault). M interpreter/opcode.py change FAST and DEREF opcodes to use lists of cells M interpreter/pycode.py cell-related fix in build_arguments; add locals2cells helper to create localcells and nestedcells M interpreter/pyframe.py add fast2locals and locals2fast; add Cell class M interpreter/test/test_interpreter.py added a 4th test for nested scopes M objspace/ann/objspace.py wrap exceptions raised by w_obj[key] (W_KnownKeysContainer) M objspace/std/stringobject.py added Coding cookie (why is there a Latin-1 character in this file?) Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Mon Jun 23 15:56:12 2003 @@ -33,14 +33,12 @@ ## def LOAD_FAST(f, varindex): - varname = f.getlocalvarname(varindex) - w_varname = f.space.wrap(varname) + # access a local variable through its cell object + cell = f.localcells[varindex] try: - w_value = f.space.getitem(f.w_locals, w_varname) - except OperationError, e: - # catch KeyErrors and turn them into UnboundLocalErrors - if not e.match(f.space, f.space.w_KeyError): - raise + w_value = cell.get() + except ValueError: + varname = f.getlocalvarname(varindex) message = "local variable '%s' referenced before assignment" % varname raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message)) f.valuestack.push(w_value) @@ -50,10 +48,9 @@ f.valuestack.push(w_const) def STORE_FAST(f, varindex): - varname = f.getlocalvarname(varindex) - w_varname = f.space.wrap(varname) - w_value = f.valuestack.pop() - f.space.setitem(f.w_locals, w_varname, w_value) + w_newvalue = f.valuestack.pop() + cell = f.localcells[varindex] + cell.set(w_newvalue) def POP_TOP(f): f.valuestack.pop() @@ -291,7 +288,12 @@ w_globals = f.space.getitem(w_tuple,f.space.wrap(1)) w_locals = f.space.getitem(w_tuple,f.space.wrap(2)) + plain = (w_locals is f.w_locals) + if plain: + f.fast2locals() f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals) + if plain: + f.locals2fast() def POP_BLOCK(f): block = f.blockstack.pop() @@ -425,36 +427,27 @@ f.valuestack.push(w_value) def DELETE_FAST(f, varindex): - varname = f.getlocalvarname(varindex) - w_varname = f.space.wrap(varname) + cell = f.localcells[varindex] try: - f.space.delitem(f.w_locals, w_varname) - except OperationError, e: - # catch KeyErrors and turn them into UnboundLocalErrors - if not e.match(f.space, f.space.w_KeyError): - raise + cell.delete() + except ValueError: + varname = f.getlocalvarname(varindex) message = "local variable '%s' referenced before assignment" % varname raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message)) def LOAD_CLOSURE(f, varindex): # nested scopes: access the cell object - # XXX at some point implement an explicit traversal of - # syntactically nested frames? - varname = f.getfreevarname(varindex) - w_varname = f.space.wrap(varname) - w_value = f.w_locals.cell(f.space, w_varname) + cell = f.nestedcells[varindex] + w_value = f.space.wrap(cell) f.valuestack.push(w_value) def LOAD_DEREF(f, varindex): # nested scopes: access a variable through its cell object - varname = f.getfreevarname(varindex) - w_varname = f.space.wrap(varname) + cell = f.nestedcells[varindex] try: - w_value = f.space.getitem(f.w_locals, w_varname) - except OperationError, e: - # catch KeyErrors - if not e.match(f.space, f.space.w_KeyError): - raise + w_value = cell.get() + except ValueError: + varname = f.getfreevarname(varindex) if f.iscellvar(varindex): message = "local variable '%s' referenced before assignment" w_exc_type = f.space.w_UnboundLocalError @@ -467,10 +460,13 @@ def STORE_DEREF(f, varindex): # nested scopes: access a variable through its cell object - varname = f.getfreevarname(varindex) - w_varname = f.space.wrap(varname) w_newvalue = f.valuestack.pop() - f.space.setitem(f.w_locals, w_varname, w_newvalue) + try: + cell = f.nestedcells[varindex] + except IndexError: + import pdb; pdb.set_trace() + raise + cell.set(w_newvalue) def BUILD_TUPLE(f, itemcount): items = [f.valuestack.pop() for i in range(itemcount)] Modified: pypy/trunk/src/pypy/interpreter/pycode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode.py Mon Jun 23 15:56:12 2003 @@ -16,7 +16,7 @@ # look at this if it makes sense # think of a proper base class??? -import baseobjspace, pyframe +import baseobjspace, pyframe, executioncontext import appfile appfile = appfile.AppFile(__name__, ["interpreter"]) @@ -66,8 +66,8 @@ # of the correct length. if space.is_true(w_closure): l = zip(co.co_freevars, space.unpackiterable(w_closure)) - for key,cell in l: - w_arguments._appendcell(space, space.wrap(key), cell) + for key, w_cell in l: + space.setitem(w_arguments, space.wrap(key), w_cell) return w_arguments class PyByteCode(PyBaseCode): @@ -119,3 +119,29 @@ ec = space.getexecutioncontext() w_ret = ec.eval_frame(frame) return w_ret + + def locals2cells(self, space, w_locals): + localcells = [] + Cell = pyframe.Cell + for name in self.co_varnames: + w_name = space.wrap(name) + try: + w_value = space.getitem(w_locals, w_name) + except executioncontext.OperationError, e: + if not e.match(space, space.w_KeyError): + raise + else: + cell = Cell() + else: + cell = Cell(w_value) + localcells.append(cell) + nestedcells = [] + for name in self.co_cellvars: + cell = Cell() + nestedcells.append(cell) + for name in self.co_freevars: + w_name = space.wrap(name) + w_cell = space.getitem(w_locals, w_name) + cell = space.unwrap(w_cell) + nestedcells.append(cell) + return localcells, nestedcells Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Mon Jun 23 15:56:12 2003 @@ -21,9 +21,10 @@ def __init__(self, space, bytecode, w_globals, w_locals): self.space = space - self.bytecode = bytecode + self.bytecode = bytecode # Misnomer; this is really like a code object self.w_globals = w_globals self.w_locals = w_locals + self.localcells, self.nestedcells = bytecode.locals2cells(space, w_locals) self.w_builtins = self.load_builtins() self.valuestack = Stack() self.blockstack = Stack() @@ -106,6 +107,35 @@ # is the variable given by index a cell or a free var? return index < len(self.bytecode.co_cellvars) + def fast2locals(self): + # Copy values from self.localcells to self.w_locals + for i in range(self.bytecode.co_nlocals): + name = self.bytecode.co_varnames[i] + cell = self.localcells[i] + w_name = self.space.wrap(name) + try: + w_value = cell.get() + except ValueError: + pass + else: + self.space.setitem(self.w_locals, w_name, w_value) + + def locals2fast(self): + # Copy values from self.w_locals to self.localcells + for i in range(self.bytecode.co_nlocals): + name = self.bytecode.co_varnames[i] + cell = self.localcells[i] + w_name = self.space.wrap(name) + try: + w_value = self.space.getitem(self.w_locals, w_name) + except OperationError, e: + if not e.match(self.space, self.space.w_KeyError): + raise + else: + pass + else: + cell.set(w_value) + ### frame initialization ### def load_builtins(self): @@ -316,3 +346,32 @@ class BytecodeCorruption(ValueError): """Detected bytecode corruption. Never caught; it's an error.""" + + +## Cells ## + +_NULL = object() # Marker object + +class Cell: + def __init__(self, w_value=_NULL): + self.w_value = w_value + + def get(self): + if self.w_value is _NULL: + raise ValueError, "get() from an empty cell" + return self.w_value + + def set(self, w_value): + self.w_value = w_value + + def delete(self): + if self.w_value is _NULL: + raise ValueError, "make_empty() on an empty cell" + self.w_value = _NULL + + def __repr__(self): + """ representation for debugging purposes """ + if self.w_value is _NULL: + return "%s()" % self.__class__.__name__ + else: + return "%s(%s)" % (self.__class__.__name__, self.w_value) Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Mon Jun 23 15:56:12 2003 @@ -233,6 +233,17 @@ return g self.assertEquals(f()(), 42) + def test_nested_scope4(self): + def f(): + x = 3 + def g(): + return x + a = g() + x = 4 + b = g() + return (a, b) + self.assertEquals(f(), (3, 4)) + def test_generator(self): def f(): yield 1 @@ -257,8 +268,7 @@ yield i me = g() self.assertRaises(ValueError, me.next) - - + if __name__ == '__main__': test.main() Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Mon Jun 23 15:56:12 2003 @@ -227,7 +227,10 @@ obj = self.unwrap(w_obj) except UnwrapException: if isinstance(w_obj, W_KnownKeysContainer): - return w_obj[key] + try: + return w_obj[key] + except: + return self.reraise() else: return W_Anything() try: Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 23 15:56:12 2003 @@ -1,3 +1,4 @@ +# -*- Coding: Latin-1 -*- """ stringobject.py From mwh at codespeak.net Mon Jun 23 16:12:14 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 16:12:14 +0200 (MEST) Subject: [pypy-svn] rev 991 - pypy/trunk/src/pypy/interpreter Message-ID: <20030623141214.C97115A243@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 16:12:14 2003 New Revision: 991 Modified: pypy/trunk/src/pypy/interpreter/py.py Log: import readline if we have it Modified: pypy/trunk/src/pypy/interpreter/py.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/py.py (original) +++ pypy/trunk/src/pypy/interpreter/py.py Mon Jun 23 16:12:14 2003 @@ -53,4 +53,8 @@ con.interact(banner) if __name__ == '__main__': + try: + import readline + except: + pass main_(sys.argv) From tismer at codespeak.net Mon Jun 23 16:13:17 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 16:13:17 +0200 (MEST) Subject: [pypy-svn] rev 992 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623141317.756EC5A243@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 16:13:17 2003 New Revision: 992 Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: made dict callable (w/all the trimmings as per Python 2.3) Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Mon Jun 23 16:13:17 2003 @@ -26,3 +26,22 @@ dict_iterkeys = MultiMethod('iterkeys', 1) dict_itervalues = MultiMethod('itervalues', 1) +# XXX we'll worry about the __new__/__init__ distinction later +def dicttype_new(space, w_listtype, w_args, w_kwds): + # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed + args = space.unpackiterable(w_args) + if len(args) == 0: + pass + elif len(args) == 1: + list_of_w_pairs = space.unpackiterable(args[0]) + list_of_w_pairs.reverse() + for pair_w in list_of_w_pairs: + k, v = space.unpackiterable(pair_w) + if not space.is_true(space.contains(w_kwds, k)): + space.setitem(w_kwds, k, v) + else: + raise OperationError(space.w_TypeError, + space.wrap("dict() takes at most 1 argument")) + return w_kwds + +StdObjSpace.new.register(dicttype_new, W_DictType, W_ANY, W_ANY) Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Mon Jun 23 16:13:17 2003 @@ -188,5 +188,18 @@ vals.sort() self.assertEqual(vals, [2,4]) + def test_new(self): + d = dict() + self.assertEqual(d, {}) + d = dict([]) + self.assertEqual(d, {}) + d = dict([['a',2], [23,45]]) + self.assertEqual(d, {'a':2, 23:45}) + d = dict([['a',2], [23,45]], a=33, b=44) + self.assertEqual(d, {'a':33, 'b':44, 23:45}) + d = dict(a=33, b=44) + self.assertEqual(d, {'a':33, 'b':44}) + + if __name__ == '__main__': test.main() From anna at codespeak.net Mon Jun 23 16:15:58 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 16:15:58 +0200 (MEST) Subject: [pypy-svn] rev 993 - pypy/trunk/doc/sprintinfo Message-ID: <20030623141558.1336F5A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 16:15:57 2003 New Revision: 993 Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: added links Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Mon Jun 23 16:15:57 2003 @@ -21,12 +21,12 @@ alex, christian -- boolobject review done boolobject.py_ -- cpythonobject review done -- instmethobject review done -- longobject review done -- sliceobject review done -- userobject review done +- boolobject review done boolobject_ +- cpythonobject review done cpythonobj_ +- instmethobject review done instmethod_ +- longobject review done removed long_ +- sliceobject review done sliceobject_ +- userobject review done userobject_ - dictobject review done - intobject - listobject @@ -63,12 +63,12 @@ - go through the wiki and clean up "stale" or old pages -- implement AnnotationObjSpace and the beginnings +- implement AnnotationObjSpace and the beginnings of a C code generator. the basic idea is "abstract interpretation".... - getting the translator to understand RPython, handling the - constructions it can and delegating the things it doesn't + constructions it can and delegating the things it doesn't understand to CPython (Mimicking Python2C) (Armin, Guido) @@ -77,4 +77,13 @@ --------------------------------------------------------------- -.. boolobject.py_: http://www.codespeak.net/svn/pypy/trunk/src/pypy/objspace/std/boolobject.py +.. _boolobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000381.html +.. _cpythonobj: http://codespeak.net/pipermail/pypy-svn/2003-June/000385.html +.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html +.. _long: http://codespeak.net/pipermail/pypy-svn/2003-June/000410.html +.. _sliceobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000408.html +.. _userobject: +.. _dictobject: +.. _intobject: + +.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html \ No newline at end of file From mwh at codespeak.net Mon Jun 23 16:16:26 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 16:16:26 +0200 (MEST) Subject: [pypy-svn] rev 994 - pypy/trunk/src/pypy/objspace Message-ID: <20030623141626.9F5AF5A243@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 16:16:25 2003 New Revision: 994 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: Fix test_generator_restart in the trivial object space. Guido pointed out a less sick way to cope with the called from app-space/call from interpreter distinction. Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 23 16:16:25 2003 @@ -13,20 +13,20 @@ self.space = space self.frame = frame self.running = 0 - def next(g_self): - if g_self.running: - raise OperationError(self.w_ValueError, + def next(self): + if self.running: + raise OperationError(self.space.w_ValueError, "generator already executing") - ec = g_self.space.getexecutioncontext() + ec = self.space.getexecutioncontext() - g_self.running = 1 + self.running = 1 try: try: - ret = ec.eval_frame(g_self.frame) + ret = ec.eval_frame(self.frame) except NoValue: raise StopIteration finally: - g_self.running = 0 + self.running = 0 return ret def __iter__(self): @@ -329,13 +329,12 @@ and callable.im_self is not None): args = (callable.im_self,) + args callable = callable.im_func - if callable == nugen.next.im_func: - try: - return apply(callable, args, kwds or {}) - except: - self.reraise() - else: + try: return apply(callable, args, kwds or {}) + except OperationError: + raise + except: + self.reraise() def hex(self, ob): try: From tismer at codespeak.net Mon Jun 23 16:22:15 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 16:22:15 +0200 (MEST) Subject: [pypy-svn] rev 995 - pypy/trunk/doc/sprintinfo Message-ID: <20030623142215.0FEBC5A243@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 16:22:14 2003 New Revision: 995 Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: reordered tasks for Alex/Chris Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Mon Jun 23 16:22:14 2003 @@ -28,11 +28,11 @@ - sliceobject review done sliceobject_ - userobject review done userobject_ - dictobject review done -- intobject -- listobject -- floatobject - iterobject - tupleobject +- listobject +- intobject +- floatobject tomek, holger, guenter From tismer at codespeak.net Mon Jun 23 16:40:12 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 16:40:12 +0200 (MEST) Subject: [pypy-svn] rev 996 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623144012.4CB315A243@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 16:40:11 2003 New Revision: 996 Modified: pypy/trunk/src/pypy/objspace/std/iterobject_app.py Log: clarified comment, soon to be removed Modified: pypy/trunk/src/pypy/objspace/std/iterobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject_app.py (original) +++ pypy/trunk/src/pypy/objspace/std/iterobject_app.py Mon Jun 23 16:40:11 2003 @@ -15,3 +15,5 @@ # Yes, the implementation is complete, I think # XXX design a way to have this working and get rid of iterobject.py +# (a very long term design goal, when the interpreter is so fast that +# we can do almost everything in app space -- for now, we just svn rm this!) From tismer at codespeak.net Mon Jun 23 16:40:49 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 16:40:49 +0200 (MEST) Subject: [pypy-svn] rev 997 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623144049.4C8A95A243@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 16:40:48 2003 New Revision: 997 Removed: pypy/trunk/src/pypy/objspace/std/iterobject_app.py Log: removed -- very long term design goal Deleted: pypy/trunk/src/pypy/objspace/std/iterobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject_app.py Mon Jun 23 16:40:48 2003 +++ (empty file) @@ -1,19 +0,0 @@ - -class SequenceIterator: - def __init__(self, it_seq, it_index): - self.it_seq = it_seq - self.it_index = it_index - def __iter__(self): - return self - def next(self): - try: - item = self.it_seq[self.it_index] - except IndexError: - raise StopIteration - self.it_index += 1 - return item - # Yes, the implementation is complete, I think - -# XXX design a way to have this working and get rid of iterobject.py -# (a very long term design goal, when the interpreter is so fast that -# we can do almost everything in app space -- for now, we just svn rm this!) From anna at codespeak.net Mon Jun 23 16:43:13 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 16:43:13 +0200 (MEST) Subject: [pypy-svn] rev 998 - pypy/trunk/doc/sprintinfo Message-ID: <20030623144313.CC2B35A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 16:43:13 2003 New Revision: 998 Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: added more links and updated done items Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Mon Jun 23 16:43:13 2003 @@ -27,11 +27,11 @@ - longobject review done removed long_ - sliceobject review done sliceobject_ - userobject review done userobject_ -- dictobject review done +- dictobject review done dictobject_ - iterobject - tupleobject - listobject -- intobject +- intobject inprocess intobject_ - floatobject tomek, holger, guenter @@ -82,8 +82,7 @@ .. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html .. _long: http://codespeak.net/pipermail/pypy-svn/2003-June/000410.html .. _sliceobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000408.html -.. _userobject: -.. _dictobject: -.. _intobject: - -.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html \ No newline at end of file +.. _userobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000449.html +.. _dictobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000515.html +.. _intobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000443.html +.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html From tismer at codespeak.net Mon Jun 23 16:44:33 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 16:44:33 +0200 (MEST) Subject: [pypy-svn] rev 999 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623144433.9731D5A243@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 16:44:33 2003 New Revision: 999 Modified: pypy/trunk/src/pypy/objspace/std/iterobject.py pypy/trunk/src/pypy/objspace/std/itertype.py pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py Log: reviewed, refactored some tests, very good and complete Modified: pypy/trunk/src/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/iterobject.py Mon Jun 23 16:44:33 2003 @@ -1,3 +1,9 @@ +""" +Reviewed 03-06-22 +Sequence-iteration is correctly implemented, thoroughly +tested, and complete. The only missing feature is support +for function-iteration. +""" from pypy.objspace.std.objspace import * from itertype import W_SeqIterType Modified: pypy/trunk/src/pypy/objspace/std/itertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/itertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/itertype.py Mon Jun 23 16:44:33 2003 @@ -1,3 +1,6 @@ +""" +Reviewed 03-06-22 +""" from pypy.objspace.std.objspace import * from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py Mon Jun 23 16:44:33 2003 @@ -11,21 +11,38 @@ def tearDown(self): pass - def test_iter(self): + def body3(self, w_iter): w = self.space.wrap - w_tuple = self.space.newtuple([w(5), w(3), w(99)]) - w_iter = W_SeqIterObject(self.space, w_tuple) self.assertEqual_w(self.space.next(w_iter), w(5)) self.assertEqual_w(self.space.next(w_iter), w(3)) self.assertEqual_w(self.space.next(w_iter), w(99)) + self.body0(w_iter) + + def body0(self, w_iter): self.assertRaises(NoValue, self.space.next, w_iter) self.assertRaises(NoValue, self.space.next, w_iter) + def test_iter(self): + w = self.space.wrap + w_tuple = self.space.newtuple([w(5), w(3), w(99)]) + w_iter = W_SeqIterObject(self.space, w_tuple) + self.body3(w_iter) + + def test_iter_builtin(self): + w = self.space.wrap + w_tuple = self.space.newtuple([w(5), w(3), w(99)]) + w_iter = self.space.iter(w_tuple) + self.body3(w_iter) + def test_emptyiter(self): w_list = self.space.newlist([]) w_iter = W_SeqIterObject(self.space, w_list) - self.assertRaises(NoValue, self.space.next, w_iter) - self.assertRaises(NoValue, self.space.next, w_iter) + self.body0(w_iter) + + def test_emptyiter_builtin(self): + w_list = self.space.newlist([]) + w_iter = self.space.iter(w_list) + self.body0(w_iter) if __name__ == '__main__': test.main() From arigo at codespeak.net Mon Jun 23 16:44:56 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Jun 2003 16:44:56 +0200 (MEST) Subject: [pypy-svn] rev 1000 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030623144456.44AB25A243@thoth.codespeak.net> Author: arigo Date: Mon Jun 23 16:44:55 2003 New Revision: 1000 Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Log: report failure Modified: pypy/trunk/src/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_userobject.py Mon Jun 23 16:44:55 2003 @@ -17,6 +17,8 @@ stuff = subclass() except: print 'not subclassable:', base + if base is not dict: # XXX must be fixed + raise else: self.failUnless(isinstance(stuff, base)) From tismer at codespeak.net Mon Jun 23 16:46:30 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 16:46:30 +0200 (MEST) Subject: [pypy-svn] rev 1001 - pypy/trunk/doc/sprintinfo Message-ID: <20030623144630.BEDB45A243@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 16:46:30 2003 New Revision: 1001 Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: iter done Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Mon Jun 23 16:46:30 2003 @@ -28,7 +28,7 @@ - sliceobject review done sliceobject_ - userobject review done userobject_ - dictobject review done dictobject_ -- iterobject +- iterobject review done iterobject_ - tupleobject - listobject - intobject inprocess intobject_ @@ -86,3 +86,5 @@ .. _dictobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000515.html .. _intobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000443.html .. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html +.. _iterobject:: http://codespeak.net/pipermail/pypy-svn/2003-June/000999.html + From anna at codespeak.net Mon Jun 23 16:49:36 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 16:49:36 +0200 (MEST) Subject: [pypy-svn] rev 1002 - pypy/trunk/doc/devel Message-ID: <20030623144936.41A295A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 16:49:35 2003 New Revision: 1002 Added: pypy/trunk/doc/devel/testdesign.txt Log: formatted test-design from wiki page in reST Added: pypy/trunk/doc/devel/testdesign.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/devel/testdesign.txt Mon Jun 23 16:49:35 2003 @@ -0,0 +1,34 @@ +============= +Test Design +============= + +Our tests are based on the unittest framework. Tests for modules usually reside in a subdirectory called "test". + +If you write a test, then you usually have the following lines at the start of your test:: + + import autopath + from pypy.tool import test + +For the time being, please refer to a pypy-dev mail_ for more info. + + +Command line tool test_all +--------------------------- + +PyPy's current testing framework (since revision 831) is driven by the command line src/pypy/test_all.py tool. Simply change to the pypy root directory and issue:: + + + python test_all.py + + +which will run all tests against the Trivial Object Space. If you want to test against the StandardObjectSpace then issue:: + + + python test_all.py -S + + +For more switches invoke "python test_all.py -h". + +----------------------------------------------------------------------------------------------- + +.. _mail: http://codespeak.net/pipermail/pypy-dev/2003q2/000789.html From arigo at codespeak.net Mon Jun 23 16:57:23 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Jun 2003 16:57:23 +0200 (MEST) Subject: [pypy-svn] rev 1003 - in pypy/trunk/src/pypy: interpreter objspace/std Message-ID: <20030623145723.5DA2D5A243@thoth.codespeak.net> Author: arigo Date: Mon Jun 23 16:57:22 2003 New Revision: 1003 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/userobject.py Log: Clean-up of the interfaces between multimethods and Python special __xxx__ methods, in both directions. M /home/arigo/python/pypy/pypy/trunk/src/pypy/interpreter/baseobjspace.py nonzero multimethod removed, next (iterators) made special M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/userobject.py properly translate Python results into multimethod-like results M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/default.py is_true falls back to len, nonzero removed M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/typeobject.py properly export and translate multimethod results to Python M /home/arigo/python/pypy/pypy/trunk/src/pypy/objspace/std/objspace.py next is now a special multimethod Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Mon Jun 23 16:57:22 2003 @@ -195,7 +195,6 @@ ('and_', '&', 2, ['__and__', '__rand__']), ('or_', '|', 2, ['__or__', '__ror__']), ('xor', '^', 2, ['__xor__', '__rxor__']), - ('nonzero', 'nonzero', 1, ['__nonzero__']), ('int', 'int', 1, ['__int__']), ('float', 'float', 1, ['__float__']), ('inplace_add', '+=', 2, ['__iadd__']), @@ -219,7 +218,6 @@ ('ge', '>=', 2, ['__ge__', '__le__']), ('contains', 'contains', 2, ['__contains__']), ('iter', 'iter', 1, ['__iter__']), - ('next', 'next', 1, ['next']), # iterator interface ('call', 'call', 3, ['__call__']), ('get', 'get', 3, ['__get__']), ('set', 'set', 2, ['__set__']), @@ -288,4 +286,5 @@ # newslice(w_start,w_stop,w_end) -> w_slice (w_end may be a real None) # newfunction(...) -> w_function # newmodule(w_name) -> w_module +# next(w_iter) -> w_value or raise NoValue # Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Mon Jun 23 16:57:22 2003 @@ -35,10 +35,15 @@ def not__ANY(space, w_obj): return space.newbool(not space.is_true(w_obj)) -# everything is True unless otherwise specified + +# __nonzero__ falls back to __len__ def is_true__ANY(space, w_obj): - return True + try: + w_len = space.len.perform_call((w_obj,)) + except FailedToImplement: + return True # everything is True unless otherwise specified + return space.is_true(space.ne(w_len, space.newint(0))) # in-place operators fall back to their non-in-place counterpart @@ -73,8 +78,6 @@ def issubtype__ANY_ANY(space, w_one, w_two): # XXX -- mwh return space.newbool(0) - -def nonzero__ANY(space, w_obj): - return space.newbool(space.is_true(w_obj)) + # XXX why is it there ? -- Armin register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Mon Jun 23 16:57:22 2003 @@ -277,6 +277,7 @@ is_data_descr = MultiMethod('is_data_descr', 1, []) # returns an unwrapped bool getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute + next = MultiMethod('next', 1, []) # iterator interface def is_(self, w_one, w_two): # XXX this is a hopefully temporary speed hack: Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Mon Jun 23 16:57:22 2003 @@ -18,15 +18,6 @@ def __init__(w_self, space): W_Object.__init__(w_self, space) w_self.w_tpname = space.wrap(w_self.typename) - w_self.multimethods = {} - # import all multimethods of the type class and of the objspace - for multimethod in (hack_out_multimethods(w_self.__class__) + - hack_out_multimethods(space.__class__)): - for i in range(len(multimethod.specialnames)): - # each PyMultimethodCode embeds a multimethod - name = multimethod.specialnames[i] - code = PyMultimethodCode(multimethod, w_self.__class__, i) - w_self.multimethods[name] = code def getbases(w_self): parents = w_self.staticbases @@ -58,10 +49,11 @@ def lookup_exactly_here(w_self, w_key): space = w_self.space + multimethods = getmultimethods(space.__class__, w_self.__class__) key = space.unwrap(w_key) assert isinstance(key, str) try: - code = w_self.multimethods[key] + code = multimethods[key] except KeyError: raise KeyError # pass on the KeyError if code.slice().is_empty(): @@ -83,6 +75,33 @@ result.append(value) return result +AllSlicedMultimethods = {} + +def getmultimethods(spaceclass, typeclass): + try: + multimethods = AllSlicedMultimethods[spaceclass, typeclass] + except KeyError: + multimethods = AllSlicedMultimethods[spaceclass, typeclass] = {} + # import all multimethods of the type class and of the objspace + for multimethod in (hack_out_multimethods(typeclass) + + hack_out_multimethods(spaceclass)): + for i in range(len(multimethod.specialnames)): + # each PyMultimethodCode embeds a multimethod + name = multimethod.specialnames[i] + if name in multimethods: + # conflict between e.g. __lt__ and + # __lt__-as-reversed-version-of-__gt__ + code = multimethods[name] + if code.bound_position < i: + continue + code = PyMultimethodCode(multimethod, typeclass, i) + multimethods[name] = code + # add some more multimethods with a special interface + code = NextMultimethodCode(spaceclass.next, typeclass) + multimethods['next'] = code + code = NonZeroMultimethodCode(spaceclass.is_true, typeclass) + multimethods['__nonzero__'] = code + return multimethods class PyMultimethodCode(pycode.PyBaseCode): @@ -104,7 +123,7 @@ def slice(self): return self.basemultimethod.slice(self.typeclass, self.bound_position) - def eval_code(self, space, w_globals, w_locals): + def do_call(self, space, w_globals, w_locals): """Call the multimethod, ignoring all implementations that do not have exactly the expected type at the bound_position.""" multimethod = self.slice() @@ -113,20 +132,38 @@ w_arg = space.getitem(w_locals, space.wrap('x%d'%(i+1))) dispatchargs.append(w_arg) dispatchargs = tuple(dispatchargs) + return multimethod.get(space).perform_call(dispatchargs) + + def eval_code(self, space, w_globals, w_locals): + "Call the multimethods, translating back information to Python." try: - w_result = multimethod.get(space).perform_call(dispatchargs) + w_result = self.do_call(space, w_globals, w_locals) except FailedToImplement, e: if e.args: raise OperationError(*e.args) else: return space.w_NotImplemented - except NoValue: - raise OperationError(space.w_StopIteration, space.w_None) - # XXX hack to accept real Nones from operations with no return value + # we accept a real None from operations with no return value if w_result is None: w_result = space.w_None return w_result +class NextMultimethodCode(PyMultimethodCode): + + def eval_code(self, space, w_globals, w_locals): + "Call the next() multimethod." + try: + return self.do_call(space, w_globals, w_locals) + except NoValue: + raise OperationError(space.w_StopIteration, space.w_None) + +class NonZeroMultimethodCode(PyMultimethodCode): + + def eval_code(self, space, w_globals, w_locals): + "Call the is_true() multimethods." + result = self.do_call(space, w_globals, w_locals) + return space.newbool(result) + def call__Type_ANY_ANY(space, w_type, w_args, w_kwds): w_newobject = space.new(w_type, w_args, w_kwds) Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Mon Jun 23 16:57:22 2003 @@ -100,51 +100,72 @@ else: return 1 -# register an implementation for all multimethods that define special names -def user_specialmethod(space, *args_w): - # args_w is in the standard multimethod order - # we need it in the Python-friendly order (i.e. swapped for __rxxx__) - args_w = list(args_w) - w_userobj = args_w.pop(g_bound_position) - w_args = space.newtuple(args_w) - w_key = space.wrap(g_method_name) - mro = space.getattr(w_userobj.w_type, space.wrap('__mro__')) - mro = space.unpacktuple(mro) - for w_base in mro: - if not isinstance(w_base, W_UserType): - continue - try: - w_function = w_base.lookup_exactly_here(w_key) - except KeyError: - continue - w_method = space.get(w_function, w_userobj, w_base) - w_result = space.call(w_method, w_args, space.newdict([])) - # XXX hack to accept real Nones from operations with no return value - if w_result is None: - return space.w_None - elif space.is_true(space.is_(w_result, space.w_NotImplemented)): + +class SpecialMethod: + """An implementation for a multimethod that looks for a user-defined + special __xxx__ method.""" + + def __init__(self, method_name, bound_position=0): + self.method_name = method_name + self.bound_position = bound_position + + def do_call(self, space, args_w): + # args_w is in the standard multimethod order + # we need it in the Python-friendly order (i.e. swapped for __rxxx__) + args_w = list(args_w) + w_userobj = args_w.pop(self.bound_position) + w_args = space.newtuple(args_w) + w_key = space.wrap(self.method_name) + w_mro = space.getattr(w_userobj.w_type, space.wrap('__mro__')) + mro = space.unpacktuple(w_mro) + for w_base in mro: + if not isinstance(w_base, W_UserType): + continue + try: + w_function = w_base.lookup_exactly_here(w_key) + except KeyError: + continue + w_method = space.get(w_function, w_userobj, w_base) + return space.call(w_method, w_args, space.newdict([])) + raise FailedToImplement + + def normal_call(self, space, *args_w): + "Call a user-defined __xxx__ method and convert the result back." + w_result = self.do_call(space, args_w) + # interpret 'NotImplemented' as meaning not implemented (duh). + if space.is_true(space.is_(w_result, space.w_NotImplemented)): raise FailedToImplement - else: - return w_result - raise FailedToImplement + return w_result + + def next_call(self, space, *args_w): + "For .next()." + # don't accept NotImplemented nor a real None, but catch StopIteration + try: + return self.do_call(space, args_w) + except OperationError, e: + if not e.match(self.space, self.space.w_StopIteration): + raise + raise NoValue + + def nonzero_call(self, space, *args_w): + "For __nonzero__()." + # accept any object and return its truth value + # XXX if the user returns another custom object he can + # force the interpreter into an infinite loop + w_result = self.do_call(space, args_w) + return space.is_true(w_result) + import new for multimethod in typeobject.hack_out_multimethods(StdObjSpace): for i in range(len(multimethod.specialnames)): - # a hack to avoid nested scopes is to give the function - # a custom globals dictionary - - g = {'W_UserType' : W_UserType, - 'FailedToImplement': FailedToImplement, - '__builtins__' : __builtins__, - 'g_method_name' : multimethod.specialnames[i], - 'g_bound_position' : i} - f = new.function(user_specialmethod.func_code, g, - 'user_%s' % multimethod.specialnames[i]) - + f = SpecialMethod(multimethod.specialnames[i], i).normal_call signature = [W_ANY] * multimethod.arity signature[i] = W_UserObject multimethod.register(f, *signature) +next__User = SpecialMethod('next').next_call +is_true__User = SpecialMethod('nonzero').nonzero_call + register_all(vars()) From anna at codespeak.net Mon Jun 23 17:01:32 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:01:32 +0200 (MEST) Subject: [pypy-svn] rev 1004 - pypy/trunk/doc/devel Message-ID: <20030623150132.DE8BD5A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:01:32 2003 New Revision: 1004 Modified: pypy/trunk/doc/devel/coding-style.txt Log: formatted for reST Modified: pypy/trunk/doc/devel/coding-style.txt ============================================================================== --- pypy/trunk/doc/devel/coding-style.txt (original) +++ pypy/trunk/doc/devel/coding-style.txt Mon Jun 23 17:01:32 2003 @@ -1,17 +1,23 @@ +===================================== +Coding Style +===================================== + + Directory Structure (example sketch) ------------------------------------ +Here is an example of the directory structure:: -trunk/ + trunk/ src/ pypy/ interpreter/ pyframe.py opcodes.py opcodes_app.py - baseobjspace.py + baseobjspace.py module/ # mixed interpreter/app-code - builtin.py + builtin.py builtin_app.py struct.py struct_app.py @@ -39,11 +45,13 @@ util/ -> used for internal deployment (not visible to outside) doc/ # meta-documents about pypy (unordered) -naming and environment +end of example. + +Naming and environment ----------------------------- -- the PYTHONPATH should be set to the filesytstem equivalent of - http://codespeak.net:8080/svn/pypy/trunk/src +- the PYTHONPATH should be set to the filesytstem equivalent of + http://codespeak.net:8080/svn/pypy/trunk/src in fact the "autopath" module does this for you. - __init__.py is always empty except for "pypy/objspace/*" @@ -55,7 +63,7 @@ - functions/methods are lowercase and '_'-separated (if you need to separate at all) -Object Spaces +Object Spaces --------------- - objectspace classes are always spelled "ObjSpace" @@ -69,32 +77,33 @@ - not more than 4 directory nesting levels -- never use plural names in directory and file names +- never use plural names in directory and file names Test conventions -------------------- -- each module has a canonical test-script (using the "unittests" +- each module has a canonical test-script (using the "unittests" package if feasible) - test/test_exactmodulename.py + test/test_exactmodulename.py + +- each TestCase is named after the class it tests -- each TestCase is named after the class it tests - class TestExactClass(unittest.TestCase): - all other testcases are assumed to test single/more functions or something that spans more than one class -- every non-test file is forbidden to start with "t" +- every non-test file is forbidden to start with "t" - each test directory needs a copy of testsupport.py. see doc/using-testsupport.txt for more information. +- see information at [[pypydoc test-design.html]] -Miscallenous stuff ------------------- +Miscellaneous stuff +--------------------- - to edit wiki pages do - svn co http://codespeak.net:8080/svn/pypy/trunk/www/moininstance/data/text wiki-pages + svn co http://codespeak.net/svn/pypy/trunk/www/moininstance/data/text wiki-pages From arigo at codespeak.net Mon Jun 23 17:05:43 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Jun 2003 17:05:43 +0200 (MEST) Subject: [pypy-svn] rev 1005 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623150543.DD0B85A243@thoth.codespeak.net> Author: arigo Date: Mon Jun 23 17:05:43 2003 New Revision: 1005 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/tupleobject.py Log: is_true removed from sequences, since it defaults to len now Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Mon Jun 23 17:05:43 2003 @@ -82,9 +82,6 @@ registerimplementation(W_DictObject) -def is_true__Dict(space, w_dict): - return not not w_dict.non_empties() - def unwrap__Dict(space, w_dict): result = {} for w_key, cell in w_dict.non_empties(): Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Mon Jun 23 17:05:43 2003 @@ -35,9 +35,6 @@ items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]] return list(items) -def is_true__List(space, w_list): - return not not w_list.ob_size - def len__List(space, w_list): result = w_list.ob_size return W_IntObject(space, result) Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 23 17:05:43 2003 @@ -7,7 +7,6 @@ Py PyPy def _is_generic(w_self, fun): - def is_true__String(space, w_str): def mod__String_ANY(space, w_str, w_item):def mod__String_Tuple(space, w_str, w_tuple):def mod_str_tuple(space, w_format, w_args): def ord__String(space, w_str): def string_richcompare(space, w_str1, w_str2, op): @@ -615,9 +614,6 @@ def unwrap__String(space, w_str): return w_str._value -def is_true__String(space, w_str): - return len(space.unwrap(w_str)) != 0 - def hash__String(space, w_str): return W_IntObject(space, hash(space.unwrap(w_str))) Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Mon Jun 23 17:05:43 2003 @@ -24,9 +24,6 @@ items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] return tuple(items) -def is_true__Tuple(space, w_tuple): - return not not w_tuple.wrappeditems - def len__Tuple(space, w_tuple): result = len(w_tuple.wrappeditems) return W_IntObject(space, result) From anna at codespeak.net Mon Jun 23 17:11:42 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:11:42 +0200 (MEST) Subject: [pypy-svn] rev 1006 - pypy/trunk/doc/devel Message-ID: <20030623151142.026115A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:11:41 2003 New Revision: 1006 Modified: pypy/trunk/doc/devel/coding-style.txt Log: corrected formatting for reST Modified: pypy/trunk/doc/devel/coding-style.txt ============================================================================== --- pypy/trunk/doc/devel/coding-style.txt (original) +++ pypy/trunk/doc/devel/coding-style.txt Mon Jun 23 17:11:41 2003 @@ -50,17 +50,17 @@ Naming and environment ----------------------------- -- the PYTHONPATH should be set to the filesytstem equivalent of - http://codespeak.net:8080/svn/pypy/trunk/src +- the PYTHONPATH should be set to the filesystem equivalent of + http://codespeak.net/svn/pypy/trunk/src in fact the "autopath" module does this for you. -- __init__.py is always empty except for "pypy/objspace/*" +- ``__init__.py`` is always empty except for ``"pypy/objspace/*"`` - directories/modules/namespaces are always lowercase - classes are CamelCase -- functions/methods are lowercase and '_'-separated (if +- functions/methods are lowercase and ``'_'-separated`` (if you need to separate at all) Object Spaces @@ -71,8 +71,8 @@ StdObjSpace - at interpreter level and in ObjSpace all boxed values - have a leading 'w_' to indicate "wrapped values". This - includes w_self. Don't use 'w_' in application level + have a leading ``w_`` to indicate "wrapped values". This + includes w_self. Don't use ``w_`` in application level python only code. - not more than 4 directory nesting levels @@ -104,6 +104,6 @@ Miscellaneous stuff --------------------- -- to edit wiki pages do +To edit wiki pages do: - svn co http://codespeak.net/svn/pypy/trunk/www/moininstance/data/text wiki-pages + `` svn co http://codespeak.net/svn/pypy/trunk/www/moininstance/data/text wiki-pages`` From anna at codespeak.net Mon Jun 23 17:14:49 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:14:49 +0200 (MEST) Subject: [pypy-svn] rev 1007 - pypy/trunk/doc/devel Message-ID: <20030623151449.33AB85A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:14:48 2003 New Revision: 1007 Modified: pypy/trunk/doc/devel/coding-style.txt Log: corrected formatting for reST Modified: pypy/trunk/doc/devel/coding-style.txt ============================================================================== --- pypy/trunk/doc/devel/coding-style.txt (original) +++ pypy/trunk/doc/devel/coding-style.txt Mon Jun 23 17:14:48 2003 @@ -99,11 +99,15 @@ - each test directory needs a copy of testsupport.py. see doc/using-testsupport.txt for more information. -- see information at [[pypydoc test-design.html]] +- see information at test-design_ Miscellaneous stuff --------------------- To edit wiki pages do: - `` svn co http://codespeak.net/svn/pypy/trunk/www/moininstance/data/text wiki-pages`` +``svn co http://codespeak.net/svn/pypy/trunk/www/moininstance/data/text wiki-pages`` + +------------------------------------------------------------------------------------------ + +.. -test-design: ../devel/test-design.html \ No newline at end of file From gvanrossum at codespeak.net Mon Jun 23 17:16:05 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 17:16:05 +0200 (MEST) Subject: [pypy-svn] rev 1008 - pypy/trunk/src/pypy/tool Message-ID: <20030623151605.A1B085A243@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 17:16:05 2003 New Revision: 1008 Modified: pypy/trunk/src/pypy/tool/option.py Log: Add -A to run tests in ann space. Generalize how the space module is imported. Modified: pypy/trunk/src/pypy/tool/option.py ============================================================================== --- pypy/trunk/src/pypy/tool/option.py (original) +++ pypy/trunk/src/pypy/tool/option.py Mon Jun 23 17:16:05 2003 @@ -22,6 +22,10 @@ callback=objspace_callback, callback_args=("trivial",), help="run in trivial object space")) options.append(make_option( + '-A', action="callback", + callback=objspace_callback, callback_args=("ann",), + help="run in annotation object space")) + options.append(make_option( '-v', action="count", dest="verbose", help="verbose")) options.append(make_option( @@ -50,14 +54,10 @@ name = Options.spacename else: name = Options.spaces[-1] - if name == 'std': - from pypy.objspace.std import Space - elif name == 'trivial': - from pypy.objspace.trivial import Space - else: - raise ValueError, "no objectspace named %s" % repr(name) try: return _spacecache[name] except KeyError: + module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) + Space = module.Space return _spacecache.setdefault(name, Space()) From anna at codespeak.net Mon Jun 23 17:16:42 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:16:42 +0200 (MEST) Subject: [pypy-svn] rev 1009 - pypy/trunk/doc/devel Message-ID: <20030623151642.E8AEA5A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:16:42 2003 New Revision: 1009 Modified: pypy/trunk/doc/devel/coding-style.txt Log: minor formatting edits Modified: pypy/trunk/doc/devel/coding-style.txt ============================================================================== --- pypy/trunk/doc/devel/coding-style.txt (original) +++ pypy/trunk/doc/devel/coding-style.txt Mon Jun 23 17:16:42 2003 @@ -110,4 +110,4 @@ ------------------------------------------------------------------------------------------ -.. -test-design: ../devel/test-design.html \ No newline at end of file +.. -test-design: ../devel/testdesign.html \ No newline at end of file From anna at codespeak.net Mon Jun 23 17:18:50 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:18:50 +0200 (MEST) Subject: [pypy-svn] rev 1010 - pypy/trunk/doc/devel Message-ID: <20030623151850.57B695A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:18:50 2003 New Revision: 1010 Modified: pypy/trunk/doc/devel/coding-style.txt Log: minor edits to links Modified: pypy/trunk/doc/devel/coding-style.txt ============================================================================== --- pypy/trunk/doc/devel/coding-style.txt (original) +++ pypy/trunk/doc/devel/coding-style.txt Mon Jun 23 17:18:50 2003 @@ -110,4 +110,4 @@ ------------------------------------------------------------------------------------------ -.. -test-design: ../devel/testdesign.html \ No newline at end of file +.. _test-design: ../devel/testdesign.html \ No newline at end of file From anna at codespeak.net Mon Jun 23 17:26:46 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:26:46 +0200 (MEST) Subject: [pypy-svn] rev 1011 - pypy/trunk/doc/devel Message-ID: <20030623152646.C06DC5A243@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:26:46 2003 New Revision: 1011 Modified: pypy/trunk/doc/devel/coding-style.txt Log: updated link to testsupport docs Modified: pypy/trunk/doc/devel/coding-style.txt ============================================================================== --- pypy/trunk/doc/devel/coding-style.txt (original) +++ pypy/trunk/doc/devel/coding-style.txt Mon Jun 23 17:26:46 2003 @@ -97,7 +97,7 @@ - every non-test file is forbidden to start with "t" -- each test directory needs a copy of testsupport.py. see doc/using-testsupport.txt for more information. +- each test directory needs a copy of testsupport.py. see using-testsupport_ for more information. - see information at test-design_ @@ -110,4 +110,5 @@ ------------------------------------------------------------------------------------------ -.. _test-design: ../devel/testdesign.html \ No newline at end of file +.. _test-design: ../devel/testdesign.html +.. _using-testsupport: ../devel/using-testsupport.html \ No newline at end of file From gvanrossum at codespeak.net Mon Jun 23 17:31:20 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 23 Jun 2003 17:31:20 +0200 (MEST) Subject: [pypy-svn] rev 1012 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030623153120.7819D5A243@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 23 17:31:20 2003 New Revision: 1012 Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py Log: There was a bug in the way exceptions were being added to the space. svn ci -m There was a bug in the way exceptions were being added to the space. Despite its attractive looks, isinstance(c, Exception) does *not* work Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Mon Jun 23 17:31:20 2003 @@ -29,11 +29,9 @@ self.w_Ellipsis = self.wrap(Ellipsis) import __builtin__, types for n, c in __builtin__.__dict__.iteritems(): - if isinstance(c, (types.TypeType, Exception)): - setattr(self, 'w_' + c.__name__, self.wrap(c)) + if isinstance(c, types.TypeType) or isinstance(c, types.ClassType): + setattr(self, 'w_'+n, self.wrap(c)) self.w_builtins = self.wrap(__builtin__) - # XXX This should be done differently: - self.w_KeyError = self.wrap(KeyError) # Service methods whose interface is in the abstract base class From anna at codespeak.net Mon Jun 23 17:31:56 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Mon, 23 Jun 2003 17:31:56 +0200 (MEST) Subject: [pypy-svn] rev 1013 - pypy/trunk/doc/devel Message-ID: <20030623153156.1CB485A25F@thoth.codespeak.net> Author: anna Date: Mon Jun 23 17:31:55 2003 New Revision: 1013 Modified: pypy/trunk/doc/devel/using-testsupport.txt Log: format using-testsupport for reST Modified: pypy/trunk/doc/devel/using-testsupport.txt ============================================================================== --- pypy/trunk/doc/devel/using-testsupport.txt (original) +++ pypy/trunk/doc/devel/using-testsupport.txt Mon Jun 23 17:31:55 2003 @@ -1,20 +1,23 @@ -Tile testsupport.py should be copied into every test subdirectory. -The main copy lives in pypy/testsupport.py . - -import testsupport - -fixes the path so that all 'import pypy.something' should work. - -Module testsupport also exposes the following: - main a function just like unittest.main - TestCase a class just like unittest.TestCase but with extra methods - objspace the object space class to be used in this test - -testsupport.objspace is normally the trivial object space, but you -can set it (via an environment variable set before running Python) -to be the standard object space instead. Specifically: - - set OBJSPACE=pypy.objspace.std.objspace.StdObjSpace - -(or equivalent syntax depending on your shell) does the job. - +======================= +Using testsupport +======================= + +file ``testsupport.py`` should be copied into every test subdirectory. +The main copy lives in ``pypy/testsupport.py`` Use:: + + import testsupport + +to fix the path so that all 'import pypy.something' should work. + +Module testsupport also exposes the following: ++ main a function just like unittest.main ++ TestCase a class just like unittest.TestCase but with extra methods ++ objspace the object space class to be used in this test + +``testsupport.objspace`` is normally the trivial object space, but you +can set it (via an environment variable set before running Python) +to be the standard object space instead. Specifically:: + + set OBJSPACE=pypy.objspace.std.objspace.StdObjSpace + +(or equivalent syntax depending on your shell) does the job. \ No newline at end of file From mwh at codespeak.net Mon Jun 23 18:32:18 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 18:32:18 +0200 (MEST) Subject: [pypy-svn] rev 1014 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030623163218.B14985A264@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 18:32:18 2003 New Revision: 1014 Modified: pypy/trunk/src/pypy/objspace/std/userobject.py Log: Refactor, Schmeefactor. Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Mon Jun 23 18:32:18 2003 @@ -143,7 +143,7 @@ try: return self.do_call(space, args_w) except OperationError, e: - if not e.match(self.space, self.space.w_StopIteration): + if not e.match(space, space.w_StopIteration): raise raise NoValue From mwh at codespeak.net Mon Jun 23 19:10:06 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 19:10:06 +0200 (MEST) Subject: [pypy-svn] rev 1015 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030623171006.616705A264@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 19:09:55 2003 New Revision: 1015 Modified: pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py Log: add a simple iterator test Modified: pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_iterobject.py Mon Jun 23 19:09:55 2003 @@ -44,5 +44,15 @@ w_iter = self.space.iter(w_list) self.body0(w_iter) +class TestW_IterObjectApp(test.AppTestCase): + + def test_user_iter(self): + class C: + def next(self): + raise StopIteration + def __iter__(self): + return self + self.assertEquals(list(C()), []) + if __name__ == '__main__': test.main() From mwh at codespeak.net Mon Jun 23 19:13:15 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 19:13:15 +0200 (MEST) Subject: [pypy-svn] rev 1016 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030623171315.543EB5A264@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 19:13:14 2003 New Revision: 1016 Added: pypy/trunk/src/pypy/interpreter/test/test_class.py (contents, props changed) Log: add test_class complete with disabled tests of the metaclass machinery (doesn't work in stdobjspace) Added: pypy/trunk/src/pypy/interpreter/test/test_class.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/interpreter/test/test_class.py Mon Jun 23 19:13:14 2003 @@ -0,0 +1,67 @@ +import autopath +from pypy.tool import test + + +class TestClassApp(test.AppTestCase): + + + def test_class(self): + class C: + pass + self.assertEquals(C.__class__, type) + c = C() + self.assertEquals(c.__class__, C) + + def dont_test_metaclass_explicit(self): + class M(type): + pass + class C: + __metaclass__ = M + self.assertEquals(C.__class__, M) + c = C() + self.assertEquals(c.__class__, C) + + def dont_test_metaclass_inherited(self): + class M(type): + pass + class B: + __metaclass__ = M + class C(B): + pass + self.assertEquals(C.__class__, M) + c = C() + self.assertEquals(c.__class__, C) + + def dont_test_metaclass_global(self): + d = {} + metatest_text = """ +class M(type): + pass +__metaclass__ = M +class C: + pass +""" + exec metatest_text in d + C = d['C'] + M = d['M'] + self.assertEquals(C.__class__, M) + c = C() + self.assertEquals(c.__class__, C) + + def test_method(self): + class C: + def meth(self): + return 1 + c = C() + self.assertEqual(c.meth(), 1) + + def test_method_exc(self): + class C: + def meth(self): + raise RuntimeError + c = C() + self.assertRaises(RuntimeError, c.meth) + + +if __name__ == '__main__': + test.main() From mwh at codespeak.net Mon Jun 23 19:19:24 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 19:19:24 +0200 (MEST) Subject: [pypy-svn] rev 1017 - pypy/trunk/src/pypy/objspace Message-ID: <20030623171924.3816A5A264@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 19:19:23 2003 New Revision: 1017 Modified: pypy/trunk/src/pypy/objspace/trivial.py Log: color me a bit confused. i was doing some work to make iterators work better in the standard object space, and the tests started working much earlier than i expected. if you run into weird behaviour with the trivial object space, come and talk to me! Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Mon Jun 23 19:19:23 2003 @@ -32,6 +32,26 @@ def __iter__(self): return self +class numeth(object): + def __init__(self, space, func, inst, cls): + self.space = space + self.func = func + self.inst = inst + self.cls = cls + def _call_(self, *args, **kws): + if self.inst is None and self.cls is not type(None): + pass + else: + args = (self.inst,) + args + return self.func(*args, **kws) + def __call__(self, *args, **kws): + try: + return self._call_(*args, **kws) + except OperationError, oe: + raise eval(oe.w_type.__name__) + except: + raise + class nufun(object): def __init__(self, space, code, globals, defaultarguments, closure): self.space = space @@ -54,8 +74,7 @@ def __call__(self, *args, **kwds): return self.do_call(*args, **kwds) def __get__(self, ob, cls=None): - import new - return new.instancemethod(self, ob, cls) + return numeth(self.space, self, ob, cls) class TrivialObjSpace(ObjSpace): From mwh at codespeak.net Mon Jun 23 19:20:24 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 23 Jun 2003 19:20:24 +0200 (MEST) Subject: [pypy-svn] rev 1018 - pypy/trunk/src/pypy/interpreter Message-ID: <20030623172024.4DAED5A264@thoth.codespeak.net> Author: mwh Date: Mon Jun 23 19:20:23 2003 New Revision: 1018 Modified: pypy/trunk/src/pypy/interpreter/opcode.py pypy/trunk/src/pypy/interpreter/opcode_app.py Log: call the right metaclass in reponse to a BUILD_CLASS opcode. Modified: pypy/trunk/src/pypy/interpreter/opcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode.py Mon Jun 23 19:20:23 2003 @@ -315,9 +315,8 @@ w_methodsdict = f.valuestack.pop() w_bases = f.valuestack.pop() w_name = f.valuestack.pop() - w_metaclass = f.space.w_type # XXX do the correct thing here - w_newclass = f.space.call_function(w_metaclass, - w_name, w_bases, w_methodsdict) + w_newclass = f.space.gethelper(appfile).call( + "build_class", [w_name, w_bases, w_methodsdict, f.w_globals]) f.valuestack.push(w_newclass) def STORE_NAME(f, varindex): Modified: pypy/trunk/src/pypy/interpreter/opcode_app.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/opcode_app.py (original) +++ pypy/trunk/src/pypy/interpreter/opcode_app.py Mon Jun 23 19:20:23 2003 @@ -183,3 +183,19 @@ ## XXX add in parent flag merging co = compile(prog,'','exec',flags,1) return (co,globals,locals) + +def build_class(name, bases, namespace, globals): + if '__metaclass__' in namespace: + metaclass = namespace['__metaclass__'] + elif len(bases) > 0: + base = bases[0] + if hasattr(base, '__class__'): + metaclass = base.__class__ + else: + metaclass = type(base) + elif '__metaclass__' in globals: + metaclass = globals['__metaclass__'] + else: + metaclass = type + + return metaclass(name, bases, namespace) From tismer at codespeak.net Mon Jun 23 19:21:12 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 23 Jun 2003 19:21:12 +0200 (MEST) Subject: [pypy-svn] rev 1019 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030623172112.8C4B85A264@thoth.codespeak.net> Author: tismer Date: Mon Jun 23 19:21:11 2003 New Revision: 1019 Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: test for, and implement, the right exception raising on invalid calls to dict Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Mon Jun 23 19:21:11 2003 @@ -36,7 +36,11 @@ list_of_w_pairs = space.unpackiterable(args[0]) list_of_w_pairs.reverse() for pair_w in list_of_w_pairs: - k, v = space.unpackiterable(pair_w) + pair = space.unpackiterable(pair_w) + if len(pair)!=2: + raise OperationError(space.w_ValueError, + space.wrap("dict() takes a sequence of pairs")) + k, v = pair if not space.is_true(space.contains(w_kwds, k)): space.setitem(w_kwds, k, v) else: Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Mon Jun 23 19:21:11 2003 @@ -199,7 +199,12 @@ self.assertEqual(d, {'a':33, 'b':44, 23:45}) d = dict(a=33, b=44) self.assertEqual(d, {'a':33, 'b':44}) - + try: d = dict(23) + except (TypeError, ValueError): pass + else: self.fail("dict(23) should raise!") + try: d = dict([[1,2,3]]) + except (TypeError, ValueError): pass + else: self.fail("dict([[1,2,3]]) should raise!") if __name__ == '__main__': test.main() From jacob at codespeak.net Mon Jun 23 19:26:59 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Mon, 23 Jun 2003 19:26:59 +0200 (MEST) Subject: [pypy-svn] rev 1020 - in pypy/trunk/src/pypy: interpreter/test objspace/std objspace/std/test Message-ID: <20030623172659.D07E45A264@thoth.codespeak.net> Author: jacob Date: Mon Jun 23 19:26:59 2003 New Revision: 1020 Modified: pypy/trunk/src/pypy/interpreter/test/s1.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py pypy/trunk/src/pypy/objspace/std/tupleobject.py Log: Automatic adding of __ne__ of __eq__ is defined. Same for __lt__/__ge__, __gt__/__le__. Modified: pypy/trunk/src/pypy/interpreter/test/s1.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/s1.py (original) +++ pypy/trunk/src/pypy/interpreter/test/s1.py Mon Jun 23 19:26:59 2003 @@ -1,18 +1,18 @@ - -### a trivial program to test strings, lists, functions and methods ### -## tiny change wrt goal so far needed: explicit parameter to str.split - -def addstr(s1,s2): - return s1 + s2 - -str = "an interesting string" -str2 = 'another::string::xxx::y:aa' -str3 = addstr(str,str2) -arr = [] -for word in str.split(' '): - if word in str2.split('::'): - arr.append(word) -print ''.join(arr) -print "str + str2 = ", str3 - - + +### a trivial program to test strings, lists, functions and methods ### +## tiny change wrt goal so far needed: explicit parameter to str.split + +def addstr(s1,s2): + return s1 + s2 + +str = "an interesting string" +str2 = 'another::string::xxx::y:aa' +str3 = addstr(str,str2) +arr = [] +for word in str.split(' '): + if word in str2.split('::'): + arr.append(word) +print ''.join(arr) +print "str + str2 = ", str3 + + Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Mon Jun 23 19:26:59 2003 @@ -303,6 +303,17 @@ 'not': 'not_', } +class curry: + def __init__(self, fun, *args): + self.fun = fun + self.pending = args[:] + + def __call__(self, *args): + return self.fun(*(self.pending + args)) + +def inverted_comparison(function, space, w_1, w_2): + return space.not_(function(space, w_1, w_2)) + def register_all(module_dict, alt_ns=None): """register implementations for multimethods. @@ -341,6 +352,23 @@ else: getattr(StdObjSpace, funcname).register(obj, *l) + # If the module has defined eq, lt or gt, + # check if it already has ne, ge and le respectively. + # If not, then add them as space.not_ on the implemented methods. + + for method, mirror in [('eq', 'ne'), ('lt', 'ge'), ('gt', 'le')]: + try: + multifunc = StdObjSpace.__dict__[method] + mirrorfunc = StdObjSpace.__dict__[mirror] + for types, function in multifunc.dispatch_table.iteritems(): + t1, t2 = types + if t1 is t2: + if not mirrorfunc.dispatch_table.has_key(types): + mirrorfunc.register( + curry(inverted_comparison, function[0]), *[t1, t1]) + except AttributeError: + print '%s not found in StdObjSpace' % method + # import the common base W_ObjectObject as well as # default implementations of some multimethods for all objects # that don't explicitely override them or that raise FailedToImplement Modified: pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_boolobject.py Mon Jun 23 19:26:59 2003 @@ -1,28 +1,28 @@ -import autopath -from pypy.tool import test - - -class TestW_BoolObject(test.TestCase): - - def setUp(self): - self.space = test.objspace() - self.true = self.space.w_True - self.false = self.space.w_False - self.wrap = self.space.wrap - - def tearDown(self): - pass - - def test_repr(self): - self.assertEqual_w(self.space.repr(self.true), self.wrap("True")) - self.assertEqual_w(self.space.repr(self.false), self.wrap("False")) - - def test_true(self): - self.failUnless_w(self.true) - - def test_false(self): - self.failIf_w(self.false) - - -if __name__ == '__main__': - test.main() +import autopath +from pypy.tool import test + + +class TestW_BoolObject(test.TestCase): + + def setUp(self): + self.space = test.objspace() + self.true = self.space.w_True + self.false = self.space.w_False + self.wrap = self.space.wrap + + def tearDown(self): + pass + + def test_repr(self): + self.assertEqual_w(self.space.repr(self.true), self.wrap("True")) + self.assertEqual_w(self.space.repr(self.false), self.wrap("False")) + + def test_true(self): + self.failUnless_w(self.true) + + def test_false(self): + self.failIf_w(self.false) + + +if __name__ == '__main__': + test.main() Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Mon Jun 23 19:26:59 2003 @@ -69,9 +69,6 @@ def mul__Int_Tuple(space, w_int, w_tuple): return mul__Tuple_Int(space, w_tuple, w_int) -def ne__Tuple_Tuple(space, w_tuple1, w_tuple2): - return space.not_(eq__Tuple_Tuple(space, w_tuple1, w_tuple2)) - def eq__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems @@ -98,9 +95,6 @@ # No more items to compare -- compare sizes return space.newbool(len(items1) < len(items2)) -def ge__Tuple_Tuple(space, w_tuple1, w_tuple2): - return space.not_(lt__Tuple_Tuple(space, w_tuple1, w_tuple2)) - def gt__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems @@ -112,9 +106,6 @@ # No more items to compare -- compare sizes return space.newbool(len(items1) > len(items2)) -def le__Tuple_Tuple(space, w_tuple1, w_tuple2): - return space.not_(gt__Tuple_Tuple(space, w_tuple1, w_tuple2)) - def repr__Tuple(space, w_tuple): # XXX slimy! --mwh return space.wrap(repr(space.unwrap(w_tuple))) From tomek at codespeak.net Tue Jun 24 10:55:29 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Tue, 24 Jun 2003 10:55:29 +0200 (MEST) Subject: [pypy-svn] rev 1021 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624085529.51CCE5A269@thoth.codespeak.net> Author: tomek Date: Tue Jun 24 10:55:28 2003 New Revision: 1021 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: I have added replace to the string object Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 10:55:28 2003 @@ -61,8 +61,8 @@ rjust def str_rjust__String_ANY(space, w_self, w_arg): rstrip def str_rstrip__String(space, w_self): split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): -splitlines *G?nter -startswith *G?nter +splitlines *Guenter +startswith *Guenter strip def str_strip__String(space, w_self): swapcase OK title def str_title__String(space, w_self): @@ -423,6 +423,55 @@ return space.wrap(res) +def str_replace__String_String_String_Int(space, w_self, w_sub, w_by, w_maxsplit=-1): + u = space.unwrap + + input = u(w_self) + sub = u(w_sub) + by = u(w_by) + maxsplit = u(w_maxsplit) #I don't use it now + + #print "from replace, input: %s, sub: %s, by: %s" % (input, sub, by) + + #what do we have to replace? + startidx = 0 + endidx = len(input) + indices = [] + foundidx = _find(input, sub, startidx, endidx, 1) + while foundidx > -1 and (maxsplit == -1 or maxsplit > 0): + indices.append(foundidx) + if len(sub) == 0: + #so that we go forward, even if sub is empty + startidx = foundidx + 1 + else: + startidx = foundidx + len(sub) + foundidx = _find(input, sub, startidx, endidx, 1) + if maxsplit != -1: + maxsplit = maxsplit - 1 + indiceslen = len(indices) + buf = [' '] * (len(input) - indiceslen * len(sub) + indiceslen * len(by)) + startidx = 0 + + #ok, so do it + bufpos = 0 + for i in range(indiceslen): + for j in range(startidx, indices[i]): + buf[bufpos] = input[j] + bufpos = bufpos + 1 + + for j in range(len(by)): + buf[bufpos] = by[j] + bufpos = bufpos + 1 + + startidx = indices[i] + len(sub) + + for j in range(startidx, len(input)): + buf[bufpos] = input[j] + bufpos = bufpos + 1 + return space.wrap("".join(buf)) + + + def _find(self, sub, start, end, dir): length = len(self) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Tue Jun 24 10:55:28 2003 @@ -8,7 +8,6 @@ str_join = MultiMethod('join', 2) str_split = MultiMethod('split', 3, defaults=(None,-1)) - str_isdigit = MultiMethod('isdigit', 1) str_isalpha = MultiMethod('isalpha', 1) str_isspace = MultiMethod('isspace', 1) @@ -23,14 +22,12 @@ str_swapcase = MultiMethod('swapcase', 1) str_capitalize = MultiMethod('capitalize', 1) str_title = MultiMethod('title', 1) - #XXX we need to have the possibility to specify, if the a parameter - #was given str_find = MultiMethod('find', 4, defaults=(None, None)) str_rfind = MultiMethod('rfind', 4, defaults=(None, None)) str_index = MultiMethod('index', 4, defaults=(None, None)) str_rindex = MultiMethod('rindex', 4, defaults=(None, None)) + str_replace = MultiMethod('replace', 4, defaults=(-1,)) str_zfill = MultiMethod('zfill', 2) - str_strip = MultiMethod('strip', 1) str_rstrip = MultiMethod('rstrip', 1) str_lstrip = MultiMethod('lstrip', 1) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Tue Jun 24 10:55:28 2003 @@ -182,7 +182,7 @@ self.assertEquals('abc'.ljust(3), 'abc') self.assertEquals('abc'.ljust(2), 'abc') - def _test_replace(self): + def test_replace(self): self.assertEquals('one!two!three!'.replace('!', '@', 1), 'one at two!three!') self.assertEquals('one!two!three!'.replace('!', ''), 'onetwothree') self.assertEquals('one!two!three!'.replace('!', '@', 2), 'one at two@three!') @@ -199,8 +199,8 @@ self.assertEquals('abc'.replace('ab', '--', 0), 'abc') self.assertEquals('abc'.replace('xy', '--'), 'abc') self.assertEquals('123'.replace('123', ''), '') - self.assertEquals('123123'.replace(123, ''), '') - self.assertEquals('123x123'.replace(123, ''), 'x') + self.assertEquals('123123'.replace('123', ''), '') + self.assertEquals('123x123'.replace('123', ''), 'x') def _test_strip(self): From arigo at codespeak.net Tue Jun 24 11:23:01 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 11:23:01 +0200 (MEST) Subject: [pypy-svn] rev 1022 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624092301.874A95A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 11:23:00 2003 New Revision: 1022 Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: Method calls now raise TypeErrors in preference of returning NotImplemented (unless they are binary __xxx__ methods). Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Tue Jun 24 11:23:00 2003 @@ -224,6 +224,7 @@ if e.args: raise OperationError(*e.args) else: + # raise a TypeError for a FailedToImplement initialtypes = [dispatchtype(a) for a in args[:self.multimethod.arity]] if len(initialtypes) <= 1: Modified: pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py Tue Jun 24 11:23:00 2003 @@ -1,8 +1,8 @@ import autopath from pypy.tool import test -from pypy.objspace.std.typeobject import PyMultimethodCode +from pypy.objspace.std.typeobject import SpecialMultimethodCode -class TestPyMultimethodCode(test.TestCase): +class TestSpecialMultimethodCode(test.TestCase): def setUp(self): self.space = test.objspace('std') @@ -13,8 +13,8 @@ def test_int_sub(self): w = self.space.wrap for i in range(2): - meth = PyMultimethodCode(self.space.sub.multimethod, - self.space.w_int.__class__, i) + meth = SpecialMultimethodCode(self.space.sub.multimethod, + self.space.w_int.__class__, i) self.assertEqual(meth.slice().is_empty(), False) # test int.__sub__ and int.__rsub__ self.assertEqual_w(meth.eval_code(self.space, None, @@ -29,16 +29,16 @@ def test_empty_inplace_add(self): for i in range(2): - meth = PyMultimethodCode(self.space.inplace_add.multimethod, - self.space.w_int.__class__, i) + meth = SpecialMultimethodCode(self.space.inplace_add.multimethod, + self.space.w_int.__class__, i) self.assertEqual(meth.slice().is_empty(), True) def test_float_sub(self): w = self.space.wrap w(1.5) # force floatobject imported for i in range(2): - meth = PyMultimethodCode(self.space.sub.multimethod, - self.space.w_float.__class__, i) + meth = SpecialMultimethodCode(self.space.sub.multimethod, + self.space.w_float.__class__, i) self.assertEqual(meth.slice().is_empty(), False) # test float.__sub__ and float.__rsub__ Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Tue Jun 24 11:23:00 2003 @@ -94,7 +94,11 @@ code = multimethods[name] if code.bound_position < i: continue - code = PyMultimethodCode(multimethod, typeclass, i) + if len(multimethod.specialnames) > 1: + mmcls = SpecialMultimethodCode + else: + mmcls = PyMultimethodCode + code = mmcls(multimethod, typeclass, i) multimethods[name] = code # add some more multimethods with a special interface code = NextMultimethodCode(spaceclass.next, typeclass) @@ -123,30 +127,40 @@ def slice(self): return self.basemultimethod.slice(self.typeclass, self.bound_position) - def do_call(self, space, w_globals, w_locals): - """Call the multimethod, ignoring all implementations that do not - have exactly the expected type at the bound_position.""" + def prepare_args(self, space, w_globals, w_locals): multimethod = self.slice() dispatchargs = [] for i in range(multimethod.arity): w_arg = space.getitem(w_locals, space.wrap('x%d'%(i+1))) dispatchargs.append(w_arg) dispatchargs = tuple(dispatchargs) - return multimethod.get(space).perform_call(dispatchargs) + return multimethod.get(space), dispatchargs + + def do_call(self, space, w_globals, w_locals): + "Call the multimethod, raising a TypeError if not implemented." + mm, args = self.prepare_args(space, w_globals, w_locals) + return mm(*args) def eval_code(self, space, w_globals, w_locals): - "Call the multimethods, translating back information to Python." + "Call the multimethods, or raise a TypeError." + w_result = self.do_call(space, w_globals, w_locals) + # we accept a real None from operations with no return value + if w_result is None: + w_result = space.w_None + return w_result + +class SpecialMultimethodCode(PyMultimethodCode): + + def do_call(self, space, w_globals, w_locals): + "Call the multimethods, possibly returning a NotImplemented." + mm, args = self.prepare_args(space, w_globals, w_locals) try: - w_result = self.do_call(space, w_globals, w_locals) + return mm.perform_call(args) except FailedToImplement, e: if e.args: raise OperationError(*e.args) else: return space.w_NotImplemented - # we accept a real None from operations with no return value - if w_result is None: - w_result = space.w_None - return w_result class NextMultimethodCode(PyMultimethodCode): From arigo at codespeak.net Tue Jun 24 11:27:40 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 11:27:40 +0200 (MEST) Subject: [pypy-svn] rev 1023 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624092740.BA69D5A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 11:27:40 2003 New Revision: 1023 Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py Log: Speed trick. Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Tue Jun 24 11:27:40 2003 @@ -28,15 +28,8 @@ # for dispatching use the result of this function instead of directly # using .__class__ +dispatchtype = lambda obj: getattr(obj, 'dispatchtype', obj.__class__) -def dispatchtype(obj): - try: - return obj.dispatchtype - except AttributeError: - return obj.__class__ - -##def todispatchtype(cls): -## return getattr(cls,'dispatchtype',cls) class AbstractMultiMethod(object): """Abstract base class for MultiMethod and UnboundMultiMethod From hpk at codespeak.net Tue Jun 24 11:28:12 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 11:28:12 +0200 (MEST) Subject: [pypy-svn] rev 1024 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030624092812.3AD775A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 11:28:11 2003 New Revision: 1024 Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: make the test use test.objspace('std') all the time. There is no point in running this test on TrivialObjSpace Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Tue Jun 24 11:28:11 2003 @@ -80,7 +80,9 @@ self.assertNotEqual_w(wd1, wd4) class Test_DictObject(test.AppTestCase): - + + def setUp(self): + self.space = test.objspace('std') def test_clear(self): d = {1:2, 3:4} From gvanrossum at codespeak.net Tue Jun 24 11:44:04 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 11:44:04 +0200 (MEST) Subject: [pypy-svn] rev 1025 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030624094404.912175A277@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 11:44:04 2003 New Revision: 1025 Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/wrapper.py Log: Made some improvements in annspace to be able to run more of the standard tests in annspace. The failing tests now all fail with UnwrapException: W_Anything(), or they fail because we don't know anything about modules yet. M objspace.py change wrap() to always return the same wrapper for fundamental constants (None, False etc.) add and call make_builtins() (simpler than the base class's) call make_sys() clone_locals() allows W_Constant newdict() can create constant dicts as well added newlist(), newstring(), str(), setattr() change is_() to return w_False if constants differ changed iter() to call reraise() instead of raising OperationError M wrapper.py add clone() to W_Constant (returns self) unify_frames() now unifies localcells rather than w_locals compatible_frames() checks the lengths of the lists of cells rename unite_frames() to unify_frames() M cloningcontext.py rename unite_frames() to unify_frames() Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Tue Jun 24 11:44:04 2003 @@ -1,7 +1,7 @@ from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.pyframe import ControlFlowException, ExitFrame from pypy.objspace.ann.wrapper \ - import union, compatible_frames, unite_frames, W_Anything, W_Constant + import union, compatible_frames, unify_frames, W_Anything, W_Constant class FunctionInfo(object): @@ -77,7 +77,7 @@ info = self.getfunctioninfo(frame) for f in info.iterknown(frame): if compatible_frames(frame, f): - c1, c2 = unite_frames(frame, f) + c1, c2 = unify_frames(frame, f) if not c2: # A fixpoint; abandon this frame raise ExitFrame(None) Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Tue Jun 24 11:44:04 2003 @@ -1,6 +1,7 @@ import sys import operator +import pypy from pypy.interpreter.baseobjspace \ import ObjSpace, OperationError, NoValue, PyPyError from pypy.interpreter.pycode import PyByteCode @@ -22,20 +23,38 @@ def initialize(self): self.bytecodecache = {} - self.w_None = self.wrap(None) - self.w_True = self.wrap(True) - self.w_False = self.wrap(False) - self.w_NotImplemented = self.wrap(NotImplemented) - self.w_Ellipsis = self.wrap(Ellipsis) + self.wrappercache = {} + self.w_None = self.wrapboot(None) + self.w_True = self.wrapboot(True) + self.w_False = self.wrapboot(False) + self.w_NotImplemented = self.wrapboot(NotImplemented) + self.w_Ellipsis = self.wrapboot(Ellipsis) import __builtin__, types for n, c in __builtin__.__dict__.iteritems(): if isinstance(c, types.TypeType) or isinstance(c, types.ClassType): setattr(self, 'w_'+n, self.wrap(c)) self.w_builtins = self.wrap(__builtin__) + self.make_builtins() + self.make_sys() + + def make_builtins(self): + self.builtin = pypy.module.builtin.Builtin(self) # Service methods whose interface is in the abstract base class + def wrapboot(self, obj): + w_obj = self.wrap(obj) + self.wrappercache[obj] = w_obj + return w_obj + def wrap(self, obj): + try: + if obj in self.wrappercache: + return self.wrappercache[obj] + except (TypeError, AttributeError): + # This can happen when obj is not hashable, for instance + # XXX What about other errors??? + pass return W_Constant(obj) def unwrap(self, w_obj): @@ -71,7 +90,7 @@ return CloningExecutionContext(self) def clone_locals(self, w_locals): - assert isinstance(w_locals, W_KnownKeysContainer) + assert isinstance(w_locals, (W_KnownKeysContainer, W_Constant)) return w_locals.clone() @@ -84,6 +103,20 @@ return self.wrap(tuple(map(self.unwrap, args_w))) def newdict(self, items_w): + d = {} + for w_key, w_value in items_w: + try: + key = self.unwrap(w_key) + value = self.unwrap(w_value) + except UnwrapException: + break + else: + d[key] = value + else: + # All keys and values were unwrappable + return W_Constant(d) + # It's not quite constant. + # Maybe the keys are constant? values_w = {} for w_key, w_value in items_w: try: @@ -102,9 +135,41 @@ def newfunction(self, *stuff): return W_Anything() + def newlist(self, list_w): + unwrappedlist = [] + try: + for w_obj in list_w: + obj = self.unwrap(w_obj) + unwrappedlist.append(obj) + except UnwrapException: + return W_Anything() + else: + return W_Constant(unwrappedlist) + + def newstring(self, listofwrappedints): + unwrappedints = [] + try: + for w_i in listofwrappedints: + i = self.unwrap(w_i) + unwrappedints.append(i) + except UnwrapException: + return W_Anything() + else: + try: + s = "".join(map(chr, unwrappedints)) + except: + self.reraise() + return W_Constant(s) + # Methods implementing Python operations # (Many missing ones are added by make_op() below) + def str(self, w_left): + if isinstance(w_left, W_Constant): + return self.wrap(str(w_left.value)) + else: + return W_Anything() + def is_(self, w_left, w_right): if w_left is w_right: return self.w_True @@ -112,6 +177,8 @@ # XXX Is this really safe? if w_left.value is w_right.value: return self.w_True + else: + return self.w_False return W_Integer() def add(self, w_left, w_right): @@ -159,8 +226,7 @@ try: it = iter(value) except: - raise OperationError(self.wrap(AttributeError), - self.wrap(AttributeError("__iter__"))) + self.reraise() return W_Anything() def next(self, w_iterator): @@ -206,6 +272,10 @@ except: return self.reraise() + def setattr(self, w_obj, w_name, w_value): + # XXX What about the side effect? + return self.w_None + def len(self, w_obj): if isinstance(w_obj, W_KnownKeysContainer): return self.wrap(len(w_obj)) Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Tue Jun 24 11:44:04 2003 @@ -56,8 +56,14 @@ def __eq__(self, other): return type(other) is type(self) and self.value == other.value + def clone(self): + return self + class W_KnownKeysContainer(W_Object): - """A dict with constant set of keys or a tuple with known length.""" + """A dict with constant set of keys or a tuple with known length. + + XXX This may be mutable! Is that a good idea? + """ def __init__(self, args_w): self.args_w = args_w @@ -81,7 +87,7 @@ # XXX Recurse down the values? return W_KnownKeysContainer(args_w) -def unite_frames(f1, f2): +def unify_frames(f1, f2): """Given two compatible frames, make them the same. This changes both f1 and f2 in-place to change all the values into @@ -112,27 +118,29 @@ c2 = True s2[i] = u - # Compare locals - # XXX uses W_KnownKeysContainer internals - assert isinstance(f1.w_locals, W_KnownKeysContainer) - assert isinstance(f2.w_locals, W_KnownKeysContainer) - l1 = f1.w_locals.args_w - l2 = f2.w_locals.args_w - keydict = {} # compute set of keys - for key in l1.iterkeys(): - keydict[key] = 1 - for key in l2.iterkeys(): - keydict[key] = 1 - for key in keydict.iterkeys(): - v1 = l1.get(key, W_Undefined()) - v2 = l2.get(key, W_Undefined()) + # Compare locals. + # XXX This uses the fast locals now and ignores w_locals. + # XXX What about nested cells? + l1 = f1.localcells + l2 = f2.localcells + assert len(l1) == len(l2) + for i in range(len(l1)): + try: + v1 = l1[i].get() + except ValueError: + v1 = W_Undefined() + try: + v2 = l2[i].get() + except ValueError: + v2 = W_Undefined() u = union(v1, v2) if v1 != u: c1 = True - l1[key] = u + l1[i].set(u) if v2 != u: c2 = True - l2[key] = u + l2[i].set(u) + return c1, c2 def compatible_frames(f1, f2): @@ -147,6 +155,8 @@ return (f1.next_instr == f2.next_instr and f1.space is f2.space and f2.bytecode is f2.bytecode and + len(f1.localcells) == len(f2.localcells) and + len(f1.nestedcells) == len(f2.nestedcells) and f1.valuestack.depth() == f2.valuestack.depth() and equivalent(f1.w_globals, f2.w_globals) and equivalent(f1.w_builtins, f2.w_builtins) and From jacob at codespeak.net Tue Jun 24 11:48:45 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Tue, 24 Jun 2003 11:48:45 +0200 (MEST) Subject: [pypy-svn] rev 1026 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624094845.590165A277@thoth.codespeak.net> Author: jacob Date: Tue Jun 24 11:48:44 2003 New Revision: 1026 Modified: pypy/trunk/src/pypy/objspace/std/listobject.py Log: Added gt__List_List Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Tue Jun 24 11:48:44 2003 @@ -123,7 +123,6 @@ return b def lt__List_List(space, w_list1, w_list2): - # XXX list_le, list_gt, list_ge, list_ne must also be explicitely done items1 = w_list1.ob_item items2 = w_list2.ob_item ncmp = _min(w_list1.ob_size, w_list2.ob_size) @@ -134,6 +133,17 @@ # No more items to compare -- compare sizes return space.newbool(w_list1.ob_size < w_list2.ob_size) +def gt__List_List(space, w_list1, w_list2): + items1 = w_list1.ob_item + items2 = w_list2.ob_item + ncmp = _min(w_list1.ob_size, w_list2.ob_size) + # Search for the first index where items are different + for p in range(ncmp): + if not space.is_true(space.eq(items1[p], items2[p])): + return space.gt(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(w_list1.ob_size > w_list2.ob_size) + # upto here, lists are nearly identical to tuples, despite the # fact that we now support over-allocation! From tismer at codespeak.net Tue Jun 24 11:56:12 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 24 Jun 2003 11:56:12 +0200 (MEST) Subject: [pypy-svn] rev 1027 - pypy/trunk/src/pypy/tool Message-ID: <20030624095612.5F8AC5A269@thoth.codespeak.net> Author: tismer Date: Tue Jun 24 11:56:12 2003 New Revision: 1027 Modified: pypy/trunk/src/pypy/tool/test.py Log: added option for individual timing (simple but works) Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Tue Jun 24 11:56:12 2003 @@ -61,8 +61,7 @@ self.successes.append(test) class MyTextTestResult(unittest._TextTestResult): - def addFailure(self, test, err): - unittest._TextTestResult.addFailure(self, test, err) + def munge(self, list, test, err): import StringIO from pypy.interpreter.baseobjspace import OperationError @@ -195,6 +194,10 @@ testreldir = 0 runcts = 0 spacename = '' + individualtime=0 + def ensure_value(*args): + return 0 + ensure_value = staticmethod(ensure_value) class RegexFilterFunc: """ stateful function to filter included/excluded strings via @@ -228,6 +231,9 @@ '-r', action="store_true", dest="testreldir", help="gather only tests relative to current dir")) options.append(make_option( + '-i', action="store_true", dest="individualtime", + help="time each test individually")) + options.append(make_option( '-c', action="store_true", dest="runcts", help="run CtsTestRunner (catches stdout and prints report " "after testing) [unix only, for now]")) @@ -263,7 +269,15 @@ suite = testsuite_from_main() else: suite = testsuite_from_dir(root, filterfunc, 1) - run_tests(suite) + if Options.individualtime and hasattr(suite, '_tests'): + for test in suite._tests: + if hasattr(test, '_tests'): + for subtest in test._tests: + run_tests(subtest) + else: + run_tests(test) + else: + run_tests(suite) if __name__ == '__main__': # test all of pypy From hpk at codespeak.net Tue Jun 24 11:59:24 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 11:59:24 +0200 (MEST) Subject: [pypy-svn] rev 1028 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624095924.1B68D5A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 11:59:23 2003 New Revision: 1028 Modified: pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/test/test_listobject.py Log: fixed the "extend" method for lists. added a test for it. previously it wouldn't do "[].extend((1,))". Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Tue Jun 24 11:59:23 2003 @@ -266,7 +266,7 @@ _ins1(w_list, w_list.ob_size, w_any) return space.w_None -def list_extend__List_List(space, w_list, w_any): +def list_extend__List_ANY(space, w_list, w_any): lis = space.unpackiterable(w_any) newlen = w_list.ob_size + len(lis) _list_resize(w_list, newlen) Modified: pypy/trunk/src/pypy/objspace/std/test/test_listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_listobject.py Tue Jun 24 11:59:23 2003 @@ -275,5 +275,18 @@ self.assertEqual_w(self.space.le(w_list4, w_list3), self.space.w_True) +class AppTestW_ListObject(test.AppTestCase): + def setUp(self): + self.space = test.objspace('std') + def test_extend_list(self): + l = [1] + l.extend([2]) + self.assertEquals(l, [1,2]) + + def test_extend_tuple(self): + l = [1] + l.extend((2,)) + self.assertEquals(l, [1,2]) + if __name__ == '__main__': test.main() From hpk at codespeak.net Tue Jun 24 12:00:12 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 12:00:12 +0200 (MEST) Subject: [pypy-svn] rev 1029 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624100012.955215A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 12:00:12 2003 New Revision: 1029 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: added an iter-method + test to strings. Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 12:00:12 2003 @@ -816,6 +816,9 @@ return w_str +def iter__String(space, w_list): + import iterobject + return iterobject.W_SeqIterObject(space, w_list) def repr__String(space, w_str): # XXX this is bogus -- mwh Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Tue Jun 24 12:00:12 2003 @@ -126,6 +126,9 @@ # self.assertEqual_w(w(s).ljust(5), w(s + " ")) class TestStringObject(test.AppTestCase): + def setUp(self): + self.space = test.objspace('std') + def test_split(self): self.assertEquals("".split(), []) self.assertEquals("a".split(), ['a']) @@ -360,5 +363,11 @@ self.assertEquals("aaa AAA 111".swapcase(), "AAA aaa 111") self.assertEquals("".swapcase(), "") + def test_iter(self): + l=[] + for i in iter("42"): + l.append(i) + self.assertEquals(l, ['4','2']) + if __name__ == '__main__': test.main() From tomek at codespeak.net Tue Jun 24 12:34:27 2003 From: tomek at codespeak.net (tomek at codespeak.net) Date: Tue, 24 Jun 2003 12:34:27 +0200 (MEST) Subject: [pypy-svn] rev 1030 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624103427.6FA655A269@thoth.codespeak.net> Author: tomek Date: Tue Jun 24 12:34:26 2003 New Revision: 1030 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/stringobject.py Log: A small error patched, space.w_ValueError is now , not UnicodeError Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Tue Jun 24 12:34:26 2003 @@ -130,7 +130,7 @@ base = done[b.__name__] newtype = self.call_function( self.w_type, - w(k), + w(v), self.newtuple([base]), self.newdict([])) setattr(self, Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 12:34:26 2003 @@ -55,9 +55,9 @@ ljust def str_ljust__String_ANY(space, w_self, w_arg): lower OK lstrip def str_lstrip__String(space, w_self): -replace *Tomek -rfind OK, nur noch tests -rindex OK, nur noch tests +replace OK +rfind OK +rindex OK rjust def str_rjust__String_ANY(space, w_self, w_arg): rstrip def str_rstrip__String(space, w_self): split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): @@ -68,7 +68,7 @@ title def str_title__String(space, w_self): translate upper def str_upper__String(space, w_self): -zfill *Tomek +zfill OK """ from pypy.objspace.std.objspace import * @@ -405,6 +405,7 @@ (self, sub, start, end) = _convert_idx_params(space, w_self, w_sub, w_start, w_end) res = _find(self, sub, start, end, 1) + print space.w_ValueError if res == -1: raise OperationError(space.w_ValueError, space.wrap("substring not found in string.index")) From arigo at codespeak.net Tue Jun 24 12:40:24 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 12:40:24 +0200 (MEST) Subject: [pypy-svn] rev 1031 - pypy/trunk/src/pypy/interpreter Message-ID: <20030624104024.3EC125A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 12:40:23 2003 New Revision: 1031 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py Log: added the isinstance() convenient method on BaseObjectSpace. Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Tue Jun 24 12:40:23 2003 @@ -152,7 +152,11 @@ def call_function(self, w_func, *args_w, **kw_w): w_kw = self.newdict([(self.wrap(k), w_v) for k, w_v in kw_w.iteritems()]) return self.call(w_func, self.newtuple(list(args_w)), w_kw) - + + def isinstance(self, w_obj, w_type): + w_objtype = self.type(w_obj) + return self.issubtype(w_objtype, w_type) + ## Table describing the regular part of the interface of object spaces, ## namely all methods which only take w_ arguments and return a w_ result ## (if any). XXX Maybe we should say that these methods must be accessed From tismer at codespeak.net Tue Jun 24 12:43:53 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 24 Jun 2003 12:43:53 +0200 (MEST) Subject: [pypy-svn] rev 1032 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030624104353.448A05A269@thoth.codespeak.net> Author: tismer Date: Tue Jun 24 12:43:52 2003 New Revision: 1032 Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: re-wrote test of new() in interpreter space because it was too slow Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Tue Jun 24 12:43:52 2003 @@ -79,6 +79,35 @@ wd5 = self.space.newdict([(w3, w3)]) self.assertNotEqual_w(wd1, wd4) + def test_dict_call(self): + space = self.space + w = space.wrap + wd = space.newdict + def mydict(w_args=w(()), w_kwds=w({})): + return space.new(space.w_dict, w_args, w_kwds) + def deepwrap(lp): + return [[w(a),w(b)] for a,b in lp] + d = mydict() + self.assertEqual_w(d, w({})) + args = w([[['a',2],[23,45]]]) + d = mydict(args) + self.assertEqual_w(d, wd(deepwrap([['a',2],[23,45]]))) + d = mydict(args, w({'a':33, 'b':44})) + self.assertEqual_w(d, wd(deepwrap([['a',33],['b',44],[23,45]]))) + d = mydict(w_kwds=w({'a':33, 'b':44})) + self.assertEqual_w(d, wd(deepwrap([['a',33],['b',44]]))) + self.assertRaises_w(space.w_TypeError, mydict, w([23])) + self.assertRaises_w(space.w_ValueError, mydict, w([[[1,2,3]]])) + ''' + try: d = dict(23) + except (TypeError, ValueError): pass + else: self.fail("dict(23) should raise!") + try: d = dict([[1,2,3]]) + except (TypeError, ValueError): pass + else: self.fail("dict([[1,2,3]]) should raise!") + ''' + + class Test_DictObject(test.AppTestCase): def setUp(self): @@ -190,14 +219,13 @@ vals.sort() self.assertEqual(vals, [2,4]) - def test_new(self): + def tooslow_test_new(self): d = dict() self.assertEqual(d, {}) - d = dict([]) - self.assertEqual(d, {}) - d = dict([['a',2], [23,45]]) + args = [['a',2], [23,45]] + d = dict(args) self.assertEqual(d, {'a':2, 23:45}) - d = dict([['a',2], [23,45]], a=33, b=44) + d = dict(args, a=33, b=44) self.assertEqual(d, {'a':33, 'b':44, 23:45}) d = dict(a=33, b=44) self.assertEqual(d, {'a':33, 'b':44}) From arigo at codespeak.net Tue Jun 24 12:46:01 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 12:46:01 +0200 (MEST) Subject: [pypy-svn] rev 1033 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624104601.7F01F5A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 12:46:00 2003 New Revision: 1033 Modified: pypy/trunk/src/pypy/objspace/std/booltype.py pypy/trunk/src/pypy/objspace/std/dicttype.py pypy/trunk/src/pypy/objspace/std/floattype.py pypy/trunk/src/pypy/objspace/std/functype.py pypy/trunk/src/pypy/objspace/std/generatortype.py pypy/trunk/src/pypy/objspace/std/instmethtype.py pypy/trunk/src/pypy/objspace/std/inttype.py pypy/trunk/src/pypy/objspace/std/itertype.py pypy/trunk/src/pypy/objspace/std/listtype.py pypy/trunk/src/pypy/objspace/std/moduletype.py pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/nonetype.py pypy/trunk/src/pypy/objspace/std/nulltype.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/slicetype.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/tupletype.py pypy/trunk/src/pypy/objspace/std/typetype.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: More speed-up tricks, plus the addition of a call to registerimplementation() for all W_XxxType classes as well. Modified: pypy/trunk/src/pypy/objspace/std/booltype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/booltype.py (original) +++ pypy/trunk/src/pypy/objspace/std/booltype.py Tue Jun 24 12:46:00 2003 @@ -11,3 +11,5 @@ typename = 'bool' staticbases = (W_IntType,) + +registerimplementation(W_BoolType) Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Tue Jun 24 12:46:00 2003 @@ -25,7 +25,9 @@ dict_iteritems = MultiMethod('iteritems', 1) dict_iterkeys = MultiMethod('iterkeys', 1) dict_itervalues = MultiMethod('itervalues', 1) - + +registerimplementation(W_DictType) + # XXX we'll worry about the __new__/__init__ distinction later def dicttype_new(space, w_listtype, w_args, w_kwds): # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed Modified: pypy/trunk/src/pypy/objspace/std/floattype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floattype.py (original) +++ pypy/trunk/src/pypy/objspace/std/floattype.py Tue Jun 24 12:46:00 2003 @@ -6,6 +6,8 @@ typename = 'float' +registerimplementation(W_FloatType) + def new__FloatType_ANY_ANY(space, w_inttype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, Modified: pypy/trunk/src/pypy/objspace/std/functype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/functype.py (original) +++ pypy/trunk/src/pypy/objspace/std/functype.py Tue Jun 24 12:46:00 2003 @@ -5,3 +5,5 @@ class W_FuncType(W_TypeObject): typename = 'FunctionType' + +registerimplementation(W_FuncType) Modified: pypy/trunk/src/pypy/objspace/std/generatortype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/generatortype.py (original) +++ pypy/trunk/src/pypy/objspace/std/generatortype.py Tue Jun 24 12:46:00 2003 @@ -5,3 +5,5 @@ class W_GeneratorType(W_TypeObject): typename = 'GeneratorType' + +registerimplementation(W_GeneratorType) Modified: pypy/trunk/src/pypy/objspace/std/instmethtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethtype.py Tue Jun 24 12:46:00 2003 @@ -9,3 +9,5 @@ class W_InstMethType(W_TypeObject): typename = 'MethodType' + +registerimplementation(W_InstMethType) Modified: pypy/trunk/src/pypy/objspace/std/inttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/inttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/inttype.py Tue Jun 24 12:46:00 2003 @@ -6,6 +6,8 @@ typename = 'int' +registerimplementation(W_IntType) + # XXX we'll worry about the __new__/__init__ distinction later def inttype_new(space, w_inttype, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/itertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/itertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/itertype.py Tue Jun 24 12:46:00 2003 @@ -8,3 +8,5 @@ class W_SeqIterType(W_TypeObject): typename = 'SeqIterType' + +registerimplementation(W_SeqIterType) Modified: pypy/trunk/src/pypy/objspace/std/listtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/listtype.py Tue Jun 24 12:46:00 2003 @@ -16,6 +16,8 @@ list_reverse= MultiMethod('reverse',1) list_sort = MultiMethod('sort', 1) +registerimplementation(W_ListType) + # XXX right now, this is responsible for building a whole new list # XXX we'll worry about the __new__/__init__ distinction later Modified: pypy/trunk/src/pypy/objspace/std/moduletype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/moduletype.py (original) +++ pypy/trunk/src/pypy/objspace/std/moduletype.py Tue Jun 24 12:46:00 2003 @@ -5,3 +5,5 @@ class W_ModuleType(W_TypeObject): typename = 'module' + +registerimplementation(W_ModuleType) Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Tue Jun 24 12:46:00 2003 @@ -26,10 +26,6 @@ # one may be automatically registered in the other one to keep # them in sync. -# for dispatching use the result of this function instead of directly -# using .__class__ -dispatchtype = lambda obj: getattr(obj, 'dispatchtype', obj.__class__) - class AbstractMultiMethod(object): """Abstract base class for MultiMethod and UnboundMultiMethod @@ -44,6 +40,11 @@ self.cache_table = {} def register(self, function, *types): + for type in types: + if (hasattr(type, 'dispatchclass') and + 'dispatchclass' not in type.__dict__): + raise error, ('looks like you forgot to call\n' + 'registerimplementation(%r)' % type) # W_ANY can be used as a placeholder to dispatch on any value. functions = self.dispatch_table.setdefault(types, []) if function not in functions: @@ -201,7 +202,7 @@ class BoundMultiMethod: - ASSERT_BASE_TYPE = None + #ASSERT_BASE_TYPE = None def __init__(self, space, multimethod): self.space = space @@ -218,7 +219,7 @@ raise OperationError(*e.args) else: # raise a TypeError for a FailedToImplement - initialtypes = [dispatchtype(a) + initialtypes = [a.dispatchclass for a in args[:self.multimethod.arity]] if len(initialtypes) <= 1: plural = "" @@ -235,15 +236,15 @@ arity = self.multimethod.arity extraargs = args[arity:] - if self.ASSERT_BASE_TYPE: - for a in args[:arity]: - assert issubclass(dispatchtype(a), self.ASSERT_BASE_TYPE), ( - "multimethod '%s' call with non wrapped argument: %r" % - (self.multimethod.operatorsymbol, a)) +## if self.ASSERT_BASE_TYPE: +## for a in args[:arity]: +## assert issubclass(a.dispatchclass, self.ASSERT_BASE_TYPE), ( +## "multimethod '%s' call with non wrapped argument: %r" % +## (self.multimethod.operatorsymbol, a)) # look for an exact match first firstfailure = None - types = tuple([(dispatchtype(a),) for a in args]) + types = tuple([(a.dispatchclass,) for a in args]) choicelist = self.multimethod.buildchoices(types) for signature, function in choicelist: try: @@ -281,7 +282,7 @@ else: converted = function(self.space, curobjs[t]) if not isinstance(converted, list): - converted = [(dispatchtype(converted), + converted = [(converted.dispatchclass, converted)] for t, a in converted: if t not in curobjs: Modified: pypy/trunk/src/pypy/objspace/std/nonetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/nonetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/nonetype.py Tue Jun 24 12:46:00 2003 @@ -5,3 +5,5 @@ class W_NoneType(W_TypeObject): typename = 'NoneType' + +registerimplementation(W_NoneType) Modified: pypy/trunk/src/pypy/objspace/std/nulltype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/nulltype.py (original) +++ pypy/trunk/src/pypy/objspace/std/nulltype.py Tue Jun 24 12:46:00 2003 @@ -5,3 +5,5 @@ class W_NullType(W_TypeObject): typename = 'NullType' + +registerimplementation(W_NullType) Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Tue Jun 24 12:46:00 2003 @@ -20,6 +20,8 @@ object_str = StdObjSpace.str object_hash = StdObjSpace.hash +registerimplementation(W_ObjectType) + # XXX we'll worry about the __new__/__init__ distinction later def new__ObjectType_ANY_ANY(space, w_objecttype, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Tue Jun 24 12:46:00 2003 @@ -22,7 +22,7 @@ W_ANY = W_Object # synonyms for use in .register() -BoundMultiMethod.ASSERT_BASE_TYPE = W_Object +#BoundMultiMethod.ASSERT_BASE_TYPE = W_Object MultiMethod.BASE_TYPE_OBJECT = W_AbstractTypeObject # delegation priorities @@ -36,6 +36,7 @@ # it may be modified to take 'statictype' instead of requiring it to be # stored in 'implcls' itself assert issubclass(implcls, W_Object) + implcls.__dict__.setdefault('dispatchclass', implcls) ################################################################## Modified: pypy/trunk/src/pypy/objspace/std/slicetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/slicetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/slicetype.py Tue Jun 24 12:46:00 2003 @@ -6,6 +6,8 @@ typename = 'slice' +registerimplementation(W_SliceType) + def slicetype_new(space, w_slicetype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Tue Jun 24 12:46:00 2003 @@ -1,4 +1,4 @@ -from pypy.objspace.std.objspace import MultiMethod, StdObjSpace, W_ANY, register_all +from pypy.objspace.std.objspace import * from typeobject import W_TypeObject @@ -38,6 +38,8 @@ str_splitlines = MultiMethod('splitlines', 2) str_startswith = MultiMethod('startswith', 2) #[optional arguments not supported now] +registerimplementation(W_StringType) + # XXX we'll worry about the __new__/__init__ distinction later def new__StringType_ANY_ANY(space, w_stringtype, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupletype.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupletype.py Tue Jun 24 12:46:00 2003 @@ -6,6 +6,8 @@ typename = 'tuple' +registerimplementation(W_TupleType) + # XXX we'll worry about the __new__/__init__ distinction later def tupletype_new(space, w_tupletype, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Tue Jun 24 12:46:00 2003 @@ -1,5 +1,5 @@ from pypy.objspace.std.objspace import * -from typeobject import W_TypeObject +from typeobject import W_TypeObject, NewMultimethodCode class W_TypeType(W_TypeObject): @@ -8,6 +8,8 @@ typename = 'type' +registerimplementation(W_TypeType) + # XXX we'll worry about the __new__/__init__ distinction later def new__TypeType_ANY_ANY(space, w_typetype, w_args, w_kwds): Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Tue Jun 24 12:46:00 2003 @@ -42,6 +42,8 @@ raise KeyError return w_value +registerimplementation(W_UserType) + # XXX we'll worry about the __new__/__init__ distinction later # XXX NOTE: currently (03-06-21) user-object can only sublass # types which register an implementation for 'new' -- currently From arigo at codespeak.net Tue Jun 24 12:48:24 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 12:48:24 +0200 (MEST) Subject: [pypy-svn] rev 1034 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624104824.D026C5A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 12:48:24 2003 New Revision: 1034 Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/typeobject.py Log: allow * and ** arguments in multimethods called by Python Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Tue Jun 24 12:48:24 2003 @@ -88,7 +88,7 @@ class MultiMethod(AbstractMultiMethod): - def __init__(self, operatorsymbol, arity, specialnames=None, defaults=()): + def __init__(self, operatorsymbol, arity, specialnames=None, **extras): "MultiMethod dispatching on the first 'arity' arguments." AbstractMultiMethod.__init__(self, operatorsymbol, arity) if arity < 1: @@ -96,7 +96,7 @@ if specialnames is None: specialnames = [operatorsymbol] self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__'] - self.defaults = defaults + self.extras = extras self.unbound_versions = {} def __get__(self, space, cls=object): # cls is some W_xxxType Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Tue Jun 24 12:48:24 2003 @@ -114,15 +114,19 @@ argnames = ['x%d'%(i+1) for i in range(multimethod.arity)] argnames.insert(0, argnames.pop(bound_position)) self.co_name = multimethod.operatorsymbol - self.co_flags = 0 self.co_varnames = tuple(argnames) self.co_argcount = multimethod.arity + self.co_flags = 0 + if multimethod.extras.get('varargs', False): + self.co_flags |= pycode.CO_VARARGS + if multimethod.extras.get('keywords', False): + self.co_flags |= pycode.CO_VARKEYWORDS self.basemultimethod = multimethod self.typeclass = typeclass self.bound_position = bound_position def getdefaults(self, space): - return space.wrap(self.basemultimethod.defaults) + return space.wrap(self.basemultimethod.extras.get('defaults', ())) def slice(self): return self.basemultimethod.slice(self.typeclass, self.bound_position) From jacob at codespeak.net Tue Jun 24 13:11:46 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Tue, 24 Jun 2003 13:11:46 +0200 (MEST) Subject: [pypy-svn] rev 1035 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624111146.D1DDE5A269@thoth.codespeak.net> Author: jacob Date: Tue Jun 24 13:11:45 2003 New Revision: 1035 Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py pypy/trunk/src/pypy/objspace/std/cpythonobject.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/floatobject.py pypy/trunk/src/pypy/objspace/std/floattype.py pypy/trunk/src/pypy/objspace/std/funcobject.py pypy/trunk/src/pypy/objspace/std/instmethobject.py pypy/trunk/src/pypy/objspace/std/iterobject.py pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/noneobject.py pypy/trunk/src/pypy/objspace/std/nullobject.py pypy/trunk/src/pypy/objspace/std/objectobject.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/sliceobject.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/tupleobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/typetype.py pypy/trunk/src/pypy/objspace/std/userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: Refactored register_all to live in its own module. Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Tue Jun 24 13:11:45 2003 @@ -7,6 +7,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from booltype import W_BoolType import intobject Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py Tue Jun 24 13:11:45 2003 @@ -10,6 +10,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from stringobject import W_StringObject import sys, operator, types Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Tue Jun 24 13:11:45 2003 @@ -1,6 +1,7 @@ """Default implementation for some operation.""" from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all # These are operations that must fall back to some default behavior, Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 24 13:11:45 2003 @@ -6,6 +6,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from dicttype import W_DictType, _no_object from stringobject import W_StringObject from pypy.interpreter.extmodule import make_builtin_func Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/floatobject.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from floattype import W_FloatType ############################################################## Modified: pypy/trunk/src/pypy/objspace/std/floattype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floattype.py (original) +++ pypy/trunk/src/pypy/objspace/std/floattype.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Tue Jun 24 13:11:45 2003 @@ -1,5 +1,6 @@ from __future__ import nested_scopes from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from functype import W_FuncType import pypy.interpreter.pyframe from pypy.objspace.std.instmethobject import W_InstMethObject Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Tue Jun 24 13:11:45 2003 @@ -15,6 +15,7 @@ from __future__ import nested_scopes from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from instmethtype import W_InstMethType Modified: pypy/trunk/src/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/iterobject.py Tue Jun 24 13:11:45 2003 @@ -5,6 +5,7 @@ for function-iteration. """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from itertype import W_SeqIterType Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from listtype import W_ListType from intobject import W_IntObject from sliceobject import W_SliceObject Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/noneobject.py Tue Jun 24 13:11:45 2003 @@ -5,6 +5,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from nonetype import W_NoneType class W_NoneObject(W_Object): Modified: pypy/trunk/src/pypy/objspace/std/nullobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/nullobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/nullobject.py Tue Jun 24 13:11:45 2003 @@ -5,6 +5,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from nulltype import W_NullType class W_NullObject(W_Object): Modified: pypy/trunk/src/pypy/objspace/std/objectobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objectobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/objectobject.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all class W_ObjectObject(W_Object): Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Tue Jun 24 13:11:45 2003 @@ -298,78 +298,6 @@ setattr(StdObjSpace, _name, MultiMethod(_symbol, _arity, _specialnames)) -_name_mappings = { - 'and': 'and_', - 'or': 'or_', - 'not': 'not_', - } - -class curry: - def __init__(self, fun, *args): - self.fun = fun - self.pending = args[:] - - def __call__(self, *args): - return self.fun(*(self.pending + args)) - -def inverted_comparison(function, space, w_1, w_2): - return space.not_(function(space, w_1, w_2)) - -def register_all(module_dict, alt_ns=None): - """register implementations for multimethods. - - By default a (name, object) pair of the given module dictionary - is registered on the multimethod 'name' of StdObjSpace. - If the name doesn't exist then the alternative namespace is tried - for registration. - """ - - for name, obj in module_dict.items(): - if name.find('__')<1: - continue - funcname, sig = name.split('__') - l=[] - for i in sig.split('_'): - if i == 'ANY': - icls = W_ANY - else: - icls = (module_dict.get('W_%s' % i) or - module_dict.get('W_%sObject' % i)) - if icls is None: - raise ValueError, \ - "no W_%s or W_%sObject for the definition of %s" % ( - i, i, name) - l.append(icls) - - if len(l) != obj.func_code.co_argcount-1: - raise ValueError, \ - "function name %s doesn't specify exactly %d arguments" % ( - repr(name), obj.func_code.co_argcount-1) - - funcname = _name_mappings.get(funcname, funcname) - - if hasattr(alt_ns, funcname): - getattr(alt_ns, funcname).register(obj, *l) - else: - getattr(StdObjSpace, funcname).register(obj, *l) - - # If the module has defined eq, lt or gt, - # check if it already has ne, ge and le respectively. - # If not, then add them as space.not_ on the implemented methods. - - for method, mirror in [('eq', 'ne'), ('lt', 'ge'), ('gt', 'le')]: - try: - multifunc = StdObjSpace.__dict__[method] - mirrorfunc = StdObjSpace.__dict__[mirror] - for types, function in multifunc.dispatch_table.iteritems(): - t1, t2 = types - if t1 is t2: - if not mirrorfunc.dispatch_table.has_key(types): - mirrorfunc.register( - curry(inverted_comparison, function[0]), *[t1, t1]) - except AttributeError: - print '%s not found in StdObjSpace' % method - # import the common base W_ObjectObject as well as # default implementations of some multimethods for all objects # that don't explicitely override them or that raise FailedToImplement Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Tue Jun 24 13:11:45 2003 @@ -6,6 +6,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from pypy.interpreter.appfile import AppFile from pypy.interpreter.extmodule import make_builtin_func from pypy.objspace.std.instmethobject import W_InstMethObject Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 13:11:45 2003 @@ -72,6 +72,7 @@ """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from stringtype import W_StringType from intobject import W_IntObject from sliceobject import W_SliceObject Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from tupletype import W_TupleType from intobject import W_IntObject from sliceobject import W_SliceObject Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Tue Jun 24 13:11:45 2003 @@ -1,4 +1,5 @@ from pypy.interpreter import pycode +from pypy.objspace.std.register_all import register_all from pypy.objspace.std.objspace import * Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Tue Jun 24 13:11:45 2003 @@ -1,7 +1,7 @@ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject, NewMultimethodCode - class W_TypeType(W_TypeObject): """The single instance of this class is the object the user sees as '__builtin__.type'.""" Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Tue Jun 24 13:11:45 2003 @@ -7,6 +7,7 @@ as well as of normal and special attributes. """ from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all from usertype import W_UserType import typeobject Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Tue Jun 24 13:11:45 2003 @@ -3,6 +3,7 @@ """ from __future__ import nested_scopes from pypy.objspace.std.objspace import * +from pypy.objspace.std.register_all import register_all import typeobject, objecttype from typeobject import W_TypeObject From tismer at codespeak.net Tue Jun 24 13:38:30 2003 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 24 Jun 2003 13:38:30 +0200 (MEST) Subject: [pypy-svn] rev 1036 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624113830.BF7495A269@thoth.codespeak.net> Author: tismer Date: Tue Jun 24 13:38:30 2003 New Revision: 1036 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/dictobject_app.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: optimization of both tests and implementations (pop, get) because it was too slow Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 24 13:38:30 2003 @@ -175,9 +175,12 @@ w_item = w_self.space.gethelper(applicationfile).call("dict_popitem", [w_self]) return w_item -def dict_get__Dict_ANY_ANY(space, w_self, w_key, w_default): - w_value = w_self.space.gethelper(applicationfile).call("dict_get", [w_self, w_key, w_default]) - return w_value +def dict_get__Dict_ANY_ANY(space, w_self, w_lookup, w_default): + data = w_self.non_empties() + for w_key, cell in data: + if space.is_true(space.eq(w_lookup, w_key)): + return cell.get() + return w_default def dict_setdefault__Dict_ANY_ANY(space, w_self, w_key, w_default): w_value = w_self.space.gethelper(applicationfile).call("dict_setdefault", [w_self, w_key, w_default]) @@ -186,9 +189,9 @@ def dict_pop__Dict_ANY_ANY(space, w_self, w_key, w_default): default = space.unwrap(w_default) if default is _no_object: - w_value = w_self.space.gethelper(applicationfile).call("dict_pop", [w_self, w_key]) + w_value = w_self.space.gethelper(applicationfile).call("dict_pop_no_default", [w_self, w_key]) else: - w_value = w_self.space.gethelper(applicationfile).call("dict_pop", [w_self, w_key, w_default]) + w_value = w_self.space.gethelper(applicationfile).call("dict_pop_with_default", [w_self, w_key, w_default]) return w_value def dict_iteritems__Dict(space, w_self): Modified: pypy/trunk/src/pypy/objspace/std/dictobject_app.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject_app.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject_app.py Tue Jun 24 13:38:30 2003 @@ -21,14 +21,17 @@ d[k] = v return v -class __unique: pass +def dict_pop_no_default(d, k): + v = d[k] + del d[k] + return v -def dict_pop(d, k, v=__unique): - if d.has_key(k): +def dict_pop_with_default(d, k, v): + try: v = d[k] del d[k] - if v is __unique: - raise KeyError, k + except KeyError: + pass return v def dict_iteritems(d): Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Tue Jun 24 13:38:30 2003 @@ -98,14 +98,45 @@ self.assertEqual_w(d, wd(deepwrap([['a',33],['b',44]]))) self.assertRaises_w(space.w_TypeError, mydict, w([23])) self.assertRaises_w(space.w_ValueError, mydict, w([[[1,2,3]]])) - ''' - try: d = dict(23) - except (TypeError, ValueError): pass - else: self.fail("dict(23) should raise!") - try: d = dict([[1,2,3]]) - except (TypeError, ValueError): pass - else: self.fail("dict([[1,2,3]]) should raise!") - ''' + + def test_dict_pop(self): + space = self.space + w = space.wrap + wd = space.newdict + def mydict(w_args=w(()), w_kwds=w({})): + return space.new(space.w_dict, w_args, w_kwds) + def deepwrap(lp): + return [[w(a),w(b)] for a,b in lp] + d = mydict(w_kwds=w({1:2, 3:4})) + dd = mydict(w_kwds=w({1:2, 3:4})) # means d.copy() + pop = space.getattr(dd, w("pop")) + result = space.call_function(pop, w(1)) + self.assertEqual_w(result, w(2)) + self.assertEqual_w(space.len(dd), w(1)) + + dd = mydict(w_kwds=w({1:2, 3:4})) # means d.copy() + pop = space.getattr(dd, w("pop")) + result = space.call_function(pop, w(1), w(44)) + self.assertEqual_w(result, w(2)) + self.assertEqual_w(space.len(dd), w(1)) + result = space.call_function(pop, w(1), w(44)) + self.assertEqual_w(result, w(44)) + self.assertEqual_w(space.len(dd), w(1)) + + self.assertRaises_w(space.w_KeyError, space.call_function, pop, w(33)) + + def test_get(self): + space = self.space + w = space.wrap + def mydict(w_args=w(()), w_kwds=w({})): + return space.new(space.w_dict, w_args, w_kwds) + d = mydict(w_kwds=w({1:2, 3:4})) + get = space.getattr(d, w("get")) + self.assertEqual_w(space.call_function(get, w(1)), w(2)) + self.assertEqual_w(space.call_function(get, w(1), w(44)), w(2)) + self.assertEqual_w(space.call_function(get, w(33)), w(None)) + self.assertEqual_w(space.call_function(get, w(33), w(44)), w(44)) + class Test_DictObject(test.AppTestCase): @@ -124,14 +155,14 @@ self.assertEqual(d, dd) self.failIf(d is dd) - def test_get(self): + def tooslow_test_get(self): d = {1:2, 3:4} self.assertEqual(d.get(1), 2) self.assertEqual(d.get(1,44), 2) self.assertEqual(d.get(33), None) self.assertEqual(d.get(33,44), 44) - def test_pop(self): + def tooslow_test_pop(self): d = {1:2, 3:4} dd = d.copy() result = dd.pop(1) From hpk at codespeak.net Tue Jun 24 13:48:57 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 13:48:57 +0200 (MEST) Subject: [pypy-svn] rev 1037 - pypy/trunk/doc/sprintinfo Message-ID: <20030624114857.626A05A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 13:48:57 2003 New Revision: 1037 Added: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Log: draft version of a LouvainLaNeuve sprint report Added: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Tue Jun 24 13:48:57 2003 @@ -0,0 +1,76 @@ +LouvainLaNeuveSprint summary report +----------------------------------- + +- enhanced/reviewed standard object space + + - reviewed, improved and enriched object implementations + mostly done by Christian, Alex + + boolobject, cpythonobject, instmethobject, longobject (removed), + sliceobject, userobject, dictobject, iterobject + + not reviewed so far? + tupleobject, listobject, intobject, floatobject + + stringobject was almost completed by Tomek and Guenter + with lots of tests + + - various improvements/bugfixes in a lot of objects/types + + - implemented tool/methodChecker.py to examine which methods + are existing on the types of the standard object space + (Jacob) + +- implemented language features + - implemented nested scopes (Michael, Holger) + dissassociated the frame.locals implementation from + the dict objectspace implementation (Guido, holger) + + - implemented generators (Michael, Holger) in Std,Triv + + - implemented unbound methods and descriptors (Michael, Samuele) + +- implemented the beginnings of the AnnotationObjectSpace + (Armin, Guido, Michael) for abstract interpretation. + + +- added lots of tests (all of us) + +- refactoring of argument-parsing for tool/test.py + and introduction of the "py.py" tool that unifies + executing commands, files and going interactive. + (michael) + +- refactoring, improvements of multimethods (Armin, Samuele) + +- documentation was restructured and transfered from + the wiki to subversion. The documents are now in reST-format + Also improvements and crossreferences between the + documents. (Anna) + a trigger was implemented that generates the new html-pages after + each checkin in the pypy/trunk/doc directory. (holger) + +- OSCON-2003 paper was beeing worked on and enhanced! + (Laura, Jacob, Guido, Armin, ...) + +- we had a discussion about EU-Funding. The EU currently + puts forward a Call for Proposals which apparently fits + the goals of pypy-development very much. There is interest + among current developers to go in this direction. + +- bugfixes, refactorings and adding tests all over the place + (everybody) + +--------------------------------------------------------------- + +.. _boolobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000381.html +.. _cpythonobj: http://codespeak.net/pipermail/pypy-svn/2003-June/000385.html +.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html +.. _long: http://codespeak.net/pipermail/pypy-svn/2003-June/000410.html +.. _sliceobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000408.html +.. _userobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000449.html +.. _dictobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000515.html +.. _intobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000443.html +.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html +.. _iterobject:: http://codespeak.net/pipermail/pypy-svn/2003-June/000999.html + From guenter at codespeak.net Tue Jun 24 13:49:24 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Tue, 24 Jun 2003 13:49:24 +0200 (MEST) Subject: [pypy-svn] rev 1038 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624114924.31A6F5A269@thoth.codespeak.net> Author: guenter Date: Tue Jun 24 13:49:23 2003 New Revision: 1038 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py Log: new method splitlines, new implementation of expandtabs additional arguments in count, refactored strip methods several bugfixes after Tomeks adaption of CPython tests Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 13:49:23 2003 @@ -37,7 +37,7 @@ __str__ def str__String(space, w_str): capitalize def str_capitalize__String(space, w_self): center def str_center__String_Int(space, w_self): -count def str_count__String_String(space, w_self): [optional arguments not supported now] +count def str_count__String_String_Int_Int(space, w_self): [optional arguments not supported now] decode !Unicode not supported now encode !Unicode not supported now endswith str_endswith__String_String [optional arguments not supported now] @@ -54,16 +54,16 @@ join def str_join__String_ANY(space, w_self, w_list): ljust def str_ljust__String_ANY(space, w_self, w_arg): lower OK -lstrip def str_lstrip__String(space, w_self): +lstrip def str_lstrip__String_String(space, w_self, w_chars): replace OK rfind OK rindex OK rjust def str_rjust__String_ANY(space, w_self, w_arg): -rstrip def str_rstrip__String(space, w_self): +rstrip def str_rstrip__String_String(space, w_self, w_chars): split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1): -splitlines *Guenter -startswith *Guenter -strip def str_strip__String(space, w_self): +splitlines def str_splitlines__String_String(space, w_self, w_keepends): +startswith str_startswith__String_String [optional arguments not supported now] +strip def str_strip__String_String(space, w_self, w_chars): swapcase OK title def str_title__String(space, w_self): translate @@ -472,8 +472,6 @@ bufpos = bufpos + 1 return space.wrap("".join(buf)) - - def _find(self, sub, start, end, dir): length = len(self) @@ -522,38 +520,39 @@ return -1 - -def str_strip__String(space, w_self): - u = space.unwrap - u_self = u(w_self) +def _strip(space, w_self, w_chars, left, right): + "internal function called by str_xstrip methods" + u_self = space.unwrap(w_self) + u_chars = space.unwrap(w_chars) + + if u_self == None or u_chars == None: + return w_self + lpos = 0 - while u_self[lpos] == ' ': - lpos += 1 - rpos = len(u_self) - while u_self[rpos - 1] == ' ': - rpos -= 1 - - return space.wrap(u_self[lpos:rpos]) - - -def str_rstrip__String(space, w_self): - u_self = space.unwrap(w_self) + + if left: + #print "while %d < %d and -%s- in -%s-:"%(lpos, rpos, u_self[lpos],w_chars) + while lpos < rpos and u_self[lpos] in u_chars: + lpos += 1 - rpos = len(u_self) - while u_self[rpos - 1] == ' ': - rpos -= 1 + if right: + while rpos > 0 and u_self[rpos - 1] in u_chars: + rpos -= 1 - return space.wrap(u_self[:rpos]) + return space.wrap(u_self[lpos:rpos]) + + +def str_strip__String_String(space, w_self, w_chars): + return _strip(space, w_self, w_chars, left=1, right=1) + +def str_rstrip__String_String(space, w_self, w_chars): + return _strip(space, w_self, w_chars, left=0, right=1) + -def str_lstrip__String(space, w_self): - u_self = space.unwrap(w_self) - lpos = 0 - while u_self[lpos] == ' ': - lpos += 1 - - return space.wrap(u_self[lpos:]) +def str_lstrip__String_String(space, w_self, w_chars): + return _strip(space, w_self, w_chars, left=1, right=0) def str_center__String_Int(space, w_self, w_arg): @@ -568,27 +567,37 @@ u_centered = u_self return W_StringObject(space, u_centered) + + +def str_count__String_String_ANY_ANY(space, w_self, w_arg, w_start, w_end): + u_self = space.unwrap(w_self) + u_arg = space.unwrap(w_arg) + u_start = space.unwrap(w_start) + u_end = space.unwrap(w_end) -#[optional arguments not supported now] -def str_count__String_String(space, w_self, w_arg): - u_self = space.unwrap(w_self) - u_arg = space.unwrap(w_arg) + + if u_end == None: + u_end = len(u_self) + elif u_end < 0: + u_end += len(u_self) + + if u_start == None: u_start = 0 + + area = u_self [u_start:u_end] count = 0 - if u_arg == "": - count = len(u_self) +1 #behaves as in Python - elif u_self == "": - pass #behaves as in Python - else: - pos = 0 - while 1: - count += 1 - pos = u_self.find(u_arg, pos+1) #XXX use pypy find - if pos == -1: - break + + pos = -1 + while 1: + pos = _find(area, u_arg, pos+1, u_end, 1) + #pos = area.find(u_arg, pos+1, u_end) + if pos == -1: + break + count += 1 return W_IntObject(space, count) + #[optional arguments not supported now] def str_endswith__String_String(space, w_self, w_end): u_self = space.unwrap(w_self) @@ -619,21 +628,70 @@ found = 1 return W_IntObject(space, found) + + +def _tabindent(u_token, u_tabsize): + "calculates distance behind the token to the next tabstop" + + distance = u_tabsize + if u_token: + distance = 0 + offset = len(u_token) + + while 1: + #no sophisticated linebreak support now, '\r' just for passing adapted CPython test + if u_token[offset-1] == "\n" or u_token[offset-1] == "\r": + break; + distance += 1 + offset -= 1 + if offset == 0: + break + + #the same like distance = len(u_token) - (offset + 1) + #print '' % (offset, distance, u_tabsize, u_token) + distance = (u_tabsize-distance) % u_tabsize + if distance == 0: + distance=u_tabsize + return distance + + def str_expandtabs__String_Int(space, w_self, w_tabsize): u_self = space.unwrap(w_self) u_tabsize = space.unwrap(w_tabsize) - + u_expanded = "" if u_self: - for token in u_self.split("\t"): #XXX use pypy split - if token: - u_expanded += token - else: - u_expanded += " " * u_tabsize + split = u_self.split("\t") #XXX use pypy split + u_expanded =oldtoken = split.pop(0) + for token in split: + #print "%d#%d -%s-" % (_tabindent(oldtoken,u_tabsize), u_tabsize, token) + u_expanded += " " * _tabindent(oldtoken,u_tabsize) + token + oldtoken = token + return W_StringObject(space, u_expanded) - + + +def str_splitlines__String_Int(space, w_self, w_keepends): + u_self = space.unwrap(w_self) + u_keepends = space.unwrap(w_keepends) + selflen = len(u_self) + + L = [] + pos = 0 + while 1: + oldpos = pos + pos = _find(u_self, '\n', pos, selflen, 1) + 1 + if pos > oldpos: + w_item = space.wrap(u_self[oldpos:pos]) + if not u_keepends: + w_item = _strip(space, w_item, W_StringObject(space,'\n'), left=0, right=1) + L.append(w_item) + else: + break + return W_ListObject(space, L) + def str_zfill__String_Int(space, w_self, w_width): u = space.unwrap input = u(w_self) @@ -662,6 +720,7 @@ return space.wrap("".join(buf)) + def unwrap__String(space, w_str): return w_str._value From hpk at codespeak.net Tue Jun 24 13:50:10 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 13:50:10 +0200 (MEST) Subject: [pypy-svn] rev 1039 - pypy/trunk/doc/sprintinfo Message-ID: <20030624115010.C5C775A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 13:50:10 2003 New Revision: 1039 Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Log: tweaking formats Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt (original) +++ pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Tue Jun 24 13:50:10 2003 @@ -5,15 +5,13 @@ - reviewed, improved and enriched object implementations mostly done by Christian, Alex - boolobject, cpythonobject, instmethobject, longobject (removed), sliceobject, userobject, dictobject, iterobject - not reviewed so far? tupleobject, listobject, intobject, floatobject - stringobject was almost completed by Tomek and Guenter - with lots of tests + - stringobject was completed with lots of tests + (Tomek, Guenter) - various improvements/bugfixes in a lot of objects/types @@ -26,7 +24,7 @@ dissassociated the frame.locals implementation from the dict objectspace implementation (Guido, holger) - - implemented generators (Michael, Holger) in Std,Triv + - implemented generators (Michael, Holger) in Std,Triv space - implemented unbound methods and descriptors (Michael, Samuele) From gvanrossum at codespeak.net Tue Jun 24 13:50:45 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 13:50:45 +0200 (MEST) Subject: [pypy-svn] rev 1040 - pypy/trunk/src/pypy/interpreter/test Message-ID: <20030624115045.73D545A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 13:50:45 2003 New Revision: 1040 Modified: pypy/trunk/src/pypy/interpreter/test/test_extmodule.py Log: Repair test_appmethod, which looked pretty bogus. Modified: pypy/trunk/src/pypy/interpreter/test/test_extmodule.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_extmodule.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_extmodule.py Tue Jun 24 13:50:45 2003 @@ -43,15 +43,11 @@ bm = BM_with_appmethod(space) w_bm = bm.wrap_me() w_bmd = space.getattr(w_bm, space.wrap('__dict__')) - bmd = space.unwrap(w_bmd) - themethod = bmd.get('amethod') - self.assertNotEqual(themethod, None) w_method = space.getitem(w_bmd, space.wrap('amethod')) - bmd['amethod'] = BM_with_appmethod.amethod - self.assertEqual(bmd, - {'__doc__': BM_with_appmethod.__doc__, - '__name__': BM_with_appmethod.__pythonname__, - 'amethod': BM_with_appmethod.amethod} ) + w_doc = space.getitem(w_bmd, space.wrap("__doc__")) + w_name = space.getitem(w_bmd, space.wrap("__name__")) + self.assertEqual(space.unwrap(w_doc), BM_with_appmethod.__doc__) + self.assertEqual(space.unwrap(w_name), BM_with_appmethod.__pythonname__) result = space.call(w_method, space.wrap(()), space.wrap({})) self.assertEqual(result, 23) From guenter at codespeak.net Tue Jun 24 13:54:14 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Tue, 24 Jun 2003 13:54:14 +0200 (MEST) Subject: [pypy-svn] rev 1041 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624115414.2C5EF5A269@thoth.codespeak.net> Author: guenter Date: Tue Jun 24 13:54:13 2003 New Revision: 1041 Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: new methods implemented in stringobject.py Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Tue Jun 24 13:54:13 2003 @@ -29,14 +29,14 @@ str_rindex = MultiMethod('rindex', 4, defaults=(None, None)) str_replace = MultiMethod('replace', 4, defaults=(-1,)) str_zfill = MultiMethod('zfill', 2) - str_strip = MultiMethod('strip', 1) - str_rstrip = MultiMethod('rstrip', 1) - str_lstrip = MultiMethod('lstrip', 1) - str_center = MultiMethod('center', 2) - str_count = MultiMethod('count', 2) #[optional arguments not supported now] + str_strip = MultiMethod('strip', 2, defaults=('', ' ')) + str_rstrip = MultiMethod('rstrip', 2, defaults=('', ' ')) + str_lstrip = MultiMethod('lstrip', 2, defaults=('', ' ')) + str_center = MultiMethod('center', 2, ) + str_count = MultiMethod('count', 4, defaults=(None,None)) str_endswith = MultiMethod('endswith', 2) #[optional arguments not supported now] str_expandtabs = MultiMethod('expandtabs', 2, defaults=(8,)) - str_splitlines = MultiMethod('splitlines', 2) + str_splitlines = MultiMethod('splitlines', 2, defaults=(0,)) str_startswith = MultiMethod('startswith', 2) #[optional arguments not supported now] registerimplementation(W_StringType) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Tue Jun 24 13:54:13 2003 @@ -206,7 +206,7 @@ self.assertEquals('123x123'.replace('123', ''), 'x') - def _test_strip(self): + def test_strip(self): s = " a b " self.assertEquals(s.strip(), "a b") self.assertEquals(s.rstrip(), " a b") @@ -247,18 +247,13 @@ self.assertEquals('abc'.center(2), 'abc') - def _test_count(self): + def test_count(self): self.assertEquals("".count("x"),0) self.assertEquals("".count(""),1) self.assertEquals("Python".count(""),7) self.assertEquals("ab aaba".count("ab"),2) self.assertEquals('aaa'.count('a'), 3) self.assertEquals('aaa'.count('b'), 0) - self.assertEquals('aaa'.count('a'), 3) - self.assertEquals('aaa'.count('b'), 0) - self.assertEquals('aaa'.count('a'), 3) - self.assertEquals('aaa'.count('b'), 0) - self.assertEquals('aaa'.count('b'), 0) self.assertEquals('aaa'.count('a', -1), 1) self.assertEquals('aaa'.count('a', -10), 3) self.assertEquals('aaa'.count('a', 0, -1), 2) @@ -287,22 +282,38 @@ self.assertEquals(''.endswith('a'),0) self.assertEquals('x'.endswith('xx'),0) self.assertEquals('y'.endswith('xx'),0) - - - def _test_expandtabs(self): + + def test_expandtabs(self): + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(4), 'abc\rab def\ng hi') + self.assertEquals('abc\r\nab\tdef\ng\thi'.expandtabs(4), 'abc\r\nab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') + self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') + self.assertEquals('abc\r\nab\r\ndef\ng\r\nhi'.expandtabs(4), 'abc\r\nab\r\ndef\ng\r\nhi') + + s = 'xy\t' + self.assertEquals(s.expandtabs(),'xy ') + s = '\txy\t' - self.assertEquals(s.expandtabs(),' xy ') + self.assertEquals(s.expandtabs(),' xy ') self.assertEquals(s.expandtabs(1),' xy ') + self.assertEquals(s.expandtabs(2),' xy ') + self.assertEquals(s.expandtabs(3),' xy ') + self.assertEquals('xy'.expandtabs(),'xy') self.assertEquals(''.expandtabs(),'') - self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') - self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') - self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(4), 'abc\rab def\ng hi') - self.assertEquals('abc\r\nab\tdef\ng\thi'.expandtabs(4), 'abc\r\nab def\ng hi') - self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') - self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') - self.assertEquals('abc\r\nab\r\ndef\ng\r\nhi'.expandtabs(4), 'abc\r\nab\r\ndef\ng\r\nhi') + + def test_splitlines(self): + s="ab\nab\n \n x\n\n\n" + self.assertEquals(s.splitlines(),['ab', 'ab', ' ', ' x', '', '']) + self.assertEquals(s.splitlines(),s.splitlines(0)) + self.assertEquals(s.splitlines(1),['ab\n', 'ab\n', ' \n', ' x\n', '\n', '\n']) + s="\none\n\two\nthree\n\n" + self.assertEquals(s.splitlines(),['', 'one', '\two', 'three', '']) + self.assertEquals(s.splitlines(1),['\n', 'one\n', '\two\n', 'three\n', '\n']) + def test_find(self): self.assertEquals('abcdefghiabc'.find('abc'), 0) self.assertEquals('abcdefghiabc'.find('abc', 1), 9) From gvanrossum at codespeak.net Tue Jun 24 13:58:25 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 13:58:25 +0200 (MEST) Subject: [pypy-svn] rev 1042 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030624115825.6D7935A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 13:58:25 2003 New Revision: 1042 Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/wrapper.py Log: Mure functionality in annotation space. M cloningcontext.py support for w_globals being a W_KnownKeysContainer M objspace.py the base clsas make_builtins() now works move most of unwrap implementation into wrapper objects support for modules and builtin functions support calling builtin functions support getting/setting module attributes M wrapper.py __repr__ places a limit on argsrepr() return value add unwrap() as a method of W_Object make W_KnownKeysContainer unwrappable if all values are add W_Module type, with getattr and setattr support add W_BuiltinFunction type (incomplete?) Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Tue Jun 24 13:58:25 2003 @@ -1,7 +1,8 @@ from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.pyframe import ControlFlowException, ExitFrame from pypy.objspace.ann.wrapper \ - import union, compatible_frames, unify_frames, W_Anything, W_Constant + import union, compatible_frames, unify_frames, W_Anything, W_Constant, \ + W_KnownKeysContainer class FunctionInfo(object): @@ -58,8 +59,7 @@ # {(bytecode, w_globals): FunctionInfo(), ...} def getfunctioninfo(self, frame, new=False): - assert isinstance(frame.w_globals, W_Constant) - key = (frame.bytecode, id(frame.w_globals.value)) + key = self.makekey(frame) info = self.functioninfos.get(key) if info is None: if not new: @@ -67,6 +67,12 @@ self.functioninfos[key] = info = FunctionInfo() return info + def makekey(self, frame): + if isinstance(frame.w_globals, W_Constant): + return (frame.bytecode, id(frame.w_globals.value)) + if isinstance(frame.w_globals, W_KnownKeysContainer): + return (frame.bytecode, id(frame.w_globals.args_w)) + def bytecode_trace(self, frame): if frame.restarting is not None: w_obj, flag = frame.restarting Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Tue Jun 24 13:58:25 2003 @@ -5,6 +5,7 @@ from pypy.interpreter.baseobjspace \ import ObjSpace, OperationError, NoValue, PyPyError from pypy.interpreter.pycode import PyByteCode +from pypy.interpreter.extmodule import PyBuiltinCode from pypy.objspace.ann.cloningcontext import CloningExecutionContext from pypy.objspace.ann.cloningcontext import IndeterminateCondition @@ -33,13 +34,9 @@ for n, c in __builtin__.__dict__.iteritems(): if isinstance(c, types.TypeType) or isinstance(c, types.ClassType): setattr(self, 'w_'+n, self.wrap(c)) - self.w_builtins = self.wrap(__builtin__) self.make_builtins() self.make_sys() - def make_builtins(self): - self.builtin = pypy.module.builtin.Builtin(self) - # Service methods whose interface is in the abstract base class def wrapboot(self, obj): @@ -58,10 +55,8 @@ return W_Constant(obj) def unwrap(self, w_obj): - if isinstance(w_obj, W_Constant): - return w_obj.value - elif isinstance(w_obj, W_Object): - raise UnwrapException("Cannot unwrap: " +repr(w_obj)) + if isinstance(w_obj, W_Object): + return w_obj.unwrap() else: raise TypeError("not wrapped: " + repr(w_obj)) @@ -130,9 +125,11 @@ return W_Anything() def newmodule(self, w_name): - return W_Anything() + return W_Module(w_name, self.w_None) - def newfunction(self, *stuff): + def newfunction(self, code, w_globals, w_defaults, w_closure=None): + if isinstance(code, PyBuiltinCode): + return W_BuiltinFunction(code, w_defaults) return W_Anything() def newlist(self, list_w): @@ -240,27 +237,42 @@ raise IndeterminateCondition(w_iterator) def call(self, w_func, w_args, w_kwds): - func = self.unwrap(w_func) # XXX What if this fails? - try: - code = func.func_code - except AttributeError: - return W_Anything() - bytecode = self.bytecodecache.get(code) - if bytecode is None: - bytecode = PyByteCode() - bytecode._from_code(code) - self.bytecodecache[code] = bytecode + if isinstance(w_func, W_BuiltinFunction): + bytecode = w_func.code + w_defaults = w_func.w_defaults + w_globals = self.w_None + else: + try: + func = self.unwrap(w_func) + except UnwrapException: + return W_Anything() + try: + code = func.func_code + except AttributeError: + return W_Anything() + bytecode = self.bytecodecache.get(code) + if bytecode is None: + bytecode = PyByteCode() + bytecode._from_code(code) + self.bytecodecache[code] = bytecode + w_defaults = self.wrap(func.func_defaults) + w_globals = self.wrap(func.func_globals) w_locals = bytecode.build_arguments(self, w_args, w_kwds, - self.wrap(func.func_defaults), + w_defaults, self.wrap(())) - w_result = bytecode.eval_code(self, - self.wrap(func.func_globals), - w_locals) + w_result = bytecode.eval_code(self, w_globals, w_locals) return w_result def getattr(self, w_obj, w_name): + if isinstance(w_obj, W_Module) and isinstance(w_name, W_Constant): + name = self.unwrap(w_name) + try: + return w_obj.getattr(name) + except KeyError: + raise OperationError(self.wrap(AttributeError), + self.wrap(AttributeError(name))) try: obj = self.unwrap(w_obj) name = self.unwrap(w_name) @@ -273,8 +285,10 @@ return self.reraise() def setattr(self, w_obj, w_name, w_value): - # XXX What about the side effect? - return self.w_None + if isinstance(w_obj, W_Module) and isinstance(w_name, W_Constant): + name = self.unwrap(w_name) + w_obj.setattr(name, w_value) + # Space setattr shouldn't return anything, so no w_None here def len(self, w_obj): if isinstance(w_obj, W_KnownKeysContainer): Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Tue Jun 24 13:58:25 2003 @@ -21,11 +21,19 @@ pass def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, self.argsrepr()) + s = self.argsrepr() + if len(s) > 100: + s = s[:25] + "..." + s[-25:] + return "%s(%s)" % (self.__class__.__name__, s) def argsrepr(self): return "" + def unwrap(self): + # XXX Somehow importing this at module level doesn't work + from pypy.objspace.ann.objspace import UnwrapException + raise UnwrapException(self) + def __eq__(self, other): return type(other) is type(self) @@ -51,7 +59,10 @@ self.value = value def argsrepr(self): - return repr(self.value)[:50] + return repr(self.value) + + def unwrap(self): + return self.value def __eq__(self, other): return type(other) is type(self) and self.value == other.value @@ -60,9 +71,9 @@ return self class W_KnownKeysContainer(W_Object): - """A dict with constant set of keys or a tuple with known length. + """A dict with a known set of keys or a list with known length. - XXX This may be mutable! Is that a good idea? + XXX This is mutable! Is that a good idea? """ def __init__(self, args_w): @@ -71,6 +82,18 @@ def argsrepr(self): return repr(self.args_w) + def unwrap(self): + if hasattr(self.args_w, "keys"): + d = {} + for k, w_v in self.args_w.iteritems(): + d[k] = w_v.unwrap() + return d + assert isinstance(self.args_w, list), self.args_w + l = [] + for w_obj in self.args_w: + l.append(w_obj.unwrap()) + return l + def __eq__(self, other): return type(other) is type(self) and self.args_w == other.args_w @@ -87,6 +110,39 @@ # XXX Recurse down the values? return W_KnownKeysContainer(args_w) +class W_Module(W_Object): + """A module object. It supports getattr and setattr (yikes!).""" + + def __init__(self, w_name, w_doc): + # The wrapped module name and wrapped docstring must be known + self.w_name = w_name + self.w_doc = w_doc + self.contents = W_KnownKeysContainer({"__name__": w_name, + "__doc__": w_doc}) + + def argsrepr(self): + return repr(self.w_name) + ", " + repr(self.w_doc) + + def getattr(self, name): + # Returned a wrapped object or raise an unwrapped KeyError exception + if name == "__dict__": + return self.contents + return self.contents[name] + + def setattr(self, name, w_obj): + self.contents.args_w[name] = w_obj + +class W_BuiltinFunction(W_Object): + """A function that executes in interpreter space.""" + + def __init__(self, code, w_defaults): + self.code = code + self.w_defaults = w_defaults + + def argsrepr(self): + return repr(self.code) + ", " + repr(self.w_defaults) + + def unify_frames(f1, f2): """Given two compatible frames, make them the same. From jacob at codespeak.net Tue Jun 24 14:02:38 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Tue, 24 Jun 2003 14:02:38 +0200 (MEST) Subject: [pypy-svn] rev 1043 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624120238.E95535A269@thoth.codespeak.net> Author: jacob Date: Tue Jun 24 14:02:38 2003 New Revision: 1043 Added: pypy/trunk/src/pypy/objspace/std/register_all.py Log: added the missing register_all.py file containing the moved register_all function Added: pypy/trunk/src/pypy/objspace/std/register_all.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/std/register_all.py Tue Jun 24 14:02:38 2003 @@ -0,0 +1,83 @@ +from pypy.objspace.std.objspace import StdObjSpace, W_ANY + +_name_mappings = { + 'and': 'and_', + 'or': 'or_', + 'not': 'not_', + } + +def register_all(module_dict, alt_ns=None): + """register implementations for multimethods. + + By default a (name, object) pair of the given module dictionary + is registered on the multimethod 'name' of StdObjSpace. + If the name doesn't exist then the alternative namespace is tried + for registration. + """ + + for name, obj in module_dict.items(): + if name.find('__')<1: + continue + funcname, sig = name.split('__') + l=[] + for i in sig.split('_'): + if i == 'ANY': + icls = W_ANY + else: + icls = (module_dict.get('W_%s' % i) or + module_dict.get('W_%sObject' % i)) + if icls is None: + raise ValueError, \ + "no W_%s or W_%sObject for the definition of %s" % ( + i, i, name) + l.append(icls) + + if len(l) != obj.func_code.co_argcount-1: + raise ValueError, \ + "function name %s doesn't specify exactly %d arguments" % ( + repr(name), obj.func_code.co_argcount-1) + + funcname = _name_mappings.get(funcname, funcname) + + if hasattr(alt_ns, funcname): + getattr(alt_ns, funcname).register(obj, *l) + else: + getattr(StdObjSpace, funcname).register(obj, *l) + add_extra_comparisons() + +class Curry: + def __init__(self, fun, arg): + self.fun = fun + self.pending = [arg] + + def __call__(self, *args): + return self.fun(*(self.pending + args)) + +def inverted_comparison(function, space, w_1, w_2): + return space.not_(function(space, w_1, w_2)) + +def add_extra_comparisons( + operators=(('eq', 'ne'), ('lt', 'ge'), ('gt', 'le'))): + """ + If the module has defined eq, lt or gt, + check if it already has ne, ge and le respectively. + If not, then add them as space.not_ on the implemented methods. + """ + + for method, mirror in operators: + try: + multifunc = StdObjSpace.__dict__[method] + mirrorfunc = StdObjSpace.__dict__[mirror] + for types, functions in multifunc.dispatch_table.iteritems(): + t1, t2 = types + if t1 is t2: + if not mirrorfunc.dispatch_table.has_key(types): + assert len(functions) == 1, 'Automatic' + 'registration of comparison functions' + ' only work when there is a single method for' + ' the operation.' + mirrorfunc.register( + Curry(inverted_comparison, functions[0]), + *[t1, t1]) + except AttributeError: + print '%s not found in StdObjSpace' % method From gvanrossum at codespeak.net Tue Jun 24 14:40:39 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 14:40:39 +0200 (MEST) Subject: [pypy-svn] rev 1044 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624124039.51BA15A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 14:40:38 2003 New Revision: 1044 Modified: pypy/trunk/src/pypy/objspace/std/typetype.py Log: Delete unused import of NewMultimethodCode which caused problems. Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Tue Jun 24 14:40:38 2003 @@ -1,6 +1,6 @@ from pypy.objspace.std.objspace import * from pypy.objspace.std.register_all import register_all -from typeobject import W_TypeObject, NewMultimethodCode +from typeobject import W_TypeObject class W_TypeType(W_TypeObject): """The single instance of this class is the object the user sees as From gvanrossum at codespeak.net Tue Jun 24 14:41:37 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 14:41:37 +0200 (MEST) Subject: [pypy-svn] rev 1045 - pypy/trunk/src/pypy/tool Message-ID: <20030624124137.F12035A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 14:41:37 2003 New Revision: 1045 Modified: pypy/trunk/src/pypy/tool/test.py Log: List tests and subdirectories in alphabetical order (case sensitive). Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Tue Jun 24 14:41:37 2003 @@ -172,7 +172,9 @@ root = os.path.abspath(root) suite = unittest.TestLoader.suiteClass() - for fn in os.listdir(root): + names = os.listdir(root) + names.sort() + for fn in names: if fn.startswith('.'): continue fullfn = os.path.join(root, fn) From hpk at codespeak.net Tue Jun 24 14:52:20 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 14:52:20 +0200 (MEST) Subject: [pypy-svn] rev 1046 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624125220.70AA35A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 14:52:19 2003 New Revision: 1046 Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py pypy/trunk/src/pypy/objspace/std/cpythonobject.py pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/floatobject.py pypy/trunk/src/pypy/objspace/std/floattype.py pypy/trunk/src/pypy/objspace/std/funcobject.py pypy/trunk/src/pypy/objspace/std/instmethobject.py pypy/trunk/src/pypy/objspace/std/iterobject.py pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/noneobject.py pypy/trunk/src/pypy/objspace/std/nullobject.py pypy/trunk/src/pypy/objspace/std/objectobject.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/register_all.py pypy/trunk/src/pypy/objspace/std/sliceobject.py pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/tupleobject.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/typetype.py pypy/trunk/src/pypy/objspace/std/userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: moved register_all into objspace so we spare an import (armin's suggestion). to avoid circular imports register_all has the imports now inside instead of at module global level. Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/boolobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/boolobject.py Tue Jun 24 14:52:19 2003 @@ -7,7 +7,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from booltype import W_BoolType import intobject Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/cpythonobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py Tue Jun 24 14:52:19 2003 @@ -10,7 +10,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from stringobject import W_StringObject import sys, operator, types Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Tue Jun 24 14:52:19 2003 @@ -1,7 +1,6 @@ """Default implementation for some operation.""" from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all # These are operations that must fall back to some default behavior, Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 24 14:52:19 2003 @@ -6,7 +6,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from dicttype import W_DictType, _no_object from stringobject import W_StringObject from pypy.interpreter.extmodule import make_builtin_func Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/floatobject.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from floattype import W_FloatType ############################################################## Modified: pypy/trunk/src/pypy/objspace/std/floattype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floattype.py (original) +++ pypy/trunk/src/pypy/objspace/std/floattype.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/funcobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/funcobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/funcobject.py Tue Jun 24 14:52:19 2003 @@ -1,6 +1,5 @@ from __future__ import nested_scopes from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from functype import W_FuncType import pypy.interpreter.pyframe from pypy.objspace.std.instmethobject import W_InstMethObject Modified: pypy/trunk/src/pypy/objspace/std/instmethobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/instmethobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/instmethobject.py Tue Jun 24 14:52:19 2003 @@ -15,7 +15,6 @@ from __future__ import nested_scopes from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from instmethtype import W_InstMethType Modified: pypy/trunk/src/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/iterobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/iterobject.py Tue Jun 24 14:52:19 2003 @@ -5,7 +5,6 @@ for function-iteration. """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from itertype import W_SeqIterType Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from listtype import W_ListType from intobject import W_IntObject from sliceobject import W_SliceObject Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/noneobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/noneobject.py Tue Jun 24 14:52:19 2003 @@ -5,7 +5,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from nonetype import W_NoneType class W_NoneObject(W_Object): Modified: pypy/trunk/src/pypy/objspace/std/nullobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/nullobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/nullobject.py Tue Jun 24 14:52:19 2003 @@ -5,7 +5,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from nulltype import W_NullType class W_NullObject(W_Object): Modified: pypy/trunk/src/pypy/objspace/std/objectobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objectobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/objectobject.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all class W_ObjectObject(W_Object): Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Tue Jun 24 14:52:19 2003 @@ -5,6 +5,7 @@ """ import pypy.interpreter.appfile +from register_all import register_all from pypy.interpreter.baseobjspace import * from multimethod import * Modified: pypy/trunk/src/pypy/objspace/std/register_all.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/register_all.py (original) +++ pypy/trunk/src/pypy/objspace/std/register_all.py Tue Jun 24 14:52:19 2003 @@ -1,4 +1,3 @@ -from pypy.objspace.std.objspace import StdObjSpace, W_ANY _name_mappings = { 'and': 'and_', @@ -14,6 +13,7 @@ If the name doesn't exist then the alternative namespace is tried for registration. """ + from pypy.objspace.std.objspace import StdObjSpace, W_ANY for name, obj in module_dict.items(): if name.find('__')<1: @@ -63,6 +63,7 @@ check if it already has ne, ge and le respectively. If not, then add them as space.not_ on the implemented methods. """ + from pypy.objspace.std.objspace import StdObjSpace, W_ANY for method, mirror in operators: try: Modified: pypy/trunk/src/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/sliceobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/sliceobject.py Tue Jun 24 14:52:19 2003 @@ -6,7 +6,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from pypy.interpreter.appfile import AppFile from pypy.interpreter.extmodule import make_builtin_func from pypy.objspace.std.instmethobject import W_InstMethObject Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 14:52:19 2003 @@ -72,7 +72,6 @@ """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from stringtype import W_StringType from intobject import W_IntObject from sliceobject import W_SliceObject Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from typeobject import W_TypeObject Modified: pypy/trunk/src/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupleobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupleobject.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from tupletype import W_TupleType from intobject import W_IntObject from sliceobject import W_SliceObject Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Tue Jun 24 14:52:19 2003 @@ -1,5 +1,4 @@ from pypy.interpreter import pycode -from pypy.objspace.std.register_all import register_all from pypy.objspace.std.objspace import * Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Tue Jun 24 14:52:19 2003 @@ -1,6 +1,5 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all -from typeobject import W_TypeObject +from typeobject import W_TypeObject # , NewMultimethodCode class W_TypeType(W_TypeObject): """The single instance of this class is the object the user sees as Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Tue Jun 24 14:52:19 2003 @@ -7,7 +7,6 @@ as well as of normal and special attributes. """ from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all from usertype import W_UserType import typeobject Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Tue Jun 24 14:52:19 2003 @@ -3,7 +3,6 @@ """ from __future__ import nested_scopes from pypy.objspace.std.objspace import * -from pypy.objspace.std.register_all import register_all import typeobject, objecttype from typeobject import W_TypeObject From gvanrossum at codespeak.net Tue Jun 24 15:14:40 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 15:14:40 +0200 (MEST) Subject: [pypy-svn] rev 1047 - pypy/trunk/src/pypy/objspace/ann Message-ID: <20030624131440.247F95A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 15:14:39 2003 New Revision: 1047 Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py Log: Add setitem for limited cases. Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Tue Jun 24 15:14:39 2003 @@ -290,6 +290,14 @@ w_obj.setattr(name, w_value) # Space setattr shouldn't return anything, so no w_None here + def setitem(self, w_obj, w_key, w_value): + if (isinstance(w_obj, W_KnownKeysContainer) and + isinstance(w_key, W_Constant)): + key = self.unwrap(w_key) + w_obj.args_w[key] = w_value + return + # XXX How to record the side effect? + def len(self, w_obj): if isinstance(w_obj, W_KnownKeysContainer): return self.wrap(len(w_obj)) From anna at codespeak.net Tue Jun 24 15:29:56 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Tue, 24 Jun 2003 15:29:56 +0200 (MEST) Subject: [pypy-svn] rev 1048 - pypy/trunk/doc/devel Message-ID: <20030624132956.2D6C15A269@thoth.codespeak.net> Author: anna Date: Tue Jun 24 15:29:55 2003 New Revision: 1048 Added: pypy/trunk/doc/devel/howtosvn.txt Log: This document shows how to use svn for new users of subversion Added: pypy/trunk/doc/devel/howtosvn.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/devel/howtosvn.txt Tue Jun 24 15:29:55 2003 @@ -0,0 +1,117 @@ +================= +subversion +================= + +Our emerging codebase and the website is controlled by subversion. + +``http://codespeak.net/svn/pypy/trunk/`` + +Jens-Uwe Mager has prepared some installation files + ++ windows commandline_ utility + + (See Microsoft website_ if you have .DLL issues.) + ++ Windows Installer file for GUI_ + + (See Win_ 2000, NT if you have problems loading it.) + ++ MacOS_ X binary tar ball + + this will also need iconv_ MacOS X tar ball + ++ Unix_ Unix source tarball + +HowToInstallServer sketches how to install a subversion server (not as easy as the client install). + +Getting started +----------------- + +If you're just getting started with subversion, here's a simple how-to so you can get started on our codebase. +For complete information, you can go read the subversion guide_. + +**Download and install the appropriate installation file of subversion above.** + +You can then go look at the files online_ with your browser, located at: http://codespeak.net/svn/pypy/trunk +But, you'll want to check out your own local copies to work on. + +Check out and Check in +----------------------------- + +There are currently two directories you'll want to check out: /src and /doc +In order to get the sourcecode and docs downloaded onto your drive, open a shell or commandline and type:: + + $ svn co http://codespeak.net/svn/pypy/trunk/src + $ svn co http://codespeak.net/svn/pypy/trunk/doc + +Once you've got the files checked out to your own system, you can use your favorite text editor to change to files. Be sure to read the coding-style_ and other documentation files before doing a lot of work on the source code. Before doing any work, make sure you're using the most recent update with:: + + $ svn up + +this will update whichever subdirectory you're in (doc or src). + +When you're ready to **check in** a file, + +cd to your local checked out sourcecode directory, and if necessary, copy the file over from wherever you worked on it:: + + $ cp ~/mydir/filename.ext filename.ext + +If you're adding a brand-new file:: + + $ svn add filename.ext + +Then, to **commit** it:: + + $ svn ci -m "your comments about what changes your committing" + $ your password: (this may not be necessary) + +You'll see something like the following:: + + Adding goals/stringcomp.py + Transmitting file data . + Committed revision 578. + +or:: + + Sending coding-style.txt + Transmitting file data . + Committed revision 631. + +Check online on the check-in archives_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made! See the readme_ on documentation for more info. + +Some other useful subversion tricks: +---------------------------------------- + +**Be sure to remember ``svn`` in the commandline in the following commands.** + +``$ svn mv filename.ext`` + to move or rename a file + +``$ svn rm filename.ext`` + to remove (delete) a file + +``$ svn status`` + will let you know what changes you've made compared to the current repository version + +``$ svn revert filename.ext`` + will fix problems if you deleted or moved a file without telling svn. + +``$ svn cleanup`` + last resort to fix it if you've got a totally messed up local copy. + Use this if you see error messages about ``locked`` files that you can't fix otherwise. + +--------------------------------------------------------------------------------- + +.. _commandline: http://codespeak.net/~jum/svn-0.24.2-setup.exe +.. _website: http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B259403 +.. _GUI: http://codespeak.net/~jum/TortoiseSVN-0.11.2-UNICODE.msi +.. _Win: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4B6140F9-2D36-4977-8FA1-6F8A0F5DCA8F +.. _MacOS: http://codespeak.net/~jum/svn-0.24.2-darwin-ppc.tar.gz +.. _iconv: http://codespeak.net/~jum/iconv-darwin-ppc.tar.gz +.. _Unix: http://codespeak.net/~jum/subversion-0.24.2.tar.gz + +.. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1 +.. _archives: http://codespeak.net/pipermail/pypy-svn/ +.. _online: http://codespeak.net/svn/pypy/trunk +.. _coding-style: http://codespeak.net/pypy/doc/devel/coding-style.html +.. _readme: http://codespeak.net/pypy/doc/readme.html \ No newline at end of file From jacob at codespeak.net Tue Jun 24 15:36:02 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Tue, 24 Jun 2003 15:36:02 +0200 (MEST) Subject: [pypy-svn] rev 1049 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030624133602.7354D5A269@thoth.codespeak.net> Author: jacob Date: Tue Jun 24 15:36:02 2003 New Revision: 1049 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py Log: Added almost correct lt and gt operators. Fixed error in eq. Test cases will follow. Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 24 15:36:02 2003 @@ -125,17 +125,59 @@ def eq__Dict_Dict(space, w_left, w_right): if len(w_left.data) != len(w_right.data): - return space.newbool(0) - for w_k, hash, cell in w_left.data: + return space.w_False + for w_key, cell in w_left.non_empties(): try: - w_v = space.getitem(w_right, w_k) + w_rightval = space.getitem(w_right, w_key) except OperationError: - return space.newbool(0) - r = space.is_true(space.eq(cell.w_value, w_v)) - if not r: - return space.newbool(r) - return space.newbool(1) + return space.w_False + if not space.is_true(space.eq(cell.w_value, w_rightval)): + return space.w_False + return space.w_True +def lt__Dict_Dict(space, w_left, w_right): + # Different sizes, no problem + if len(w_left.data) < len(w_right.data): + return space.w_True + if len(w_left.data) > len(w_right.data): + return space.w_False + + # Same size + for w_key, cell in w_left.non_empties(): + # This is incorrect, but we need to decide what comparisons on + # dictionaries of equal size actually means + # The Python language specification is silent on the subject + try: + w_rightval = space.getitem(w_right, w_key) + except OperationError: + return space.w_True + if space.is_true(space.lt(cell.w_value, w_rightval)): + return space.w_True + # The dictionaries are equal. This is correct. + return space.w_False + + +def gt__Dict_Dict(space, w_left, w_right): + # Different sizes, no problem + if len(w_left.data) > len(w_right.data): + return space.w_True + if len(w_left.data) < len(w_right.data): + return space.w_False + + # Same size + for w_key, cell in w_left.non_empties(): + # This is incorrect, but we need to decide what comparisons on + # dictionaries of equal size actually means + # The Python language specification is silent on the subject + try: + w_rightval = space.getitem(w_right, w_key) + except OperationError: + return space.w_True + if space.is_true(space.gt(cell.w_value, w_rightval)): + return space.w_True + # The dictionaries are equal. This is correct. + return space.w_False + def dict_copy__Dict(space, w_self): return W_DictObject(space, [(w_key,cell.get()) for w_key,cell in From hpk at codespeak.net Tue Jun 24 15:37:58 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 15:37:58 +0200 (MEST) Subject: [pypy-svn] rev 1050 - pypy/trunk/doc/devel Message-ID: <20030624133758.1AC105A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 15:37:57 2003 New Revision: 1050 Modified: pypy/trunk/doc/devel/howtosvn.txt Log: added/modified some links. clarified information. Modified: pypy/trunk/doc/devel/howtosvn.txt ============================================================================== --- pypy/trunk/doc/devel/howtosvn.txt (original) +++ pypy/trunk/doc/devel/howtosvn.txt Tue Jun 24 15:37:57 2003 @@ -2,11 +2,17 @@ subversion ================= -Our emerging codebase and the website is controlled by subversion. +The PyPy codebase, documentation and web pages are controlled by subversion. +If you already know how to use it here is the URL you need to interact +with subversion: ``http://codespeak.net/svn/pypy/trunk/`` -Jens-Uwe Mager has prepared some installation files +If you don't know what to do then Jens-Uwe Mager has prepared some +installation files which should help you to install subversion on +your computer. + ++ Unix source tarball_ + windows commandline_ utility @@ -20,14 +26,12 @@ this will also need iconv_ MacOS X tar ball -+ Unix_ Unix source tarball - -HowToInstallServer sketches how to install a subversion server (not as easy as the client install). +btw, HowToInstallServer_ sketches how to install a subversion server on Linux (not as easy as the client install). You don't need to install server side files to get your client going. Getting started ----------------- -If you're just getting started with subversion, here's a simple how-to so you can get started on our codebase. +If you're just getting started with subversion, here's a simple how-to. For complete information, you can go read the subversion guide_. **Download and install the appropriate installation file of subversion above.** @@ -108,10 +112,11 @@ .. _Win: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4B6140F9-2D36-4977-8FA1-6F8A0F5DCA8F .. _MacOS: http://codespeak.net/~jum/svn-0.24.2-darwin-ppc.tar.gz .. _iconv: http://codespeak.net/~jum/iconv-darwin-ppc.tar.gz -.. _Unix: http://codespeak.net/~jum/subversion-0.24.2.tar.gz +.. _tarball: http://codespeak.net/~jum/subversion-0.24.2.tar.gz .. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1 .. _archives: http://codespeak.net/pipermail/pypy-svn/ .. _online: http://codespeak.net/svn/pypy/trunk .. _coding-style: http://codespeak.net/pypy/doc/devel/coding-style.html -.. _readme: http://codespeak.net/pypy/doc/readme.html \ No newline at end of file +.. _readme: http://codespeak.net/pypy/doc/readme.html +.. _HowToInstallServer: http://codespeak.net/moin/pypy/moin.cgi/HowToInstallServer From hpk at codespeak.net Tue Jun 24 15:42:33 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 24 Jun 2003 15:42:33 +0200 (MEST) Subject: [pypy-svn] rev 1051 - pypy/trunk/doc/sprintinfo Message-ID: <20030624134233.7598F5A269@thoth.codespeak.net> Author: hpk Date: Tue Jun 24 15:42:33 2003 New Revision: 1051 Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Log: enhanced links and infos Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt (original) +++ pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Tue Jun 24 15:42:33 2003 @@ -5,10 +5,10 @@ - reviewed, improved and enriched object implementations mostly done by Christian, Alex - boolobject, cpythonobject, instmethobject, longobject (removed), - sliceobject, userobject, dictobject, iterobject + boolobject_, cpythonobject_, instmethobject_, longobject_ (removed), + sliceobject_, userobject_, dictobject_, iterobject_ not reviewed so far? - tupleobject, listobject, intobject, floatobject + tupleobject, listobject, intobject, floatobject - stringobject was completed with lots of tests (Tomek, Guenter) @@ -22,7 +22,7 @@ - implemented language features - implemented nested scopes (Michael, Holger) dissassociated the frame.locals implementation from - the dict objectspace implementation (Guido, holger) + the dict objectspace implementation (Guido, Holger) - implemented generators (Michael, Holger) in Std,Triv space From jacob at codespeak.net Tue Jun 24 15:48:42 2003 From: jacob at codespeak.net (jacob at codespeak.net) Date: Tue, 24 Jun 2003 15:48:42 +0200 (MEST) Subject: [pypy-svn] rev 1052 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030624134842.232575C02C@thoth.codespeak.net> Author: jacob Date: Tue Jun 24 15:48:41 2003 New Revision: 1052 Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Log: Added tests for eq and lt Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Tue Jun 24 15:48:41 2003 @@ -250,6 +250,31 @@ vals.sort() self.assertEqual(vals, [2,4]) + def test_eq(self): + d1 = {1:2, 3:4} + d2 = {1:2, 3:4} + d3 = {1:2} + bool = d1 == d2 + self.assertEqual(bool, True) + bool = d1 == d3 + self.assertEqual(bool, False) + bool = d1 != d2 + self.assertEqual(bool, False) + bool = d1 != d3 + self.assertEqual(bool, True) + + def test_lt(self): + d1 = {1:2, 3:4} + d2 = {1:2, 3:4} + d3 = {1:2, 3:5} + d4 = {1:2} + bool = d1 < d2 + self.assertEqual(bool, False) + bool = d1 < d3 + self.assertEqual(bool, True) + bool = d1 < d4 + self.assertEqual(bool, False) + def tooslow_test_new(self): d = dict() self.assertEqual(d, {}) From arigo at codespeak.net Tue Jun 24 15:50:58 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 15:50:58 +0200 (MEST) Subject: [pypy-svn] rev 1053 - in pypy/trunk/src/pypy: interpreter objspace/stdobjspace/std/test Message-ID: <20030624135058.C18715A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 15:50:57 2003 New Revision: 1053 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/dicttype.py pypy/trunk/src/pypy/objspace/std/floattype.py pypy/trunk/src/pypy/objspace/std/inttype.py pypy/trunk/src/pypy/objspace/std/listobject.py pypy/trunk/src/pypy/objspace/std/listtype.py pypy/trunk/src/pypy/objspace/std/objectobject.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/objspace.py pypy/trunk/src/pypy/objspace/std/register_all.py pypy/trunk/src/pypy/objspace/std/slicetype.py pypy/trunk/src/pypy/objspace/std/stringtype.py pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py pypy/trunk/src/pypy/objspace/std/tupletype.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/std/typetype.py pypy/trunk/src/pypy/objspace/std/userobject.py pypy/trunk/src/pypy/objspace/std/usertype.py Log: Got the __new__ and __init__ methods (probably) right. Reorganized constructors of all object types accordingly. Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Tue Jun 24 15:50:57 2003 @@ -226,8 +226,6 @@ ('get', 'get', 3, ['__get__']), ('set', 'set', 2, ['__set__']), ('delete', 'delete', 2, ['__delete__']), - ('new', 'new', 3, ['__new__']), - ('init', 'init', 3, ['__init__']), ] ObjSpace.BuiltinModuleTable = [ Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 24 15:50:57 2003 @@ -88,6 +88,26 @@ result[space.unwrap(w_key)] = space.unwrap(cell.get()) return result +def object_init__Dict_ANY_ANY(space, w_dict, w_args, w_kwds): + # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed + dict_clear__Dict(space, w_dict) + args = space.unpackiterable(w_args) + if len(args) == 0: + pass + elif len(args) == 1: + # XXX do dict({...}) with dict_update__Dict_Dict() + list_of_w_pairs = space.unpackiterable(args[0]) + for w_pair in list_of_w_pairs: + pair = space.unpackiterable(w_pair) + if len(pair)!=2: + raise OperationError(space.w_ValueError, + space.wrap("dict() takes a sequence of pairs")) + w_k, w_v = pair + setitem__Dict_ANY_ANY(space, w_dict, w_k, w_v) + else: + raise OperationError(space.w_TypeError, + space.wrap("dict() takes at most 1 argument")) + def getitem__Dict_ANY(space, w_dict, w_lookup): data = w_dict.non_empties() # XXX shouldn't this use hashing? -- mwh Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/dicttype.py Tue Jun 24 15:50:57 2003 @@ -28,26 +28,8 @@ registerimplementation(W_DictType) -# XXX we'll worry about the __new__/__init__ distinction later -def dicttype_new(space, w_listtype, w_args, w_kwds): - # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed - args = space.unpackiterable(w_args) - if len(args) == 0: - pass - elif len(args) == 1: - list_of_w_pairs = space.unpackiterable(args[0]) - list_of_w_pairs.reverse() - for pair_w in list_of_w_pairs: - pair = space.unpackiterable(pair_w) - if len(pair)!=2: - raise OperationError(space.w_ValueError, - space.wrap("dict() takes a sequence of pairs")) - k, v = pair - if not space.is_true(space.contains(w_kwds, k)): - space.setitem(w_kwds, k, v) - else: - raise OperationError(space.w_TypeError, - space.wrap("dict() takes at most 1 argument")) - return w_kwds -StdObjSpace.new.register(dicttype_new, W_DictType, W_ANY, W_ANY) +def type_new__DictType_DictType_ANY_ANY(space, w_basetype, w_dicttype, w_args, w_kwds): + return space.newdict([]), True + +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/floattype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/floattype.py (original) +++ pypy/trunk/src/pypy/objspace/std/floattype.py Tue Jun 24 15:50:57 2003 @@ -8,24 +8,25 @@ registerimplementation(W_FloatType) -def new__FloatType_ANY_ANY(space, w_inttype, w_args, w_kwds): + +def type_new__FloatType_FloatType_ANY_ANY(space, w_basetype, w_floattype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) args = space.unpackiterable(w_args) if len(args) == 0: - return space.newint(0) + return space.newfloat(0), True elif len(args) == 1: arg = args[0] if space.is_true(space.issubtype(space.type(arg), space.w_str)): try: - return space.newfloat(float(space.unwrap(arg))) + return space.newfloat(float(space.unwrap(arg))), True except TypeError: raise OperationError(space.w_TypeError, space.wrap("invalid literal for float()")) else: - return space.float(args[0]) + return space.float(args[0]), True else: raise OperationError(space.w_TypeError, space.wrap("float() takes at most 1 argument")) Modified: pypy/trunk/src/pypy/objspace/std/inttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/inttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/inttype.py Tue Jun 24 15:50:57 2003 @@ -9,27 +9,26 @@ registerimplementation(W_IntType) -# XXX we'll worry about the __new__/__init__ distinction later -def inttype_new(space, w_inttype, w_args, w_kwds): +def type_new__IntType_IntType_ANY_ANY(space, w_basetype, w_inttype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) args = space.unpackiterable(w_args) if len(args) == 0: - return space.newint(0) + return space.newint(0), True elif len(args) == 1: arg = args[0] if space.is_true(space.issubtype(space.type(arg), space.w_str)): try: - return space.newint(int(space.unwrap(arg))) + return space.newint(int(space.unwrap(arg))), True except TypeError: raise OperationError(space.w_TypeError, space.wrap("invalid literal for int()")) else: - return space.int(args[0]) + return space.int(args[0]), True else: raise OperationError(space.w_TypeError, space.wrap("int() takes at most 1 argument")) -StdObjSpace.new.register(inttype_new, W_IntType, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/listobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/listobject.py Tue Jun 24 15:50:57 2003 @@ -35,6 +35,27 @@ items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]] return list(items) +def object_init__List_ANY_ANY(space, w_list, w_args, w_kwds): + if space.is_true(w_kwds): + raise OperationError(space.w_TypeError, + space.wrap("no keyword arguments expected")) + w_list.ob_size = 0 # XXX think about it later + args = space.unpackiterable(w_args) + if len(args) == 0: + pass # empty list + elif len(args) == 1: + w_iterable = args[0] + w_iterator = space.iter(w_iterable) + while True: + try: + w_item = space.next(w_iterator) + except NoValue: + break # done + _ins1(w_list, w_list.ob_size, w_item) + else: + raise OperationError(space.w_TypeError, + space.wrap("list() takes at most 1 argument")) + def len__List(space, w_list): result = w_list.ob_size return W_IntObject(space, result) @@ -158,23 +179,24 @@ items[idx] = w_any return space.w_None -# not trivial! +# XXX not trivial! def setitem__List_Slice_List(space, w_list, w_slice, w_list2): - items = w_list.ob_item - w_length = space.wrap(w_list.ob_size) - w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length) - start = space.unwrap(w_start) - step = space.unwrap(w_step) - slicelength = space.unwrap(w_slicelength) - assert slicelength >= 0 - w_res = W_ListObject(space, []) - _list_resize(w_res, slicelength) - subitems = w_res.ob_item - for i in range(slicelength): - subitems[i] = items[start] - start += step - w_res.ob_size = slicelength - return w_res + raise Exception, "not done!" +## items = w_list.ob_item +## w_length = space.wrap(w_list.ob_size) +## w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length) +## start = space.unwrap(w_start) +## step = space.unwrap(w_step) +## slicelength = space.unwrap(w_slicelength) +## assert slicelength >= 0 +## w_res = W_ListObject(space, []) +## _list_resize(w_res, slicelength) +## subitems = w_res.ob_item +## for i in range(slicelength): +## subitems[i] = items[start] +## start += step +## w_res.ob_size = slicelength +## return w_res def repr__List(space, w_list): w = space.wrap Modified: pypy/trunk/src/pypy/objspace/std/listtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/listtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/listtype.py Tue Jun 24 15:50:57 2003 @@ -19,20 +19,7 @@ registerimplementation(W_ListType) -# XXX right now, this is responsible for building a whole new list -# XXX we'll worry about the __new__/__init__ distinction later -def listtype_new(space, w_listtype, w_args, w_kwds): - if space.is_true(w_kwds): - raise OperationError(space.w_TypeError, - space.wrap("no keyword arguments expected")) - args = space.unpackiterable(w_args) - if len(args) == 0: - list_w = [] - elif len(args) == 1: - list_w = space.unpackiterable(args[0]) - else: - raise OperationError(space.w_TypeError, - space.wrap("list() takes at most 1 argument")) - return space.newlist(list_w) +def type_new__ListType_ListType_ANY_ANY(space, w_basetype, w_listtype, w_args, w_kwds): + return space.newlist([]), True -StdObjSpace.new.register(listtype_new, W_ListType, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objectobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objectobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/objectobject.py Tue Jun 24 15:50:57 2003 @@ -17,5 +17,8 @@ return W_ObjectObject(space) delegate__ANY.priority = PRIORITY_PARENT_TYPE +def object_init__Object_ANY_ANY(space, w_object, w_args, w_kwds): + pass + register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Tue Jun 24 15:50:57 2003 @@ -20,14 +20,16 @@ object_str = StdObjSpace.str object_hash = StdObjSpace.hash + # this is a method in 'object' because it is not an object space operation + object_init = MultiMethod('__init__', 3, varargs=True, keywords=True) + registerimplementation(W_ObjectType) -# XXX we'll worry about the __new__/__init__ distinction later -def new__ObjectType_ANY_ANY(space, w_objecttype, w_args, w_kwds): +def type_new__ObjectType_ObjectType_ANY_ANY(space, w_basetype, w_objecttype, w_args, w_kwds): # XXX 2.2 behavior: ignoring all arguments from objectobject import W_ObjectObject - return W_ObjectObject(space) + return W_ObjectObject(space), True ### The following implementations are registered to the Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Tue Jun 24 15:50:57 2003 @@ -302,5 +302,6 @@ # import the common base W_ObjectObject as well as # default implementations of some multimethods for all objects # that don't explicitely override them or that raise FailedToImplement +from pypy.objspace.std.register_all import register_all import pypy.objspace.std.objectobject import pypy.objspace.std.default Modified: pypy/trunk/src/pypy/objspace/std/register_all.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/register_all.py (original) +++ pypy/trunk/src/pypy/objspace/std/register_all.py Tue Jun 24 15:50:57 2003 @@ -14,6 +14,9 @@ for registration. """ from pypy.objspace.std.objspace import StdObjSpace, W_ANY + namespaces = [StdObjSpace] + if alt_ns: + namespaces.insert(0, alt_ns) for name, obj in module_dict.items(): if name.find('__')<1: @@ -32,23 +35,40 @@ i, i, name) l.append(icls) - if len(l) != obj.func_code.co_argcount-1: - raise ValueError, \ - "function name %s doesn't specify exactly %d arguments" % ( - repr(name), obj.func_code.co_argcount-1) + #XXX trying to be too clever at the moment for userobject.SpecialMethod + #if len(l) != obj.func_code.co_argcount-1: + # raise ValueError, \ + # "function name %s doesn't specify exactly %d arguments" % ( + # repr(name), obj.func_code.co_argcount-1) funcname = _name_mappings.get(funcname, funcname) - if hasattr(alt_ns, funcname): - getattr(alt_ns, funcname).register(obj, *l) - else: - getattr(StdObjSpace, funcname).register(obj, *l) + func = hack_func_by_name(funcname, namespaces) + func.register(obj, *l) add_extra_comparisons() +def hack_func_by_name(funcname, namespaces): + for ns in namespaces: + if hasattr(ns, funcname): + return getattr(ns, funcname) + import typetype + try: + return getattr(typetype.W_TypeType, funcname) + except AttributeError: + pass # catches not only the getattr() but the typetype.W_TypeType + # in case it is not fully imported yet :-(((( + import objecttype + try: + return getattr(objecttype.W_ObjectType, funcname) + except AttributeError: + pass # same comment + raise NameError, ("trying hard but not finding a multimethod named %s" % + funcname) + class Curry: def __init__(self, fun, arg): self.fun = fun - self.pending = [arg] + self.pending = (arg,) def __call__(self, *args): return self.fun(*(self.pending + args)) Modified: pypy/trunk/src/pypy/objspace/std/slicetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/slicetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/slicetype.py Tue Jun 24 15:50:57 2003 @@ -8,7 +8,8 @@ registerimplementation(W_SliceType) -def slicetype_new(space, w_slicetype, w_args, w_kwds): + +def type_new__SliceType_SliceType_ANY_ANY(space, w_basetype, w_slicetype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) @@ -28,6 +29,6 @@ else: raise OperationError(space.w_TypeError, space.wrap("slice() takes at least 1 argument")) - return space.newslice(start, stop, step) + return space.newslice(start, stop, step), True -StdObjSpace.new.register(slicetype_new, W_SliceType, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringtype.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringtype.py Tue Jun 24 15:50:57 2003 @@ -41,16 +41,15 @@ registerimplementation(W_StringType) -# XXX we'll worry about the __new__/__init__ distinction later -def new__StringType_ANY_ANY(space, w_stringtype, w_args, w_kwds): +def type_new__StringType_StringType_ANY_ANY(space, w_basetype, w_stringtype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) args = space.unpackiterable(w_args) if len(args) == 0: - return space.newstring([]) + return space.newstring([]), True elif len(args) == 1: - return space.str(args[0]) + return space.str(args[0]), True else: raise OperationError(space.w_TypeError, space.wrap("str() takes at most 1 argument")) Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py Tue Jun 24 15:50:57 2003 @@ -84,7 +84,7 @@ w = space.wrap wd = space.newdict def mydict(w_args=w(()), w_kwds=w({})): - return space.new(space.w_dict, w_args, w_kwds) + return space.call(space.w_dict, w_args, w_kwds) def deepwrap(lp): return [[w(a),w(b)] for a,b in lp] d = mydict() @@ -104,7 +104,7 @@ w = space.wrap wd = space.newdict def mydict(w_args=w(()), w_kwds=w({})): - return space.new(space.w_dict, w_args, w_kwds) + return space.call(space.w_dict, w_args, w_kwds) def deepwrap(lp): return [[w(a),w(b)] for a,b in lp] d = mydict(w_kwds=w({1:2, 3:4})) @@ -129,7 +129,7 @@ space = self.space w = space.wrap def mydict(w_args=w(()), w_kwds=w({})): - return space.new(space.w_dict, w_args, w_kwds) + return space.call(space.w_dict, w_args, w_kwds) d = mydict(w_kwds=w({1:2, 3:4})) get = space.getattr(d, w("get")) self.assertEqual_w(space.call_function(get, w(1)), w(2)) Modified: pypy/trunk/src/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/tupletype.py (original) +++ pypy/trunk/src/pypy/objspace/std/tupletype.py Tue Jun 24 15:50:57 2003 @@ -9,8 +9,7 @@ registerimplementation(W_TupleType) -# XXX we'll worry about the __new__/__init__ distinction later -def tupletype_new(space, w_tupletype, w_args, w_kwds): +def type_new__TupleType_TupleType_ANY_ANY(space, w_basetype, w_tupletype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) @@ -22,6 +21,6 @@ else: raise OperationError(space.w_TypeError, space.wrap("tuple() takes at most 1 argument")) - return space.newtuple(tuple_w) + return space.newtuple(tuple_w), True -StdObjSpace.new.register(tupletype_new, W_TupleType, W_ANY, W_ANY) +register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Tue Jun 24 15:50:57 2003 @@ -94,11 +94,13 @@ code = multimethods[name] if code.bound_position < i: continue - if len(multimethod.specialnames) > 1: - mmcls = SpecialMultimethodCode - else: - mmcls = PyMultimethodCode - code = mmcls(multimethod, typeclass, i) + pycodeclass = multimethod.extras.get('pycodeclass') + if pycodeclass is None: + if len(multimethod.specialnames) > 1: + pycodeclass = SpecialMultimethodCode + else: + pycodeclass = PyMultimethodCode + code = pycodeclass(multimethod, typeclass, i) multimethods[name] = code # add some more multimethods with a special interface code = NextMultimethodCode(spaceclass.next, typeclass) @@ -182,10 +184,21 @@ result = self.do_call(space, w_globals, w_locals) return space.newbool(result) +class NewMultimethodCode(PyMultimethodCode): + + def eval_code(self, space, w_globals, w_locals): + "Call the __new__() method of typetype.py." + w_result, callinit = self.do_call(space, w_globals, w_locals) + return w_result + def call__Type_ANY_ANY(space, w_type, w_args, w_kwds): - w_newobject = space.new(w_type, w_args, w_kwds) - # XXX call __init__() later + type_new = typetype.W_TypeType.type_new.get(space) + w_newobject, callinit = type_new(w_type, w_type, w_args, w_kwds) + if callinit: + import objecttype + object_init = objecttype.W_ObjectType.object_init.get(space) + object_init(w_newobject, w_args, w_kwds) return w_newobject def issubtype__Type_Type(space, w_type1, w_type2): Modified: pypy/trunk/src/pypy/objspace/std/typetype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typetype.py (original) +++ pypy/trunk/src/pypy/objspace/std/typetype.py Tue Jun 24 15:50:57 2003 @@ -1,5 +1,12 @@ from pypy.objspace.std.objspace import * -from typeobject import W_TypeObject # , NewMultimethodCode +from pypy.objspace.std.register_all import register_all +from typeobject import W_TypeObject + + +def NewMultimethodCode_builder(*args): + from typeobject import NewMultimethodCode # sadly necessary late import hack + return NewMultimethodCode(*args) + class W_TypeType(W_TypeObject): """The single instance of this class is the object the user sees as @@ -7,22 +14,31 @@ typename = 'type' -registerimplementation(W_TypeType) + # XXX this is worth tons of comments. + # the four arguments are (T, S, args, kw) for the expression + # T.__new__(S, *args, **kw). There is no (known?) way to get it as + # an unbound method, because 'type.__new__' means reading from the + # instance 'type' of the class 'type', as opposed to reading from + # the class 'type'. + # Attention, this internally returns a tuple (w_result, flag), + # where 'flag' specifies whether we would like __init__() to be called. + type_new = MultiMethod('__new__', 4, varargs=True, keywords=True, + pycodeclass=NewMultimethodCode_builder) +registerimplementation(W_TypeType) -# XXX we'll worry about the __new__/__init__ distinction later -def new__TypeType_ANY_ANY(space, w_typetype, w_args, w_kwds): +def type_new__TypeType_TypeType_ANY_ANY(space, w_basetype, w_typetype, w_args, w_kwds): if space.is_true(w_kwds): raise OperationError(space.w_TypeError, space.wrap("no keyword arguments expected")) args = space.unpackiterable(w_args) if len(args) == 1: - return space.type(args[0]) + return space.type(args[0]), False # don't call __init__() on that elif len(args) == 3: from usertype import W_UserType w_name, w_bases, w_dict = args w_usertype = W_UserType(space, w_name, w_bases, w_dict) - return w_usertype + return w_usertype, True else: raise OperationError(space.w_TypeError, space.wrap("type() takes 1 or 3 arguments")) Modified: pypy/trunk/src/pypy/objspace/std/userobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/userobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/userobject.py Tue Jun 24 15:50:57 2003 @@ -42,10 +42,11 @@ try: return _bltin_subclass_cache[cls] except: - _bltin_subclass_cache[cls] = subcls = type(W_Object)("%s_sub" % cls.__name__,(cls,), - {'statictype': W_UserType, - 'bltbase': cls, - 'dispatchtype': W_UserObject}) + subcls = type(W_Object)("%s_sub" % cls.__name__, (cls,), + {'statictype' : W_UserType, + 'bltbase' : cls, + 'dispatchclass': W_UserObject}) + _bltin_subclass_cache[cls] = subcls return subcls def morph_into_user_object(space,w_type,newobj): @@ -109,12 +110,7 @@ self.method_name = method_name self.bound_position = bound_position - def do_call(self, space, args_w): - # args_w is in the standard multimethod order - # we need it in the Python-friendly order (i.e. swapped for __rxxx__) - args_w = list(args_w) - w_userobj = args_w.pop(self.bound_position) - w_args = space.newtuple(args_w) + def internal_do_call(self, space, w_userobj, w_args, w_kwds): w_key = space.wrap(self.method_name) w_mro = space.getattr(w_userobj.w_type, space.wrap('__mro__')) mro = space.unpacktuple(w_mro) @@ -126,9 +122,17 @@ except KeyError: continue w_method = space.get(w_function, w_userobj, w_base) - return space.call(w_method, w_args, space.newdict([])) + return space.call(w_method, w_args, w_kwds) raise FailedToImplement + def do_call(self, space, args_w): + # args_w is in the standard multimethod order + # we need it in the Python-friendly order (i.e. swapped for __rxxx__) + args_w = list(args_w) + w_userobj = args_w.pop(self.bound_position) + w_args = space.newtuple(args_w) + return self.internal_do_call(space, w_userobj, w_args, space.newdict([])) + def normal_call(self, space, *args_w): "Call a user-defined __xxx__ method and convert the result back." w_result = self.do_call(space, args_w) @@ -155,6 +159,10 @@ w_result = self.do_call(space, args_w) return space.is_true(w_result) + def argskwds_call(self, space, w_userobj, w_args, w_kwds): + "For __init__()." + return self.internal_do_call(space, w_userobj, w_args, w_kwds) + import new for multimethod in typeobject.hack_out_multimethods(StdObjSpace): @@ -166,6 +174,6 @@ next__User = SpecialMethod('next').next_call is_true__User = SpecialMethod('nonzero').nonzero_call - +object_init__User_ANY_ANY = SpecialMethod('__init__').argskwds_call register_all(vars()) Modified: pypy/trunk/src/pypy/objspace/std/usertype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/usertype.py (original) +++ pypy/trunk/src/pypy/objspace/std/usertype.py Tue Jun 24 15:50:57 2003 @@ -53,17 +53,35 @@ # but we're documenting it here as there seems no better place!!! # The problem is actually that, currently, several types such as # int and float just cannot be CALLED -- this needs to be fixed soon. -def new__UserType_ANY_ANY(space, w_usertype, w_args, w_kwds): - from userobject import make_user_object - newobj = make_user_object(space, w_usertype, w_args, w_kwds) - try: - init = space.getattr(newobj, space.wrap('__init__')) - except OperationError, err: - if not err.match(space, space.w_AttributeError): - raise - else: - space.call(init, w_args, w_kwds) - return newobj +def type_new__UserType_UserType_ANY_ANY(space, w_basetype, w_usertype, w_args, w_kwds): + import typetype + # XXX this uses the following algorithm: + # walk the __mro__ of the user type + # for each *user* type t in there, just look for a __new__ in t.__dict__ + # if we get to a *built-in* type t, we use t.__new__, which is a + # bound method from the type 'type'. + for w_looktype in w_basetype.getmro(): + if not isinstance(w_looktype, W_UserType): + # no user-defined __new__ found + type_new = typetype.W_TypeType.type_new.get(space) + return type_new(w_looktype, w_usertype, w_args, w_kwds) + try: + w_new = w_looktype.lookup_exactly_here(space.wrap('__new__')) + except KeyError: + pass + else: + w_newobj = space.call_function(w_new, [w_usertype, w_args, w_kwds]) + return w_newobj, True + raise AssertionError, "execution should not get here" + +def type_new__ANY_UserType_ANY_ANY(space, w_basetype, w_usertype, w_args, w_kwds): + import typetype + from userobject import morph_into_user_object, getsinglebuiltintype + assert w_basetype is getsinglebuiltintype(space, w_usertype) + type_new = typetype.W_TypeType.type_new.get(space) + w_newobject, callinit = type_new(w_basetype, w_basetype, w_args, w_kwds) + morph_into_user_object(space, w_usertype, w_newobject) + return w_newobject, True def getdict__UserType(space, w_usertype): return w_usertype.w_dict From anna at codespeak.net Tue Jun 24 15:54:43 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Tue, 24 Jun 2003 15:54:43 +0200 (MEST) Subject: [pypy-svn] rev 1054 - pypy/trunk/doc Message-ID: <20030624135443.197BD5A269@thoth.codespeak.net> Author: anna Date: Tue Jun 24 15:54:42 2003 New Revision: 1054 Modified: pypy/trunk/doc/readme.txt Log: added some info on how to use reST to the readme Modified: pypy/trunk/doc/readme.txt ============================================================================== --- pypy/trunk/doc/readme.txt (original) +++ pypy/trunk/doc/readme.txt Tue Jun 24 15:54:42 2003 @@ -15,8 +15,32 @@ *Note* If you don't markup the textfile, it'll still be checked in, but when docutils runs the parser, it'll look ugly on the website. -You can get more info on reST markup at http://docutils.sourceforge.net/docs/rst/quickref.html +Some reST basics: +------------------ + +There should be a title on your page. Do it like this:: + + Here is my Title + ================== + + Here is a section title + ------------------------- + +Make sure you have a blank line after your = or - lines or it will give you an error. +For marking a block of code so it'll look right, you can:: + Put a line of text ending with :: + indent your code at least one space + my code + more code + even more code + still more code + +End of the "block" occurs whenever you unindent back to the same level as the text with the ``::`` at the end. + +Using an underscore after a word like this_ will make reST think you want a hyperlink. To avoid that (especially with things like ``wrap_``), you can use the `` back quote `` to mark it as plain text. + +You can get more info on reST markup at http://docutils.sourceforge.net/docs/rst/quickref.html Here are some sample textfiles: @@ -25,5 +49,6 @@ --------------------------------------------------------------------------------- +.. _this: http://docutils.sourceforge.net/docs/rst/quickref.html .. _ObjectSpace: objspace/objspace.txt -.. _ObjectSpaceInterface: objspace/objspaceinterface.txt \ No newline at end of file +.. _ObjectSpaceInterface: objspace/objspaceinterface.txt From gvanrossum at codespeak.net Tue Jun 24 16:20:09 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 16:20:09 +0200 (MEST) Subject: [pypy-svn] rev 1055 - pypy/trunk/src/pypy/interpreter Message-ID: <20030624142009.9F0675A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 16:20:09 2003 New Revision: 1055 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py Log: Fix formatting of traceback to be more compatible. Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Tue Jun 24 16:20:09 2003 @@ -123,7 +123,7 @@ l = '' else: l = linecache.getline(fname, lineno) - print >> file, " File", `fname`+',', + print >> file, " File \"%s\"," % fname, print >> file, "line", lineno, "in", co.co_name if l: if l.endswith('\n'): From anna at codespeak.net Tue Jun 24 16:32:12 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Tue, 24 Jun 2003 16:32:12 +0200 (MEST) Subject: [pypy-svn] rev 1056 - pypy/trunk/doc Message-ID: <20030624143212.D339E5A269@thoth.codespeak.net> Author: anna Date: Tue Jun 24 16:32:12 2003 New Revision: 1056 Modified: pypy/trunk/doc/readme.txt Log: added more reST howto information Modified: pypy/trunk/doc/readme.txt ============================================================================== --- pypy/trunk/doc/readme.txt (original) +++ pypy/trunk/doc/readme.txt Tue Jun 24 16:32:12 2003 @@ -42,7 +42,29 @@ You can get more info on reST markup at http://docutils.sourceforge.net/docs/rst/quickref.html -Here are some sample textfiles: +------------------------ +Checking your work +------------------------ + +In order to make sure that what you commit looks reasonably pretty (or at least not entirely broken), you'll need to run the ``docutils`` parser on it. Unless you've installed it in the past, you probably don't have it installed. Open IDLE (or any Python interactive environment) and try "import docutils". If it imports, hooray! Otherwise, you'll need to download it. + +Go to sourceforge and download the snapshot version. Install it. + +*Note to Debian users:* Be sure you have ``distutils`` installed and working before trying to install ``docutils``. + +Once you have ``docutils`` installed, you can use it go to your shell and use it like this:: + + $ python ~/mypath/docutils/tools/buildhtml.py + /// Processing directory: /home/anna/downloads/arObjSpaceDoc + ::: Processing .txt: howtosvn.txt + ::: Processing .txt: index.txt + +**WARNING** This will process **all** text documents in the directory and any subdirectories. I prefer to work on text in a separate directory, run the ``docutils`` parser to see what it looks like, then copy the .txt file over to my local /doc checkouts to commit it. + +Use a browser to File:Open:filename.html then you can see what it looks like. Look at the command shell to see what errors you've got on which lines and fix it in your textfile. You can then re-run the buildhtml.py script and see what errors you get. After it's fixed, you can commit the .txt file and it'll automagically be turned into html viewable on the website. + + +Here are some sample reST textfiles to see what it looks like: + ObjectSpace_ + ObjectSpaceInterface_ From anna at codespeak.net Tue Jun 24 16:35:29 2003 From: anna at codespeak.net (anna at codespeak.net) Date: Tue, 24 Jun 2003 16:35:29 +0200 (MEST) Subject: [pypy-svn] rev 1057 - pypy/trunk/doc Message-ID: <20030624143529.60B955A269@thoth.codespeak.net> Author: anna Date: Tue Jun 24 16:35:29 2003 New Revision: 1057 Modified: pypy/trunk/doc/readme.txt Log: updated some formatting to make instructions on reST clearer Modified: pypy/trunk/doc/readme.txt ============================================================================== --- pypy/trunk/doc/readme.txt (original) +++ pypy/trunk/doc/readme.txt Tue Jun 24 16:35:29 2003 @@ -48,7 +48,7 @@ In order to make sure that what you commit looks reasonably pretty (or at least not entirely broken), you'll need to run the ``docutils`` parser on it. Unless you've installed it in the past, you probably don't have it installed. Open IDLE (or any Python interactive environment) and try "import docutils". If it imports, hooray! Otherwise, you'll need to download it. -Go to sourceforge and download the snapshot version. Install it. +Go to sourceforge and download the ``snapshot`` version. Install it. *Note to Debian users:* Be sure you have ``distutils`` installed and working before trying to install ``docutils``. @@ -61,7 +61,7 @@ **WARNING** This will process **all** text documents in the directory and any subdirectories. I prefer to work on text in a separate directory, run the ``docutils`` parser to see what it looks like, then copy the .txt file over to my local /doc checkouts to commit it. -Use a browser to File:Open:filename.html then you can see what it looks like. Look at the command shell to see what errors you've got on which lines and fix it in your textfile. You can then re-run the buildhtml.py script and see what errors you get. After it's fixed, you can commit the .txt file and it'll automagically be turned into html viewable on the website. +Use a browser menu to go to ``File: Open: filename.html`` then you can see what it looks like. Look at the command shell to see what errors you've got on which lines and fix it in your textfile. You can then re-run the buildhtml.py script and see what errors you get. After it's fixed, you can commit the .txt file and it'll automagically be turned into html viewable on the website. Here are some sample reST textfiles to see what it looks like: From gvanrossum at codespeak.net Tue Jun 24 17:04:50 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 17:04:50 +0200 (MEST) Subject: [pypy-svn] rev 1058 - pypy/trunk/src/pypy/interpreter Message-ID: <20030624150450.E9A9C5A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 17:04:50 2003 New Revision: 1058 Modified: pypy/trunk/src/pypy/interpreter/pyframe.py Log: cloning frames wasn't cloning the new fast locals. Now it does. Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Tue Jun 24 17:04:50 2003 @@ -24,7 +24,8 @@ self.bytecode = bytecode # Misnomer; this is really like a code object self.w_globals = w_globals self.w_locals = w_locals - self.localcells, self.nestedcells = bytecode.locals2cells(space, w_locals) + self.localcells, self.nestedcells = bytecode.locals2cells(space, + w_locals) self.w_builtins = self.load_builtins() self.valuestack = Stack() self.blockstack = Stack() @@ -32,14 +33,14 @@ self.next_instr = 0 def clone(self): - # Clone the locals (only the annotation space implements this) - w_locals = self.space.clone_locals(self.w_locals) - # XXX assume globals are constant - f = PyFrame(self.space, self.bytecode, self.w_globals, w_locals) + # XXX assume locals and globals are constant + f = PyFrame(self.space, self.bytecode, self.w_globals, self.w_locals) f.valuestack = self.valuestack.clone() f.blockstack = self.blockstack.clone() f.last_exception = self.last_exception f.next_instr = self.next_instr + f.localcells = clonecells(self.localcells) + f.nestedcells = clonecells(self.nestedcells) return f def eval(self, executioncontext): @@ -109,7 +110,7 @@ def fast2locals(self): # Copy values from self.localcells to self.w_locals - for i in range(self.bytecode.co_nlocals): + for i in range(len(self.localcells)): name = self.bytecode.co_varnames[i] cell = self.localcells[i] w_name = self.space.wrap(name) @@ -375,3 +376,16 @@ return "%s()" % self.__class__.__name__ else: return "%s(%s)" % (self.__class__.__name__, self.w_value) + +def clonecells(cells): + """Clone a list of cells.""" + newcells = [] + for cell in cells: + try: + value = cell.get() + except ValueError: + newcell = Cell() + else: + newcell = Cell(value) + newcells.append(newcell) + return newcells From gvanrossum at codespeak.net Tue Jun 24 17:19:44 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Tue, 24 Jun 2003 17:19:44 +0200 (MEST) Subject: [pypy-svn] rev 1059 - in pypy/trunk/src/pypy/objspace/ann: . test Message-ID: <20030624151944.512D25A269@thoth.codespeak.net> Author: gvanrossum Date: Tue Jun 24 17:19:43 2003 New Revision: 1059 Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py pypy/trunk/src/pypy/objspace/ann/wrapper.py Log: More functionality added to the annotation space. One thing added is properly creating function objects from code. M objspace.py support calling python functions support newslice reraise exception on add of incompatible arguments M wrapper.py add W_PythonFunction M test\test_objspace.py two new tests that helped discover the problem with cloning fast locals Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Tue Jun 24 17:19:43 2003 @@ -130,6 +130,8 @@ def newfunction(self, code, w_globals, w_defaults, w_closure=None): if isinstance(code, PyBuiltinCode): return W_BuiltinFunction(code, w_defaults) + if isinstance(code, PyByteCode): + return W_PythonFunction(code, w_globals, w_defaults, w_closure) return W_Anything() def newlist(self, list_w): @@ -158,6 +160,25 @@ self.reraise() return W_Constant(s) + def newslice(self, w_start, w_stop, w_end=None): + try: + if w_start is None: + start = None + else: + start = self.unwrap(w_start) + if w_stop is None: + stop = None + else: + stop = self.unwrap(w_stop) + if w_end is None: + end = None + else: + end = self.unwrap(w_end) + except UnwrapException: + return W_Anything() # W_Slice()??? + else: + return self.wrap(slice(start, stop, end)) + # Methods implementing Python operations # (Many missing ones are added by make_op() below) @@ -185,7 +206,11 @@ except UnwrapException: pass else: - return self.wrap(left + right) + try: + sum = left + right + except: + self.reraise() + return self.wrap(sum) if is_int(w_left) and is_int(w_right): return W_Integer() else: @@ -237,10 +262,16 @@ raise IndeterminateCondition(w_iterator) def call(self, w_func, w_args, w_kwds): + w_closure = None if isinstance(w_func, W_BuiltinFunction): bytecode = w_func.code w_defaults = w_func.w_defaults w_globals = self.w_None + elif isinstance(w_func, W_PythonFunction): + bytecode = w_func.code + w_defaults = w_func.w_defaults + w_closure = w_func.w_closure + w_globals = w_func.w_globals else: try: func = self.unwrap(w_func) @@ -257,11 +288,10 @@ self.bytecodecache[code] = bytecode w_defaults = self.wrap(func.func_defaults) w_globals = self.wrap(func.func_globals) - w_locals = bytecode.build_arguments(self, - w_args, - w_kwds, - w_defaults, - self.wrap(())) + if w_closure is None: + w_closure = self.wrap(()) + w_locals = bytecode.build_arguments(self, w_args, w_kwds, + w_defaults, w_closure) w_result = bytecode.eval_code(self, w_globals, w_locals) return w_result Modified: pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Tue Jun 24 17:19:43 2003 @@ -103,6 +103,24 @@ 'f', [W_Integer()]) self.assertEquals(type(x), W_Integer) + def test_assign_local(self): + x = self.codetest("def f():\n" + " x = 1\n" + " y = 2\n" + " return x+y\n", + 'f', []) + self.assertEquals(self.space.unwrap(x), 3) + + def test_assign_local_w_flow_control(self): + code = """ +def f(n): + total = 0 + for i in range(n): + total = total + 1 + return n +""" + x = self.codetest(code, 'f', [self.space.wrap(3)]) + self.assertEquals(self.space.unwrap(x), 3) def dont_test_global(self): # XXX This will never work, because we don't handle mutating globals Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Tue Jun 24 17:19:43 2003 @@ -142,6 +142,23 @@ def argsrepr(self): return repr(self.code) + ", " + repr(self.w_defaults) +class W_PythonFunction(W_Object): + """A Python function.""" + + def __init__(self, code, w_globals, w_defaults, w_closure=None): + self.code = code + self.w_globals = w_globals + self.w_defaults = w_defaults + self.w_closure = w_closure + + def argsrepr(self): + s = repr(self.code) + ", " + repr(self.w_globals) + s += ", " + repr(self.w_defaults) + if self.w_closure != None: + s += ", " + repr(self.w_closure) + return s + + def unify_frames(f1, f2): """Given two compatible frames, make them the same. From arigo at codespeak.net Tue Jun 24 17:27:14 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Jun 2003 17:27:14 +0200 (MEST) Subject: [pypy-svn] rev 1060 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624152714.6CB705A269@thoth.codespeak.net> Author: arigo Date: Tue Jun 24 17:27:13 2003 New Revision: 1060 Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Log: dict tests pass again (sorry Alex, I was misunderstanding the original dict.__new__ when I translated into dict.__init__). Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/dictobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/dictobject.py Tue Jun 24 17:27:13 2003 @@ -89,7 +89,6 @@ return result def object_init__Dict_ANY_ANY(space, w_dict, w_args, w_kwds): - # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed dict_clear__Dict(space, w_dict) args = space.unpackiterable(w_args) if len(args) == 0: @@ -107,6 +106,7 @@ else: raise OperationError(space.w_TypeError, space.wrap("dict() takes at most 1 argument")) + dict_update__Dict_Dict(space, w_dict, w_kwds) def getitem__Dict_ANY(space, w_dict, w_lookup): data = w_dict.non_empties() Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Tue Jun 24 17:27:13 2003 @@ -19,7 +19,7 @@ def from_x_to_str_sometimes(space, xinstance): if xinstance.value: - return '!' + repr(xinstance.value) + return w('!' + repr(xinstance.value)) else: return [] @@ -72,6 +72,19 @@ return '' % (x,) w_TypeError = 'w_TypeError' +def w(x, cache={}): + if type(x) in cache: + Stub = cache[type(x)] + else: + class Stub(type(x)): + pass + Stub.dispatchclass = Stub + cache[type(x)] = Stub + return Stub(x) + +X.dispatchclass = X +Y.dispatchclass = Y + class TestMultiMethod(test.TestCase): @@ -96,28 +109,28 @@ r = space.add(X(-3), Y(20)) self.assertEquals(repr(r), "('add_x_x', , >)") - r = space.add(-3, [7,6,5]) + r = space.add(w(-3), w([7,6,5])) self.assertEquals(repr(r), "('add_int_any', -3, [7, 6, 5])") - r = space.add(5,"test") + r = space.add(w(5), w("test")) self.assertEquals(repr(r), "('add_int_string', 5, 'test')") - r = space.add("x","y") + r = space.add(w("x"), w("y")) self.assertEquals(repr(r), "('add_string_string', 'x', 'y')") - self.assertRaises(OperationError, space.add, [3],4) + self.assertRaises(OperationError, space.add, w([3]), w(4)) - self.assertRaises(OperationError, space.add, 3.0,'bla') + self.assertRaises(OperationError, space.add, w(3.0), w('bla')) - r = space.add(X(42),"spam") + r = space.add(X(42), w("spam")) self.assertEquals(repr(r), "('add_string_string', '!42', 'spam')") - r = space.add(Y(20),"egg") + r = space.add(Y(20), w("egg")) self.assertEquals(repr(r), "('add_string_string', '!', 'egg')") - self.assertRaises(OperationError, space.add, X(0),"spam") + self.assertRaises(OperationError, space.add, X(0), w("spam")) - self.assertRaises(OperationError, space.add, Y(666),"egg") + self.assertRaises(OperationError, space.add, Y(666), w("egg")) if __name__ == '__main__': From guenter at codespeak.net Tue Jun 24 21:14:43 2003 From: guenter at codespeak.net (guenter at codespeak.net) Date: Tue, 24 Jun 2003 21:14:43 +0200 (MEST) Subject: [pypy-svn] rev 1061 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030624191443.2685E5A269@thoth.codespeak.net> Author: guenter Date: Tue Jun 24 21:14:42 2003 New Revision: 1061 Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: __repr__ implemented Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Tue Jun 24 21:14:42 2003 @@ -119,7 +119,10 @@ def _islower(ch): o = ord(ch) return (o>=97 and o<=122) - + +def _isreadable(ch): #following CPython string_repr + o = ord(ch) + return (o>=32 and o <127) def _is_generic(self, fun): space = w_self.space @@ -880,13 +883,78 @@ import iterobject return iterobject.W_SeqIterObject(space, w_list) + +#for comparison and understandiong of the underlying algorithm the unrestricted implementation +#def repr__String(space, w_str): +# u_str = space.unwrap(w_str) +# +# quote = '\'' +# if '\'' in u_str and not '"' in u_str: +# quote = '"' +# +# u_repr = quote +# +# for i in range(len(u_str)): +# c = u_str[i] +# if c == '\\' or c == quote: u_repr+= '\\'+c +# elif c == '\t': u_repr+= '\\t' +# elif c == '\r': u_repr+= '\\r' +# elif c == '\n': u_repr+= '\\n' +# elif not _isreadable(c) : +# u_repr+= '\\' + hex(ord(c))[-3:] +# else: +# u_repr += c +# +# u_repr += quote +# +# return space.wrap(u_repr) + def repr__String(space, w_str): - # XXX this is bogus -- mwh - return space.wrap(repr(space.unwrap(w_str))) - a = space.add - q = space.wrap("'") - return a(a(q, w_str), q) + u_str = space.unwrap(w_str) + quote = '\'' + if '\'' in u_str and not '"' in u_str: + quote = '"' + + buflen = 2 + for i in range(len(u_str)): + c = u_str[i] + if c in quote+"\\\r\t\n" : + buflen+= 2 + elif _isreadable(c) : + buflen+= 1 + else: + buflen+= 4 + + buf = [' ']* buflen + + buf[0] = quote + j=1 + for i in range(len(u_str)): + #print buflen-j + c = u_str[i] + if c in quote+"\\\r\t\n" : + buf[j]= '\\' + j+=1 + if c == quote or c=='\\': buf[j] = c + elif c == '\t': buf[j] = 't' + elif c == '\r': buf[j] = 'r' + elif c == '\n': buf[j] = 'n' + j +=1 + elif not _isreadable(c) : + buf[j]= '\\' + j+=1 + for x in hex(ord(c))[-3:]: + buf[j] = x + j+=1 + else: + buf[j] = c + j+=1 + + buf[j] = quote + return space.wrap("".join(buf)) + + def ord__String(space, w_str): return space.wrap(ord(space.unwrap(w_str))) Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Tue Jun 24 21:14:42 2003 @@ -13,7 +13,7 @@ def tearDown(self): pass - def test_order_rich(self): + def qqqtest_order_rich(self): space = self.space def w(txt): return W_StringObject(space, txt) @@ -40,12 +40,12 @@ w(str2), pypyconst)) - def test_equality(self): + def qqqtest_equality(self): w = self.space.wrap self.assertEqual_w(w('abc'), w('abc')) self.assertNotEqual_w(w('abc'), w('def')) - def test_order_cmp(self): + def qqqtest_order_cmp(self): space = self.space w = space.wrap self.failUnless_w(space.lt(w('a'), w('b'))) @@ -53,12 +53,12 @@ self.failUnless_w(space.le(w('a'), w('a'))) self.failUnless_w(space.gt(w('a'), w(''))) - def test_truth(self): + def qqqtest_truth(self): w = self.space.wrap self.failUnless_w(w('non-empty')) self.failIf_w(w('')) - def test_getitem(self): + def qqqtest_getitem(self): space = self.space w = space.wrap w_str = w('abc') @@ -69,7 +69,7 @@ w_str, w(3)) - def test_slice(self): + def qqqtest_slice(self): space = self.space w = space.wrap w_str = w('abc') @@ -92,7 +92,7 @@ w_slice = space.newslice(w(-1), space.w_None, None) self.assertEqual_w(space.getitem(w_str, w_slice), w('c')) - def test_extended_slice(self): + def qqqtest_extended_slice(self): space = self.space if self.space.__class__.__name__.startswith('Trivial'): import sys @@ -116,7 +116,7 @@ #AttributeError: W_StringObject instance has no attribute 'ljust' -# def test_ljust(self): +# def qqqtest_ljust(self): # w = self.space.wrap # s = "abc" # @@ -129,7 +129,7 @@ def setUp(self): self.space = test.objspace('std') - def test_split(self): + def qqqtest_split(self): self.assertEquals("".split(), []) self.assertEquals("a".split(), ['a']) self.assertEquals(" a ".split(), ['a']) @@ -148,13 +148,13 @@ self.assertEquals('endcase test'.split('test'), ['endcase ', '']) - def test_split_splitchar(self): + def qqqtest_split_splitchar(self): self.assertEquals("/a/b/c".split('/'), ['','a','b','c']) - def test_title(self): + def qqqtest_title(self): self.assertEquals("brown fox".title(), "Brown Fox") - def test_capitalize(self): + def qqqtest_capitalize(self): self.assertEquals("brown fox".capitalize(), "Brown fox") self.assertEquals(' hello '.capitalize(), ' hello ') self.assertEquals('Hello '.capitalize(), 'Hello ') @@ -162,7 +162,7 @@ self.assertEquals('aaaa'.capitalize(), 'Aaaa') self.assertEquals('AaAa'.capitalize(), 'Aaaa') - def test_rjust(self): + def qqqtest_rjust(self): s = "abc" self.assertEquals(s.rjust(2), s) self.assertEquals(s.rjust(3), s) @@ -174,7 +174,7 @@ self.assertEquals('abc'.rjust(2), 'abc') - def test_ljust(self): + def qqqtest_ljust(self): s = "abc" self.assertEquals(s.ljust(2), s) self.assertEquals(s.ljust(3), s) @@ -185,7 +185,7 @@ self.assertEquals('abc'.ljust(3), 'abc') self.assertEquals('abc'.ljust(2), 'abc') - def test_replace(self): + def qqqtest_replace(self): self.assertEquals('one!two!three!'.replace('!', '@', 1), 'one at two!three!') self.assertEquals('one!two!three!'.replace('!', ''), 'onetwothree') self.assertEquals('one!two!three!'.replace('!', '@', 2), 'one at two@three!') @@ -206,7 +206,7 @@ self.assertEquals('123x123'.replace('123', ''), 'x') - def test_strip(self): + def qqqtest_strip(self): s = " a b " self.assertEquals(s.strip(), "a b") self.assertEquals(s.rstrip(), " a b") @@ -215,7 +215,7 @@ self.assertEquals('xyzzyhelloxyzzy'.lstrip('xyz'), 'helloxyzzy') self.assertEquals('xyzzyhelloxyzzy'.rstrip('xyz'), 'xyzzyhello') - def test_zfill(self): + def qqqtest_zfill(self): self.assertEquals('123'.zfill(2), '123') self.assertEquals('123'.zfill(3), '123') self.assertEquals('123'.zfill(4), '0123') @@ -229,7 +229,7 @@ self.assertEquals('34'.zfill(1), '34') self.assertEquals('34'.zfill(4), '0034') - def test_center(self): + def qqqtest_center(self): s="a b" self.assertEquals(s.center(0), "a b") self.assertEquals(s.center(1), "a b") @@ -247,7 +247,7 @@ self.assertEquals('abc'.center(2), 'abc') - def test_count(self): + def qqqtest_count(self): self.assertEquals("".count("x"),0) self.assertEquals("".count(""),1) self.assertEquals("Python".count(""),7) @@ -260,7 +260,7 @@ self.assertEquals('aaa'.count('a', 0, -10), 0) - def test_startswith(self): + def qqqtest_startswith(self): self.assertEquals('ab'.startswith('ab'),1) self.assertEquals('ab'.startswith('a'),1) self.assertEquals('ab'.startswith(''),1) @@ -272,7 +272,7 @@ self.assertEquals('y'.startswith('xx'),0) - def test_endswith(self): + def qqqtest_endswith(self): self.assertEquals('ab'.endswith('ab'),1) self.assertEquals('ab'.endswith('b'),1) self.assertEquals('ab'.endswith(''),1) @@ -283,7 +283,7 @@ self.assertEquals('x'.endswith('xx'),0) self.assertEquals('y'.endswith('xx'),0) - def test_expandtabs(self): + def qqqtest_expandtabs(self): self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(4), 'abc\rab def\ng hi') @@ -305,7 +305,7 @@ self.assertEquals(''.expandtabs(),'') - def test_splitlines(self): + def qqqtest_splitlines(self): s="ab\nab\n \n x\n\n\n" self.assertEquals(s.splitlines(),['ab', 'ab', ' ', ' x', '', '']) self.assertEquals(s.splitlines(),s.splitlines(0)) @@ -314,12 +314,12 @@ self.assertEquals(s.splitlines(),['', 'one', '\two', 'three', '']) self.assertEquals(s.splitlines(1),['\n', 'one\n', '\two\n', 'three\n', '\n']) - def test_find(self): + def qqqtest_find(self): self.assertEquals('abcdefghiabc'.find('abc'), 0) self.assertEquals('abcdefghiabc'.find('abc', 1), 9) self.assertEquals('abcdefghiabc'.find('def', 4), -1) - def test_index(self): + def qqqtest_index(self): self.assertEquals('abcdefghiabc'.index(''), 0) self.assertEquals('abcdefghiabc'.index('def'), 3) self.assertEquals('abcdefghiabc'.index('abc'), 0) @@ -330,13 +330,13 @@ #self.assertRaises(ValueError, 'abcdefghi'.index('ghi', 8)) #self.assertRaises(ValueError, 'abcdefghi'.index('ghi', -1)) - def test_rfind(self): + def qqqtest_rfind(self): self.assertEquals('abcdefghiabc'.rfind('abc'), 9) self.assertEquals('abcdefghiabc'.rfind(''), 12) self.assertEquals('abcdefghiabc'.rfind('abcd'), 0) self.assertEquals('abcdefghiabc'.rfind('abcz'), -1) - def test_rindex(self): + def qqqtest_rindex(self): self.assertEquals('abcdefghiabc'.rindex(''), 12) self.assertEquals('abcdefghiabc'.rindex('def'), 3) self.assertEquals('abcdefghiabc'.rindex('abc'), 9) @@ -349,7 +349,7 @@ #self.assertRaises(ValueError, 'abcdefghi'.rindex('ghi', 0, -1)) - def test_split_maxsplit(self): + def qqqtest_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) self.assertEquals("a/b/c".split("/"), ['a', 'b', 'c']) self.assertEquals(" a ".split(None, 0), ['a ']) @@ -357,28 +357,47 @@ self.assertEquals(" a a ".split(" ", 0), [' a a ']) self.assertEquals(" a a ".split(" ", 1), ['', 'a a ']) - def test_join(self): + def qqqtest_join(self): self.assertEquals(", ".join(['a', 'b', 'c']), "a, b, c") self.assertEquals("".join([]), "") self.assertEquals("-".join(['a', 'b']), 'a-b') - def test_lower(self): + def qqqtest_lower(self): self.assertEquals("aaa AAA".lower(), "aaa aaa") self.assertEquals("".lower(), "") - def test_upper(self): + def qqqtest_upper(self): self.assertEquals("aaa AAA".upper(), "AAA AAA") self.assertEquals("".upper(), "") - def test_swapcase(self): + def qqqtest_swapcase(self): self.assertEquals("aaa AAA 111".swapcase(), "AAA aaa 111") self.assertEquals("".swapcase(), "") - def test_iter(self): + def qqqtest_iter(self): l=[] for i in iter("42"): l.append(i) self.assertEquals(l, ['4','2']) + + def test_repr(self): + self.assertEquals(repr("") ,"''") + self.assertEquals(repr("a") ,"'a'") + self.assertEquals(repr("'") ,'"\'"') + self.assertEquals(repr("\'") ,"\"\'\"") + self.assertEquals(repr("\"") ,'\'"\'') + self.assertEquals(repr("\t") ,"'\\t'") + self.assertEquals(repr("\\") ,"'\\\\'") + self.assertEquals(repr('') ,"''") + self.assertEquals(repr('a') ,"'a'") + self.assertEquals(repr('"') ,"'\"'") + self.assertEquals(repr('\'') ,'"\'"') + self.assertEquals(repr('\"') ,"'\"'") + self.assertEquals(repr('\t') ,"'\\t'") + self.assertEquals(repr('\\') ,"'\\\\'") + self.assertEquals(repr("'''\"") ,'\'\\\'\\\'\\\'"\'') + self.assertEquals(repr(chr(19)) ,"'\\x13'") + if __name__ == '__main__': test.main() From hpk at codespeak.net Sat Jun 28 22:38:44 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 28 Jun 2003 22:38:44 +0200 (MEST) Subject: [pypy-svn] rev 1062 - pypy/trunk/doc/sprintinfo Message-ID: <20030628203844.682F05AF19@thoth.codespeak.net> Author: hpk Date: Sat Jun 28 22:38:43 2003 New Revision: 1062 Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt pypy/trunk/doc/sprintinfo/sprint-planning.txt Log: fixed some formatting. more doc enhancements to follow ... Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt (original) +++ pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Sat Jun 28 22:38:43 2003 @@ -5,10 +5,8 @@ - reviewed, improved and enriched object implementations mostly done by Christian, Alex - boolobject_, cpythonobject_, instmethobject_, longobject_ (removed), - sliceobject_, userobject_, dictobject_, iterobject_ - not reviewed so far? - tupleobject, listobject, intobject, floatobject + boolobject_, cpythonobject_, instmethodobject_, longobject_ (removed), + sliceobject_, userobject_, dictobject_, iterobject_. - stringobject was completed with lots of tests (Tomek, Guenter) @@ -30,7 +28,6 @@ - implemented the beginnings of the AnnotationObjectSpace (Armin, Guido, Michael) for abstract interpretation. - - added lots of tests (all of us) @@ -62,13 +59,12 @@ --------------------------------------------------------------- .. _boolobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000381.html -.. _cpythonobj: http://codespeak.net/pipermail/pypy-svn/2003-June/000385.html -.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html -.. _long: http://codespeak.net/pipermail/pypy-svn/2003-June/000410.html +.. _cpythonobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000385.html +.. _instmethodobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html +.. _longobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000410.html .. _sliceobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000408.html .. _userobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000449.html .. _dictobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000515.html .. _intobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000443.html -.. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html -.. _iterobject:: http://codespeak.net/pipermail/pypy-svn/2003-June/000999.html +.. _iterobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000999.html Modified: pypy/trunk/doc/sprintinfo/sprint-planning.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/sprint-planning.txt (original) +++ pypy/trunk/doc/sprintinfo/sprint-planning.txt Sat Jun 28 22:38:43 2003 @@ -86,5 +86,5 @@ .. _dictobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000515.html .. _intobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000443.html .. _instmethod: http://codespeak.net/pipermail/pypy-svn/2003-June/000389.html -.. _iterobject:: http://codespeak.net/pipermail/pypy-svn/2003-June/000999.html +.. _iterobject: http://codespeak.net/pipermail/pypy-svn/2003-June/000999.html From jum at codespeak.net Sun Jun 29 01:26:21 2003 From: jum at codespeak.net (jum at codespeak.net) Date: Sun, 29 Jun 2003 01:26:21 +0200 (MEST) Subject: [pypy-svn] rev 1063 - pypy/trunk/doc/devel Message-ID: <20030628232621.01FFB5BC18@thoth.codespeak.net> Author: jum Date: Sun Jun 29 01:26:20 2003 New Revision: 1063 Modified: pypy/trunk/doc/devel/howtosvn.txt Log: Changed link to the newest Windows svn GUI client. Modified: pypy/trunk/doc/devel/howtosvn.txt ============================================================================== --- pypy/trunk/doc/devel/howtosvn.txt (original) +++ pypy/trunk/doc/devel/howtosvn.txt Sun Jun 29 01:26:20 2003 @@ -108,7 +108,7 @@ .. _commandline: http://codespeak.net/~jum/svn-0.24.2-setup.exe .. _website: http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B259403 -.. _GUI: http://codespeak.net/~jum/TortoiseSVN-0.11.2-UNICODE.msi +.. _GUI: http://codespeak.net/~jum/TortoiseSVN-0.12.1-UNICODE.msi .. _Win: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4B6140F9-2D36-4977-8FA1-6F8A0F5DCA8F .. _MacOS: http://codespeak.net/~jum/svn-0.24.2-darwin-ppc.tar.gz .. _iconv: http://codespeak.net/~jum/iconv-darwin-ppc.tar.gz From hpk at codespeak.net Sun Jun 29 12:45:27 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 29 Jun 2003 12:45:27 +0200 (MEST) Subject: [pypy-svn] rev 1064 - in pypy/trunk/src/pypy: interpreter objspace/stdobjspace/std/test Message-ID: <20030629104527.54D155AA42@thoth.codespeak.net> Author: hpk Date: Sun Jun 29 12:45:26 2003 New Revision: 1064 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py pypy/trunk/src/pypy/objspace/std/register_all.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Log: fixes to get our trunk to run the tests again. Obviously in the last hours of the sprint nobody really ran all the tests?! Maybe the fact that stringobject now uses the list object to implement itself brought up some boostrapping issues regarding strings <-> lists. For me, all tests pass now for all object spaces. M interpreter/executioncontext.py fixed exception printing problem (probably a bootstrap issue regarding string ops) M objspace/std/test/test_multimethod.py rearranged to more finer grained unit tests. obvious delegation doesn't work as expected with the FakeObjSpace. I had to disable one delegation-test! Please somebody look into it! I couldn't figure out why exactly but it's probably due to Armin/Samuele's latest changes in combination with other's changes. M objspace/std/register_all.py disabled the add_extra_comparison stuff because it also seems to have bootrapping issues. Probably because it tries to iterate over all types on every register_all invocation of each module. Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sun Jun 29 12:45:26 2003 @@ -152,7 +152,7 @@ if exc_value is None: print >> file, exc_typename else: - print >> file, exc_typename+':', exc_value + print >> file, exc_typename, exc_value class NoValue(Exception): Modified: pypy/trunk/src/pypy/objspace/std/register_all.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/register_all.py (original) +++ pypy/trunk/src/pypy/objspace/std/register_all.py Sun Jun 29 12:45:26 2003 @@ -45,8 +45,10 @@ func = hack_func_by_name(funcname, namespaces) func.register(obj, *l) + add_extra_comparisons() + def hack_func_by_name(funcname, namespaces): for ns in namespaces: if hasattr(ns, funcname): @@ -76,13 +78,22 @@ def inverted_comparison(function, space, w_1, w_2): return space.not_(function(space, w_1, w_2)) -def add_extra_comparisons( - operators=(('eq', 'ne'), ('lt', 'ge'), ('gt', 'le'))): +def add_extra_comparisons(): """ If the module has defined eq, lt or gt, check if it already has ne, ge and le respectively. If not, then add them as space.not_ on the implemented methods. """ + return + #XXX disabled because it doesn't work correctly probably + # because it iterates over partially initialized method tables + # we also had discussions on the LLN sprint to implement + # a < b with b > a and so on. I wonder whether the automatic + # creation of boolean operators is really worth it. instead + # we could just implement the operators in their appropriate + # files + operators=(('eq', 'ne'), ('lt', 'ge'), ('gt', 'le')) + from pypy.objspace.std.objspace import StdObjSpace, W_ANY for method, mirror in operators: Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Sun Jun 29 12:45:26 2003 @@ -87,50 +87,56 @@ class TestMultiMethod(test.TestCase): + def setUp(self): + self.space = FakeObjSpace() - def test_base(self): - space = FakeObjSpace() + def test_non_delegate(self): + space = self.space r = space.add(X(2), X(5)) self.assertEquals(repr(r), "('add_x_x', , )") r = space.add(X(3), Y(4)) self.assertEquals(repr(r), "('add_x_y', , )") - - r = space.add(Y(-1), X(7)) - self.assertEquals(repr(r), "('add_x_x', >, )") - - r = space.add(Y(1), X(7)) - self.assertEquals(repr(r), "('add_x_x', >, )") - + r = space.add(Y(0), Y(20)) self.assertEquals(repr(r), "('add_y_y', , )") - - r = space.add(X(-3), Y(20)) - self.assertEquals(repr(r), "('add_x_x', , >)") - + r = space.add(w(-3), w([7,6,5])) self.assertEquals(repr(r), "('add_int_any', -3, [7, 6, 5])") r = space.add(w(5), w("test")) self.assertEquals(repr(r), "('add_int_string', 5, 'test')") - + r = space.add(w("x"), w("y")) self.assertEquals(repr(r), "('add_string_string', 'x', 'y')") - self.assertRaises(OperationError, space.add, w([3]), w(4)) + def test_delegate_y_to_x(self): + space = self.space + r = space.add(Y(-1), X(7)) + self.assertEquals(repr(r), "('add_x_x', >, )") + r = space.add(Y(1), X(7)) + self.assertEquals(repr(r), "('add_x_x', >, )") + + r = space.add(X(-3), Y(20)) + self.assertEquals(repr(r), "('add_x_x', , >)") + + def test_no_operation_defined(self): + space = self.space + self.assertRaises(OperationError, space.add, w([3]), w(4)) self.assertRaises(OperationError, space.add, w(3.0), w('bla')) + self.assertRaises(OperationError, space.add, X(0), w("spam")) + self.assertRaises(OperationError, space.add, Y(666), w("egg")) + def _test_delegate_x_to_str_sometimes(self): + space = self.space r = space.add(X(42), w("spam")) self.assertEquals(repr(r), "('add_string_string', '!42', 'spam')") r = space.add(Y(20), w("egg")) self.assertEquals(repr(r), "('add_string_string', '!', 'egg')") - self.assertRaises(OperationError, space.add, X(0), w("spam")) - - self.assertRaises(OperationError, space.add, Y(666), w("egg")) if __name__ == '__main__': From mwh at codespeak.net Mon Jun 30 11:23:52 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 30 Jun 2003 11:23:52 +0200 (MEST) Subject: [pypy-svn] rev 1065 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030630092352.797785AF1A@thoth.codespeak.net> Author: mwh Date: Mon Jun 30 11:23:51 2003 New Revision: 1065 Modified: pypy/trunk/src/pypy/objspace/std/objspace.py Log: Tomek's fix wasn't quite right. Modified: pypy/trunk/src/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/std/objspace.py Mon Jun 30 11:23:51 2003 @@ -132,7 +132,7 @@ base = done[b.__name__] newtype = self.call_function( self.w_type, - w(v), + w(next), self.newtuple([base]), self.newdict([])) setattr(self, From mwh at codespeak.net Mon Jun 30 11:44:12 2003 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 30 Jun 2003 11:44:12 +0200 (MEST) Subject: [pypy-svn] rev 1066 - pypy/trunk/src/pypy/interpreter Message-ID: <20030630094412.3A4A05AF1A@thoth.codespeak.net> Author: mwh Date: Mon Jun 30 11:44:11 2003 New Revision: 1066 Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py Log: revert hpk's slightly inappropriate fix. Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/executioncontext.py (original) +++ pypy/trunk/src/pypy/interpreter/executioncontext.py Mon Jun 30 11:44:11 2003 @@ -152,7 +152,7 @@ if exc_value is None: print >> file, exc_typename else: - print >> file, exc_typename, exc_value + print >> file, exc_typename+':', exc_value class NoValue(Exception): From arigo at codespeak.net Mon Jun 30 16:44:32 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 30 Jun 2003 16:44:32 +0200 (MEST) Subject: [pypy-svn] rev 1067 - in pypy/trunk/src/pypy/objspace/std: . test Message-ID: <20030630144432.321C05BBA2@thoth.codespeak.net> Author: arigo Date: Mon Jun 30 16:44:31 2003 New Revision: 1067 Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Log: Fixed the genuine problem reported by the disabled test in test_multimethod. Re-enabled the test. Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Mon Jun 30 16:44:31 2003 @@ -140,7 +140,8 @@ parenttypes += list(t.__bases__) if parenttypes: def delegate_to_parent_classes(space, a, parenttypes=parenttypes): - return [(t, a) for t in parenttypes] + return [(t, a) for t in parenttypes + if issubclass(a.dispatchclass, t)] # hard-wire it at priority 0 by_priority[0] = [((t,), delegate_to_parent_classes) for t in arg1types] @@ -265,6 +266,7 @@ for argi in range(arity-1, -1, -1): curtypes = types[argi] # growing tuple of types we can delegate to + assert len(curtypes) == 1 curobjs = {curtypes[0]: args[argi]} # maps them to actual objects args = args[:argi] # initial segments of arguments before this one types = types[:argi] # same with types (no deleg tried on them yet) Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py Mon Jun 30 16:44:31 2003 @@ -76,8 +76,7 @@ if type(x) in cache: Stub = cache[type(x)] else: - class Stub(type(x)): - pass + Stub = type(type(x))('%s_stub' % type(x).__name__, (type(x),), {}) Stub.dispatchclass = Stub cache[type(x)] = Stub return Stub(x) @@ -129,7 +128,7 @@ self.assertRaises(OperationError, space.add, X(0), w("spam")) self.assertRaises(OperationError, space.add, Y(666), w("egg")) - def _test_delegate_x_to_str_sometimes(self): + def test_delegate_x_to_str_sometimes(self): space = self.space r = space.add(X(42), w("spam")) self.assertEquals(repr(r), "('add_string_string', '!42', 'spam')") From arigo at codespeak.net Mon Jun 30 16:44:44 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 30 Jun 2003 16:44:44 +0200 (MEST) Subject: [pypy-svn] rev 1068 - pypy/trunk/src/pypy/objspace/std/test Message-ID: <20030630144444.0B1815BBA2@thoth.codespeak.net> Author: arigo Date: Mon Jun 30 16:44:43 2003 New Revision: 1068 Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Log: Re-enabled the tests accidentally removed in test_stringobject.py. Modified: pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py Mon Jun 30 16:44:43 2003 @@ -13,7 +13,7 @@ def tearDown(self): pass - def qqqtest_order_rich(self): + def test_order_rich(self): space = self.space def w(txt): return W_StringObject(space, txt) @@ -40,12 +40,12 @@ w(str2), pypyconst)) - def qqqtest_equality(self): + def test_equality(self): w = self.space.wrap self.assertEqual_w(w('abc'), w('abc')) self.assertNotEqual_w(w('abc'), w('def')) - def qqqtest_order_cmp(self): + def test_order_cmp(self): space = self.space w = space.wrap self.failUnless_w(space.lt(w('a'), w('b'))) @@ -53,12 +53,12 @@ self.failUnless_w(space.le(w('a'), w('a'))) self.failUnless_w(space.gt(w('a'), w(''))) - def qqqtest_truth(self): + def test_truth(self): w = self.space.wrap self.failUnless_w(w('non-empty')) self.failIf_w(w('')) - def qqqtest_getitem(self): + def test_getitem(self): space = self.space w = space.wrap w_str = w('abc') @@ -69,7 +69,7 @@ w_str, w(3)) - def qqqtest_slice(self): + def test_slice(self): space = self.space w = space.wrap w_str = w('abc') @@ -92,7 +92,7 @@ w_slice = space.newslice(w(-1), space.w_None, None) self.assertEqual_w(space.getitem(w_str, w_slice), w('c')) - def qqqtest_extended_slice(self): + def test_extended_slice(self): space = self.space if self.space.__class__.__name__.startswith('Trivial'): import sys @@ -116,7 +116,7 @@ #AttributeError: W_StringObject instance has no attribute 'ljust' -# def qqqtest_ljust(self): +# def test_ljust(self): # w = self.space.wrap # s = "abc" # @@ -129,7 +129,7 @@ def setUp(self): self.space = test.objspace('std') - def qqqtest_split(self): + def test_split(self): self.assertEquals("".split(), []) self.assertEquals("a".split(), ['a']) self.assertEquals(" a ".split(), ['a']) @@ -148,13 +148,13 @@ self.assertEquals('endcase test'.split('test'), ['endcase ', '']) - def qqqtest_split_splitchar(self): + def test_split_splitchar(self): self.assertEquals("/a/b/c".split('/'), ['','a','b','c']) - def qqqtest_title(self): + def test_title(self): self.assertEquals("brown fox".title(), "Brown Fox") - def qqqtest_capitalize(self): + def test_capitalize(self): self.assertEquals("brown fox".capitalize(), "Brown fox") self.assertEquals(' hello '.capitalize(), ' hello ') self.assertEquals('Hello '.capitalize(), 'Hello ') @@ -162,7 +162,7 @@ self.assertEquals('aaaa'.capitalize(), 'Aaaa') self.assertEquals('AaAa'.capitalize(), 'Aaaa') - def qqqtest_rjust(self): + def test_rjust(self): s = "abc" self.assertEquals(s.rjust(2), s) self.assertEquals(s.rjust(3), s) @@ -174,7 +174,7 @@ self.assertEquals('abc'.rjust(2), 'abc') - def qqqtest_ljust(self): + def test_ljust(self): s = "abc" self.assertEquals(s.ljust(2), s) self.assertEquals(s.ljust(3), s) @@ -185,7 +185,7 @@ self.assertEquals('abc'.ljust(3), 'abc') self.assertEquals('abc'.ljust(2), 'abc') - def qqqtest_replace(self): + def test_replace(self): self.assertEquals('one!two!three!'.replace('!', '@', 1), 'one at two!three!') self.assertEquals('one!two!three!'.replace('!', ''), 'onetwothree') self.assertEquals('one!two!three!'.replace('!', '@', 2), 'one at two@three!') @@ -206,7 +206,7 @@ self.assertEquals('123x123'.replace('123', ''), 'x') - def qqqtest_strip(self): + def test_strip(self): s = " a b " self.assertEquals(s.strip(), "a b") self.assertEquals(s.rstrip(), " a b") @@ -215,7 +215,7 @@ self.assertEquals('xyzzyhelloxyzzy'.lstrip('xyz'), 'helloxyzzy') self.assertEquals('xyzzyhelloxyzzy'.rstrip('xyz'), 'xyzzyhello') - def qqqtest_zfill(self): + def test_zfill(self): self.assertEquals('123'.zfill(2), '123') self.assertEquals('123'.zfill(3), '123') self.assertEquals('123'.zfill(4), '0123') @@ -229,7 +229,7 @@ self.assertEquals('34'.zfill(1), '34') self.assertEquals('34'.zfill(4), '0034') - def qqqtest_center(self): + def test_center(self): s="a b" self.assertEquals(s.center(0), "a b") self.assertEquals(s.center(1), "a b") @@ -247,7 +247,7 @@ self.assertEquals('abc'.center(2), 'abc') - def qqqtest_count(self): + def test_count(self): self.assertEquals("".count("x"),0) self.assertEquals("".count(""),1) self.assertEquals("Python".count(""),7) @@ -260,7 +260,7 @@ self.assertEquals('aaa'.count('a', 0, -10), 0) - def qqqtest_startswith(self): + def test_startswith(self): self.assertEquals('ab'.startswith('ab'),1) self.assertEquals('ab'.startswith('a'),1) self.assertEquals('ab'.startswith(''),1) @@ -272,7 +272,7 @@ self.assertEquals('y'.startswith('xx'),0) - def qqqtest_endswith(self): + def test_endswith(self): self.assertEquals('ab'.endswith('ab'),1) self.assertEquals('ab'.endswith('b'),1) self.assertEquals('ab'.endswith(''),1) @@ -283,7 +283,7 @@ self.assertEquals('x'.endswith('xx'),0) self.assertEquals('y'.endswith('xx'),0) - def qqqtest_expandtabs(self): + def test_expandtabs(self): self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(), 'abc\rab def\ng hi') self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(8), 'abc\rab def\ng hi') self.assertEquals('abc\rab\tdef\ng\thi'.expandtabs(4), 'abc\rab def\ng hi') @@ -305,7 +305,7 @@ self.assertEquals(''.expandtabs(),'') - def qqqtest_splitlines(self): + def test_splitlines(self): s="ab\nab\n \n x\n\n\n" self.assertEquals(s.splitlines(),['ab', 'ab', ' ', ' x', '', '']) self.assertEquals(s.splitlines(),s.splitlines(0)) @@ -314,12 +314,12 @@ self.assertEquals(s.splitlines(),['', 'one', '\two', 'three', '']) self.assertEquals(s.splitlines(1),['\n', 'one\n', '\two\n', 'three\n', '\n']) - def qqqtest_find(self): + def test_find(self): self.assertEquals('abcdefghiabc'.find('abc'), 0) self.assertEquals('abcdefghiabc'.find('abc', 1), 9) self.assertEquals('abcdefghiabc'.find('def', 4), -1) - def qqqtest_index(self): + def test_index(self): self.assertEquals('abcdefghiabc'.index(''), 0) self.assertEquals('abcdefghiabc'.index('def'), 3) self.assertEquals('abcdefghiabc'.index('abc'), 0) @@ -330,13 +330,13 @@ #self.assertRaises(ValueError, 'abcdefghi'.index('ghi', 8)) #self.assertRaises(ValueError, 'abcdefghi'.index('ghi', -1)) - def qqqtest_rfind(self): + def test_rfind(self): self.assertEquals('abcdefghiabc'.rfind('abc'), 9) self.assertEquals('abcdefghiabc'.rfind(''), 12) self.assertEquals('abcdefghiabc'.rfind('abcd'), 0) self.assertEquals('abcdefghiabc'.rfind('abcz'), -1) - def qqqtest_rindex(self): + def test_rindex(self): self.assertEquals('abcdefghiabc'.rindex(''), 12) self.assertEquals('abcdefghiabc'.rindex('def'), 3) self.assertEquals('abcdefghiabc'.rindex('abc'), 9) @@ -349,7 +349,7 @@ #self.assertRaises(ValueError, 'abcdefghi'.rindex('ghi', 0, -1)) - def qqqtest_split_maxsplit(self): + def test_split_maxsplit(self): self.assertEquals("/a/b/c".split('/', 2), ['','a','b/c']) self.assertEquals("a/b/c".split("/"), ['a', 'b', 'c']) self.assertEquals(" a ".split(None, 0), ['a ']) @@ -357,24 +357,24 @@ self.assertEquals(" a a ".split(" ", 0), [' a a ']) self.assertEquals(" a a ".split(" ", 1), ['', 'a a ']) - def qqqtest_join(self): + def test_join(self): self.assertEquals(", ".join(['a', 'b', 'c']), "a, b, c") self.assertEquals("".join([]), "") self.assertEquals("-".join(['a', 'b']), 'a-b') - def qqqtest_lower(self): + def test_lower(self): self.assertEquals("aaa AAA".lower(), "aaa aaa") self.assertEquals("".lower(), "") - def qqqtest_upper(self): + def test_upper(self): self.assertEquals("aaa AAA".upper(), "AAA AAA") self.assertEquals("".upper(), "") - def qqqtest_swapcase(self): + def test_swapcase(self): self.assertEquals("aaa AAA 111".swapcase(), "AAA aaa 111") self.assertEquals("".swapcase(), "") - def qqqtest_iter(self): + def test_iter(self): l=[] for i in iter("42"): l.append(i) From arigo at codespeak.net Mon Jun 30 16:45:18 2003 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 30 Jun 2003 16:45:18 +0200 (MEST) Subject: [pypy-svn] rev 1069 - pypy/trunk/src/pypy/objspace/std Message-ID: <20030630144518.DBC795BBA2@thoth.codespeak.net> Author: arigo Date: Mon Jun 30 16:45:18 2003 New Revision: 1069 Modified: pypy/trunk/src/pypy/objspace/std/default.py pypy/trunk/src/pypy/objspace/std/register_all.py Log: Completed the automatic definition of missing comparison operators. Re-enabled them (I cannot see the problem mentioned by Holger?). Removed the default fall-backs in default.py. The purpose of this fix is to make the special methods visible at the application level (e.g. 'None.__ne__'). Modified: pypy/trunk/src/pypy/objspace/std/default.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/default.py (original) +++ pypy/trunk/src/pypy/objspace/std/default.py Mon Jun 30 16:45:18 2003 @@ -13,16 +13,16 @@ def eq__ANY_ANY(space, w_a, w_b): return space.is_(w_a, w_b) -# 'ne' -> 'eq', 'le/gt/ge' -> 'lt' - -def ne__ANY_ANY(space, w_a, w_b): - return space.not_(space.eq(w_a, w_b)) -def le__ANY_ANY(space, w_a, w_b): - return space.not_(space.lt(w_b, w_a)) -def gt__ANY_ANY(space, w_a, w_b): - return space.lt(w_b, w_a) -def ge__ANY_ANY(space, w_a, w_b): - return space.not_(space.lt(w_a, w_b)) +### 'ne' -> 'eq', 'le/gt/ge' -> 'lt' +## +##def ne__ANY_ANY(space, w_a, w_b): +## return space.not_(space.eq(w_a, w_b)) +##def le__ANY_ANY(space, w_a, w_b): +## return space.not_(space.lt(w_b, w_a)) +##def gt__ANY_ANY(space, w_a, w_b): +## return space.lt(w_b, w_a) +##def ge__ANY_ANY(space, w_a, w_b): +## return space.not_(space.lt(w_a, w_b)) # 'id' falls back to the address of the wrapper Modified: pypy/trunk/src/pypy/objspace/std/register_all.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/register_all.py (original) +++ pypy/trunk/src/pypy/objspace/std/register_all.py Mon Jun 30 16:45:18 2003 @@ -67,49 +67,61 @@ raise NameError, ("trying hard but not finding a multimethod named %s" % funcname) -class Curry: - def __init__(self, fun, arg): - self.fun = fun - self.pending = (arg,) - def __call__(self, *args): - return self.fun(*(self.pending + args)) - -def inverted_comparison(function, space, w_1, w_2): - return space.not_(function(space, w_1, w_2)) +def op_negated(function): + def op(space, w_1, w_2, function=function): + return space.not_(function(space, w_1, w_2)) + return op + +def op_swapped(function): + def op(space, w_1, w_2, function=function): + return function(space, w_2, w_1) + return op + +def op_swapped_negated(function): + def op(space, w_1, w_2, function=function): + return space.not_(function(space, w_2, w_1)) + return op + +OPERATORS = ['lt', 'le', 'eq', 'ne', 'gt', 'ge'] +OP_CORRESPONDANCES = [ + ('eq', 'ne', op_negated), + ('lt', 'gt', op_swapped), + ('le', 'ge', op_swapped), + ('lt', 'ge', op_negated), + ('le', 'gt', op_negated), + ('lt', 'le', op_swapped_negated), + ('gt', 'ge', op_swapped_negated), + ] +for op1, op2, value in OP_CORRESPONDANCES[:]: + i = OP_CORRESPONDANCES.index((op1, op2, value)) + OP_CORRESPONDANCES.insert(i+1, (op2, op1, value)) def add_extra_comparisons(): """ - If the module has defined eq, lt or gt, - check if it already has ne, ge and le respectively. - If not, then add them as space.not_ on the implemented methods. + Add the missing comparison operators if they were not explicitely + defined: eq <-> ne and lt <-> le <-> gt <-> ge. + We try to add them in the order defined by the OP_CORRESPONDANCES + table, thus favouring swapping the arguments over negating the result. """ - return - #XXX disabled because it doesn't work correctly probably - # because it iterates over partially initialized method tables - # we also had discussions on the LLN sprint to implement - # a < b with b > a and so on. I wonder whether the automatic - # creation of boolean operators is really worth it. instead - # we could just implement the operators in their appropriate - # files - operators=(('eq', 'ne'), ('lt', 'ge'), ('gt', 'le')) - from pypy.objspace.std.objspace import StdObjSpace, W_ANY - - for method, mirror in operators: - try: - multifunc = StdObjSpace.__dict__[method] - mirrorfunc = StdObjSpace.__dict__[mirror] - for types, functions in multifunc.dispatch_table.iteritems(): - t1, t2 = types - if t1 is t2: - if not mirrorfunc.dispatch_table.has_key(types): - assert len(functions) == 1, 'Automatic' - 'registration of comparison functions' - ' only work when there is a single method for' - ' the operation.' - mirrorfunc.register( - Curry(inverted_comparison, functions[0]), - *[t1, t1]) - except AttributeError: - print '%s not found in StdObjSpace' % method + originaltable = {} + for op in OPERATORS: + originaltable[op] = getattr(StdObjSpace, op).dispatch_table.copy() + + for op1, op2, correspondance in OP_CORRESPONDANCES: + mirrorfunc = getattr(StdObjSpace, op2) + for types, functions in originaltable[op1].iteritems(): + t1, t2 = types + if t1 is t2: + if types not in mirrorfunc.dispatch_table: + assert len(functions) == 1, ('Automatic' + ' registration of comparison functions' + ' only work when there is a single method for' + ' the operation.') + #print 'adding %s <<<%s>>> %s as %s(%s)' % ( + # t1, op2, t2, + # correspondance.func_name, functions[0].func_name) + mirrorfunc.register( + correspondance(functions[0]), + *types) From gvanrossum at codespeak.net Mon Jun 30 16:51:20 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 30 Jun 2003 16:51:20 +0200 (MEST) Subject: [pypy-svn] rev 1070 - pypy/trunk/src/pypy/interpreter Message-ID: <20030630145120.8711A5BBA2@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 30 16:51:20 2003 New Revision: 1070 Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py Log: Add a hook, gethelperspace(), which should return the space to be passed to AppHelper. It defaults to self. Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Mon Jun 30 16:51:20 2003 @@ -62,10 +62,16 @@ helper = self.appfile_helpers[applicationfile] except KeyError: from appfile import AppHelper - helper = AppHelper(self, applicationfile) + helper = AppHelper(self.gethelperspace(), applicationfile) self.appfile_helpers[applicationfile] = helper return helper + def gethelperspace(self): + # Return the object space to be used for executing helper code. + # A subclass may override this if it wants to use a different + # space to execute helpers (e.g. the annotating space) + return self + # Following is a friendly interface to common object space operations # that can be defined in term of more primitive ones. Subclasses # may also override specific functions for performance. From gvanrossum at codespeak.net Mon Jun 30 16:55:08 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 30 Jun 2003 16:55:08 +0200 (MEST) Subject: [pypy-svn] rev 1071 - pypy/trunk/src/pypy/module Message-ID: <20030630145508.05D195BBA2@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 30 16:55:08 2003 New Revision: 1071 Modified: pypy/trunk/src/pypy/module/builtin.py Log: Add TypeError and type to the Builtin class, hoping to get some more Ann space code to work (these are used by some appspace helpers called from the interpreter). Modified: pypy/trunk/src/pypy/module/builtin.py ============================================================================== --- pypy/trunk/src/pypy/module/builtin.py (original) +++ pypy/trunk/src/pypy/module/builtin.py Mon Jun 30 16:55:08 2003 @@ -179,6 +179,9 @@ # we have None! But leave these at the bottom, otherwise the default # arguments of the above-defined functions will see this new None... None = appdata(_b.None) + # XXX Add these for Ann space. + TypeError = appdata(_b.TypeError) + type = appdata(_b.type) ## False = appdata(_b.False) ## True = appdata(_b.True) ## dict = appdata(_b.dict) # XXX temporary From gvanrossum at codespeak.net Mon Jun 30 17:08:28 2003 From: gvanrossum at codespeak.net (gvanrossum at codespeak.net) Date: Mon, 30 Jun 2003 17:08:28 +0200 (MEST) Subject: [pypy-svn] rev 1072 - in pypy/trunk/src/pypy: interpreter objspace/annobjspace/ann/test Message-ID: <20030630150828.617F65BBA2@thoth.codespeak.net> Author: gvanrossum Date: Mon Jun 30 17:08:27 2003 New Revision: 1072 Modified: pypy/trunk/src/pypy/interpreter/pyframe.py pypy/trunk/src/pypy/objspace/ann/cloningcontext.py pypy/trunk/src/pypy/objspace/ann/objspace.py pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py pypy/trunk/src/pypy/objspace/ann/wrapper.py Log: Final redux from EuroPython hacking sessions. The code is mostly better, but still, many tests hang when run with -A, and there's at least one (in test_interpreter.py) that causes an infinite loop. M interpreter/pyframe.py Move the clone() method and the clonecells() function to objspace/cloningcontext.py. Commented out extracting __builtins__; it seems not needed and confused the Ann space. M objspace/ann/test/test_objspace.py Add another test; disable one that no longer works. M objspace/ann/cloningcontext.py Many changes; moved cloning here from pyframe.py. App helpers called from the interpreter are now run in a special subclass of CloningExecutionContext, which doesn't unify frames (because we need the real results from these helpers). M objspace/ann/wrapper.py Add constant iterators; add some APIs; other misc changes. M objspace/ann/objspace.py Change the wrapper cache to contain the key objects too; before, wrap(1) would return self.w_True. Get rid of unused clone_locals() method. Add gethelperspace() to return a HelperObjSpace() instance. Implement some more operations correctly on constants, for the appspace helpers. All operations now catch exceptions and call self.reraise() when appropriate. Slight optimizations in generic_operator(). Modified: pypy/trunk/src/pypy/interpreter/pyframe.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyframe.py (original) +++ pypy/trunk/src/pypy/interpreter/pyframe.py Mon Jun 30 17:08:27 2003 @@ -32,17 +32,6 @@ self.last_exception = None self.next_instr = 0 - def clone(self): - # XXX assume locals and globals are constant - f = PyFrame(self.space, self.bytecode, self.w_globals, self.w_locals) - f.valuestack = self.valuestack.clone() - f.blockstack = self.blockstack.clone() - f.last_exception = self.last_exception - f.next_instr = self.next_instr - f.localcells = clonecells(self.localcells) - f.nestedcells = clonecells(self.nestedcells) - return f - def eval(self, executioncontext): "Interpreter main loop!" from pypy.interpreter import opcode @@ -154,10 +143,12 @@ # object. Here we will just try to read its __dict__ attribute and # if it fails we assume that it was a dictionary in the first place. w_attrname = self.space.wrap("__dict__") - try: - w_builtins = self.space.getattr(w_builtins, w_attrname) - except OperationError: - pass # catch and ignore any error + # XXX Commented out the following; it doesn't work for Ann space, + # and doesn't seem to be needed for other spaces AFAICT. +## try: +## w_builtins = self.space.getattr(w_builtins, w_attrname) +## except OperationError: +## pass # XXX catch and ignore any error return w_builtins ### exception stack ### @@ -377,15 +368,3 @@ else: return "%s(%s)" % (self.__class__.__name__, self.w_value) -def clonecells(cells): - """Clone a list of cells.""" - newcells = [] - for cell in cells: - try: - value = cell.get() - except ValueError: - newcell = Cell() - else: - newcell = Cell(value) - newcells.append(newcell) - return newcells Modified: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (original) +++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Mon Jun 30 17:08:27 2003 @@ -1,12 +1,14 @@ from pypy.interpreter.executioncontext import ExecutionContext -from pypy.interpreter.pyframe import ControlFlowException, ExitFrame +from pypy.interpreter.pyframe \ + import ControlFlowException, ExitFrame, PyFrame, Cell from pypy.objspace.ann.wrapper \ import union, compatible_frames, unify_frames, W_Anything, W_Constant, \ W_KnownKeysContainer class FunctionInfo(object): - def __init__(self): + def __init__(self, ec): + self.ec = ec self.result = None self.clones = [] # List of (next_instr, w_obj, force) tuples self.knownframes = {} # Mapping from next_instr to list of frames @@ -14,23 +16,26 @@ def addresult(self, result): self.result = union(self.result, result) - def addclone(self, next_instr, w_obj, force): - self.clones.append((next_instr, w_obj, force)) + def addclone(self, next_instr, stack_level, block_level, w_obj, force): + self.clones.append((next_instr, stack_level, block_level, w_obj, force)) - def getframe(self): + def getclone(self): if not self.clones: return None - next_instr, w_obj, force = self.clones.pop() + next_instr, stack_level, block_level, w_obj, force = self.clones.pop() frames = self.knownframes[next_instr] - assert len(frames) == 1 - f = frames[0].clone() - f.restarting = (w_obj, force) - return f + for f in frames: + assert f.next_instr == next_instr + if (f.valuestack.depth() == stack_level and + f.blockstack.depth() == block_level): + f = self.ec.clone_frame(f) + f.restarting = (w_obj, force) + return f + assert False, "no suitable clone found -- impossible" def addknown(self, frame): frames = self.knownframes.setdefault(frame.next_instr, []) frames.append(frame) - assert len(frames) <= 1 # We think this is true def iterknown(self, frame): return iter(self.knownframes.get(frame.next_instr, [])) @@ -46,8 +51,16 @@ def action(self, frame, last_instr, context): info = context.getfunctioninfo(frame) - info.addclone(last_instr, self.w_obj, True) - info.addclone(last_instr, self.w_obj, False) + info.addclone(last_instr, + frame.valuestack.depth(), + frame.blockstack.depth(), + self.w_obj, + True) + info.addclone(last_instr, + frame.valuestack.depth(), + frame.blockstack.depth(), + self.w_obj, + False) # Abandon this frame; the two clones will take over raise ExitFrame(None) @@ -64,7 +77,7 @@ if info is None: if not new: raise KeyError, repr(key) - self.functioninfos[key] = info = FunctionInfo() + self.functioninfos[key] = info = FunctionInfo(self) return info def makekey(self, frame): @@ -88,7 +101,7 @@ # A fixpoint; abandon this frame raise ExitFrame(None) return - info.addknown(frame.clone()) + info.addknown(self.clone_frame(frame)) def eval_frame(self, frame): assert self.space is frame.space @@ -97,5 +110,46 @@ while frame is not None: result = ExecutionContext.eval_frame(self, frame) info.addresult(result) - frame = info.getframe() - return info.getresult() + frame = info.getclone() + w_result = info.getresult() + if w_result is None: + raise TypeError("no result at all?!?!") + return w_result + + def clone_frame(self, frame): + f = PyFrame(self.space, frame.bytecode, frame.w_globals, frame.w_locals) + f.valuestack = frame.valuestack.clone() + f.blockstack = frame.blockstack.clone() + f.last_exception = frame.last_exception + f.next_instr = frame.next_instr + f.localcells = clonecells(frame.localcells) + f.nestedcells = clonecells(frame.nestedcells) + return f + +class HelperExecutionContext(CloningExecutionContext): + + def eval_frame(self, frame): + frame.key = object() + result = CloningExecutionContext.eval_frame(self, frame) + return result + + def makekey(self, frame): + return frame.key + + def clone_frame(self, frame): + f = CloningExecutionContext.clone_frame(self, frame) + f.key = frame.key + return f + +def clonecells(cells): + """Clone a list of cells.""" + newcells = [] + for cell in cells: + try: + value = cell.get() + except ValueError: + newcell = Cell() + else: + newcell = Cell(value) + newcells.append(newcell) + return newcells Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/objspace.py Mon Jun 30 17:08:27 2003 @@ -7,6 +7,7 @@ from pypy.interpreter.pycode import PyByteCode from pypy.interpreter.extmodule import PyBuiltinCode from pypy.objspace.ann.cloningcontext import CloningExecutionContext +from pypy.objspace.ann.cloningcontext import HelperExecutionContext from pypy.objspace.ann.cloningcontext import IndeterminateCondition from pypy.objspace.ann.wrapper import * @@ -40,14 +41,19 @@ # Service methods whose interface is in the abstract base class def wrapboot(self, obj): + # Wrapper around wrap() to initialize the wrappercache w_obj = self.wrap(obj) - self.wrappercache[obj] = w_obj + self.wrappercache[obj] = (obj, w_obj) return w_obj def wrap(self, obj): + if isinstance(obj, W_Object): + raise TypeError("already wrapped: " + repr(obj)) try: if obj in self.wrappercache: - return self.wrappercache[obj] + key, w_obj = self.wrappercache[obj] + if obj is key: + return w_obj except (TypeError, AttributeError): # This can happen when obj is not hashable, for instance # XXX What about other errors??? @@ -77,17 +83,15 @@ pass else: return bool(obj) - # It's indeterminate!!! Aargh!!! + # It's indeterminate!!! # Raise an exception that will clone the interpreter. raise IndeterminateCondition(w_obj) def createexecutioncontext(self): return CloningExecutionContext(self) - def clone_locals(self, w_locals): - assert isinstance(w_locals, (W_KnownKeysContainer, W_Constant)) - return w_locals.clone() - + def gethelperspace(self): + return HelperObjSpace() # Specialized creators whose interface is in the abstract base class @@ -109,7 +113,7 @@ d[key] = value else: # All keys and values were unwrappable - return W_Constant(d) + return self.wrap(d) # It's not quite constant. # Maybe the keys are constant? values_w = {} @@ -143,7 +147,7 @@ except UnwrapException: return W_Anything() else: - return W_Constant(unwrappedlist) + return self.wrap(unwrappedlist) def newstring(self, listofwrappedints): unwrappedints = [] @@ -155,10 +159,11 @@ return W_Anything() else: try: - s = "".join(map(chr, unwrappedints)) + result = "".join(map(chr, unwrappedints)) except: self.reraise() - return W_Constant(s) + else: + return self.wrap(result) def newslice(self, w_start, w_stop, w_end=None): try: @@ -184,7 +189,12 @@ def str(self, w_left): if isinstance(w_left, W_Constant): - return self.wrap(str(w_left.value)) + try: + result = str(w_left.value) + except: + self.reraise() + else: + return self.wrap(result) else: return W_Anything() @@ -192,7 +202,7 @@ if w_left is w_right: return self.w_True if isinstance(w_left, W_Constant) and isinstance(w_right, W_Constant): - # XXX Is this really safe? + # XXX Is this really correct? if w_left.value is w_right.value: return self.w_True else: @@ -207,10 +217,11 @@ pass else: try: - sum = left + right + result = left + right except: self.reraise() - return self.wrap(sum) + else: + return self.wrap(result) if is_int(w_left) and is_int(w_right): return W_Integer() else: @@ -223,7 +234,12 @@ except UnwrapException: pass else: - return self.wrap(left - right) + try: + result = left - right + except: + self.reraise() + else: + return self.wrap(result) if is_int(w_left) and is_int(w_right): return W_Integer() else: @@ -236,15 +252,26 @@ except UnwrapException: pass else: - return self.wrap(left * right) + try: + result = left * right + except: + self.reraise() + else: + return self.wrap(result) if is_int(w_left) and is_int(w_right): return W_Integer() else: return W_Anything() def iter(self, w_iterable): + # XXX Should return an actual iterable, so that + # (1) if a true constant, a loop using next() will work correctly + # (e.g. unpackiterable()) + # (2) otherwise, we can at least unify the result types for next() if isinstance(w_iterable, W_Constant): value = w_iterable.value + if isinstance(value, list): + return W_ConstantIterator(value) try: it = iter(value) except: @@ -259,9 +286,17 @@ return W_Anything() else: raise NoValue + if isinstance(w_iterator, W_ConstantIterator): + try: + value = w_iterator.next() + except StopIteration: + raise NoValue + else: + return self.wrap(value) raise IndeterminateCondition(w_iterator) def call(self, w_func, w_args, w_kwds): + # XXX Need to move this (or most of it) into the W_*Function classes w_closure = None if isinstance(w_func, W_BuiltinFunction): bytecode = w_func.code @@ -280,7 +315,20 @@ try: code = func.func_code except AttributeError: - return W_Anything() + # Hmmm... A built-in funtion? Call it if constant args. + try: + args = self.unwrap(w_args) + kwds = self.unwrap(w_kwds) + except UnwrapException: + return W_Anything() + else: + try: + result = func(*args, **kwds) + except: + self.reraise() + else: + w_result = self.wrap(result) + return w_result bytecode = self.bytecodecache.get(code) if bytecode is None: bytecode = PyByteCode() @@ -310,23 +358,37 @@ return W_Anything() else: try: - return self.wrap(getattr(obj, name)) + result = getattr(obj, name) except: return self.reraise() + else: + return self.wrap(result) def setattr(self, w_obj, w_name, w_value): if isinstance(w_obj, W_Module) and isinstance(w_name, W_Constant): name = self.unwrap(w_name) w_obj.setattr(name, w_value) + return # Space setattr shouldn't return anything, so no w_None here def setitem(self, w_obj, w_key, w_value): - if (isinstance(w_obj, W_KnownKeysContainer) and - isinstance(w_key, W_Constant)): + if isinstance(w_key, W_Constant): key = self.unwrap(w_key) - w_obj.args_w[key] = w_value - return - # XXX How to record the side effect? + if isinstance(w_obj, W_KnownKeysContainer): + try: + w_obj[key] = w_value + except: + self.reraise() + return + elif (isinstance(w_obj, W_Constant) and + isinstance(w_value, W_Constant)): + try: + w_obj[key] = self.unwrap(w_value) + except: + self.reraise() + return + # XXX What if isinstance(w_obj, W_Constant) ??? + # XXX Otherwise, how to record the side effect? def len(self, w_obj): if isinstance(w_obj, W_KnownKeysContainer): @@ -336,7 +398,12 @@ except UnwrapException: return W_Anything() else: - return self.wrap(len(obj)) + try: + result = len(obj) + except: + self.reraise() + else: + return self.wrap(result) def getitem(self, w_obj, w_key): try: @@ -354,29 +421,53 @@ else: return W_Anything() try: - return self.wrap(obj[key]) + result = obj[key] except: self.reraise() + else: + return self.wrap(result) -def make_op(name, symbol, arity, specialnames): +class HelperObjSpace(AnnotationObjSpace): - if not hasattr(operator, name): - return # Can't do it + def __init__(self): + self.ec = None + AnnotationObjSpace.__init__(self) + + def getexecutioncontext(self): + if self.ec is None: + self.ec = self.createexecutioncontext() + return self.ec + + def createexecutioncontext(self): + return HelperExecutionContext(self) + +def make_op(name, symbol, arity, specialnames): if hasattr(AnnotationObjSpace, name): return # Shouldn't do it - def generic_operator(space, *args_w): - assert len(args_w) == arity, "got a wrong number of arguments" + op = getattr(operator, name, None) + if not op: + return # Can't do it + + def generic_operator(self, *args_w): + assert len(args_w) == arity, name+" got the wrong number of arguments" + args = [] for w_arg in args_w: - if not isinstance(w_arg, W_Constant): + try: + arg = self.unwrap(w_arg) + except UnwrapException: break + else: + args.append(arg) else: - # all arguments are constants, call the operator now - op = getattr(operator, name) - args = [space.unwrap(w_arg) for w_arg in args_w] - result = op(*args) - return space.wrap(result) + # All arguments are constants: call the operator now + try: + result = op(*args) + except: + self.reraise() + else: + return self.wrap(result) return W_Anything() @@ -384,3 +475,5 @@ for line in ObjSpace.MethodTable: make_op(*line) + +call_level = 0 Modified: pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/objspace/ann/test/test_objspace.py Mon Jun 30 17:08:27 2003 @@ -111,7 +111,8 @@ 'f', []) self.assertEquals(self.space.unwrap(x), 3) - def test_assign_local_w_flow_control(self): + def dont_test_assign_local_w_flow_control(self): + # XXX This test doesn't work any more -- disabled for now code = """ def f(n): total = 0 @@ -120,7 +121,29 @@ return n """ x = self.codetest(code, 'f', [self.space.wrap(3)]) - self.assertEquals(self.space.unwrap(x), 3) + self.assertEquals(type(x), W_Integer) + + def test_build_class(self): + code = """ +def f(name, bases, namespace, globals={}): + if len(bases) > 0: + base = bases[0] + if hasattr(base, '__class__'): + metaclass = base.__class__ + else: + metaclass = type(base) + else: + metaclass = type + + return metaclass(name, bases, namespace) +""" + x = self.codetest(code, 'f', + [self.space.wrap("MyClass"), + self.space.wrap(()), + self.space.wrap({}), + ]) + print x + self.assertEquals(isinstance(x, W_Anything), False) def dont_test_global(self): # XXX This will never work, because we don't handle mutating globals Modified: pypy/trunk/src/pypy/objspace/ann/wrapper.py ============================================================================== --- pypy/trunk/src/pypy/objspace/ann/wrapper.py (original) +++ pypy/trunk/src/pypy/objspace/ann/wrapper.py Mon Jun 30 17:08:27 2003 @@ -8,6 +8,8 @@ """ +import copy + class W_Object(object): """Abstract base class. do not instantiate.""" @@ -67,13 +69,24 @@ def __eq__(self, other): return type(other) is type(self) and self.value == other.value + def __len__(self): + return len(self.value) + + def __getitem__(self, key): + return self.value[key] + + def __setitem__(self, key, value): + self.value[key] = value + def clone(self): - return self + return W_Constant(copy.deepcopy(self.value)) class W_KnownKeysContainer(W_Object): """A dict with a known set of keys or a list with known length. XXX This is mutable! Is that a good idea? + + XXX Should unify some of this with W_Constant. """ def __init__(self, args_w): @@ -100,16 +113,38 @@ def __len__(self): return len(self.args_w) - def __getitem__(self, i): - return self.args_w[i] + def __getitem__(self, key): + return self.args_w[key] + + def __setitem__(self, key, w_value): + self.args_w[key] = w_value def clone(self): args_w = self.args_w if isinstance(args_w, dict): args_w = args_w.copy() - # XXX Recurse down the values? return W_KnownKeysContainer(args_w) +class W_ConstantIterator(W_Object): + + def __init__(self, seq, start=0): + self.seq = seq + self.start = start + + def argsrepr(self): + return "%r, %r" % (self.seq, self.start) + + def clone(self): + return W_ConstantIterator(self.seq, self.start) + + def next(self): + try: + value = self.seq[self.start] + except IndexError: + raise StopIteration + self.start += 1 + return value + class W_Module(W_Object): """A module object. It supports getattr and setattr (yikes!).""" @@ -117,8 +152,8 @@ # The wrapped module name and wrapped docstring must be known self.w_name = w_name self.w_doc = w_doc - self.contents = W_KnownKeysContainer({"__name__": w_name, - "__doc__": w_doc}) + self.w_dict = W_KnownKeysContainer({"__name__": w_name, + "__doc__": w_doc}) def argsrepr(self): return repr(self.w_name) + ", " + repr(self.w_doc) @@ -126,11 +161,11 @@ def getattr(self, name): # Returned a wrapped object or raise an unwrapped KeyError exception if name == "__dict__": - return self.contents - return self.contents[name] + return self.w_dict + return self.w_dict[name] def setattr(self, name, w_obj): - self.contents.args_w[name] = w_obj + self.w_dict.args_w[name] = w_obj class W_BuiltinFunction(W_Object): """A function that executes in interpreter space.""" From hpk at codespeak.net Mon Jun 30 17:41:08 2003 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 30 Jun 2003 17:41:08 +0200 (MEST) Subject: [pypy-svn] rev 1073 - in pypy/trunk/src/pypy: interpreter/test objspace/std tool Message-ID: <20030630154108.BA5935BBA2@thoth.codespeak.net> Author: hpk Date: Mon Jun 30 17:41:07 2003 New Revision: 1073 Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py pypy/trunk/src/pypy/objspace/std/register_all.py (props changed) pypy/trunk/src/pypy/objspace/std/stringobject.py pypy/trunk/src/pypy/tool/test.py Log: - improved the hack to perform specific objspace tests only when actually running the tests with the respective objspace. (i.e. objspace.ann* tests are skipped for StdObjSpace and objspace.std* for AnnObjSpace) - removed some cruft from tests M interpreter/test/test_interpreter.py "test_print" now redirects sys.stdout to some class to check if "print 42" works correctly M objspace/std/stringobject.py removed print junk _M objspace/std/register_all.py fixeol M tool/test.py improved hack to skip tests when running wrong objspace tests. Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Mon Jun 30 17:41:07 2003 @@ -194,21 +194,20 @@ self.assertEquals(f(), 2) def test_print(self): - #import sys - #save = sys.stdout - #class Out: - # def __init__(self): - # self.args = [] - # def write(self, *args): - # self.args.extend(args) - #out = Out() - #try: - # sys.stdout = out - # print 10 - # self.assertEquals(out.args, ['10','\n']) - #finally: - # sys.stdout = save - print 42 + import sys + save = sys.stdout + class Out: + def __init__(self): + self.args = [] + def write(self, *args): + self.args.extend(args) + out = Out() + try: + sys.stdout = out + print 10 + self.assertEquals(out.args, ['10','\n']) + finally: + sys.stdout = save def test_identity(self): def f(x): return x Modified: pypy/trunk/src/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/stringobject.py Mon Jun 30 17:41:07 2003 @@ -408,7 +408,6 @@ (self, sub, start, end) = _convert_idx_params(space, w_self, w_sub, w_start, w_end) res = _find(self, sub, start, end, 1) - print space.w_ValueError if res == -1: raise OperationError(space.w_ValueError, space.wrap("substring not found in string.index")) Modified: pypy/trunk/src/pypy/tool/test.py ============================================================================== --- pypy/trunk/src/pypy/tool/test.py (original) +++ pypy/trunk/src/pypy/tool/test.py Mon Jun 30 17:41:07 2003 @@ -22,11 +22,12 @@ return result fm = getattr(self, 'frommodule','') - if fm and fm.startswith('pypy.objspace.std') and \ - Options.spacename != 'std': - sys.stderr.write("\n%s skip for objspace %r" % ( - fm, Options.spacename)) - return result + for spacename in ('std','trivial','ann'): + if fm and fm.startswith('pypy.objspace.' + spacename) and \ + Options.spacename != spacename: + sys.stderr.write("\n%s skip for objspace %r" % ( + fm, Options.spacename)) + return result if fm and Options.verbose==0: sys.stderr.write('\n%s [%d]' %(fm, count)) From pedronis at codespeak.net Mon Jun 30 23:13:44 2003 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 30 Jun 2003 23:13:44 +0200 (MEST) Subject: [pypy-svn] rev 1074 - pypy/trunk/doc/sprintinfo Message-ID: <20030630211344.C40F15AF1A@thoth.codespeak.net> Author: pedronis Date: Mon Jun 30 23:13:43 2003 New Revision: 1074 Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt (contents, props changed) Log: some additions Modified: pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt (original) +++ pypy/trunk/doc/sprintinfo/LouvainLaNeuveReport.txt Mon Jun 30 23:13:43 2003 @@ -26,6 +26,14 @@ - implemented unbound methods and descriptors (Michael, Samuele) + - first cut at implementing the right __new__/__init__ semantics + (Armin, Samuele) + + - use intepreter-level Python class inheritance for structure + sharing for user subclasses of builtin types, switched to an + indipendent hierarchy for mm-dispatch purposes (dispatchclass attr) + (Samuele, design discussion with Armin) + - implemented the beginnings of the AnnotationObjectSpace (Armin, Guido, Michael) for abstract interpretation.