Index: build.Lib.include.properties =================================================================== --- build.Lib.include.properties (revision 2831) +++ build.Lib.include.properties (working copy) @@ -57,6 +57,7 @@ httplib.py imaplib.py imghdr.py +inspect.py keyword.py linecache.py macpath.py @@ -77,6 +78,7 @@ nturl2path.py pdb.py pickle.py +pickletools.py pipes.py poplib.py posixfile.py Index: Lib/inspect.py =================================================================== --- Lib/inspect.py (revision 2831) +++ Lib/inspect.py (working copy) @@ -1,23 +0,0 @@ -# -# Very simple version of inspect, just enough is supported for -# doctest to work. -# - -import org.python.core as _core - -def isclass(cls): - return isinstance(cls, _core.PyClass) - -def isfunction(func): - return isinstance(func, _core.PyFunction) - -def ismodule(mod): - return isinstance(mod, _core.PyModule) - -def ismethod(meth): - return isinstance(meth, _core.PyMethod) - -def classify_class_attrs(obj): - return [] - - Index: Lib/pickle.py =================================================================== --- Lib/pickle.py (revision 2831) +++ Lib/pickle.py (working copy) @@ -1,990 +0,0 @@ -"""Create portable serialized representations of Python objects. - -See module cPickle for a (much) faster implementation. -See module copy_reg for a mechanism for registering custom picklers. - -Classes: - - Pickler - Unpickler - -Functions: - - dump(object, file) - dumps(object) -> string - load(file) -> object - loads(string) -> object - -Misc variables: - - __version__ - format_version - compatible_formats - -""" - -__version__ = "$Revision: 1.56.4.4 $" # Code version - -from types import * -from copy_reg import dispatch_table, safe_constructors -import marshal -import sys -import struct -import re - -__all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler", - "Unpickler", "dump", "dumps", "load", "loads"] - -format_version = "1.3" # File format version we write -compatible_formats = ["1.0", "1.1", "1.2"] # Old format versions we can read - -mdumps = marshal.dumps -mloads = marshal.loads - -class PickleError(Exception): pass -class PicklingError(PickleError): pass -class UnpicklingError(PickleError): pass - -class _Stop(Exception): - def __init__(self, value): - self.value = value - -try: - from org.python.core import PyStringMap -except ImportError: - PyStringMap = None - -try: - UnicodeType -except NameError: - UnicodeType = None - - -MARK = '(' -STOP = '.' -POP = '0' -POP_MARK = '1' -DUP = '2' -FLOAT = 'F' -INT = 'I' -BININT = 'J' -BININT1 = 'K' -LONG = 'L' -BININT2 = 'M' -NONE = 'N' -PERSID = 'P' -BINPERSID = 'Q' -REDUCE = 'R' -STRING = 'S' -BINSTRING = 'T' -SHORT_BINSTRING = 'U' -UNICODE = 'V' -BINUNICODE = 'X' -APPEND = 'a' -BUILD = 'b' -GLOBAL = 'c' -DICT = 'd' -EMPTY_DICT = '}' -APPENDS = 'e' -GET = 'g' -BINGET = 'h' -INST = 'i' -LONG_BINGET = 'j' -LIST = 'l' -EMPTY_LIST = ']' -OBJ = 'o' -PUT = 'p' -BINPUT = 'q' -LONG_BINPUT = 'r' -SETITEM = 's' -TUPLE = 't' -EMPTY_TUPLE = ')' -SETITEMS = 'u' -BINFLOAT = 'G' - -__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)]) - -class Pickler: - - def __init__(self, file, bin = 0): - self.write = file.write - self.memo = {} - self.bin = bin - - def dump(self, object): - self.save(object) - self.write(STOP) - - def put(self, i): - if self.bin: - s = mdumps(i)[1:] - if i < 256: - return BINPUT + s[0] - - return LONG_BINPUT + s - - return PUT + `i` + '\n' - - def get(self, i): - if self.bin: - s = mdumps(i)[1:] - - if i < 256: - return BINGET + s[0] - - return LONG_BINGET + s - - return GET + `i` + '\n' - - def save(self, object, pers_save = 0): - memo = self.memo - - if not pers_save: - pid = self.persistent_id(object) - if pid is not None: - self.save_pers(pid) - return - - d = id(object) - - t = type(object) - - if (t is TupleType) and (len(object) == 0): - if self.bin: - self.save_empty_tuple(object) - else: - self.save_tuple(object) - return - - if memo.has_key(d): - self.write(self.get(memo[d][0])) - return - - try: - f = self.dispatch[t] - except KeyError: - pid = self.inst_persistent_id(object) - if pid is not None: - self.save_pers(pid) - return - - try: - # XXX: TypeType comparison broken in Jython so Kludging around this for now. - #issc = issubclass(t, TypeType) - issc = str(t) == "" - except TypeError: # t is not a class - issc = 0 - if issc: - self.save_global(object) - return - - try: - reduce = dispatch_table[t] - except KeyError: - try: - reduce = object.__reduce__ - except AttributeError: - raise PicklingError, \ - "can't pickle %s object: %s" % (`t.__name__`, - `object`) - else: - tup = reduce() - else: - tup = reduce(object) - - if type(tup) is StringType: - self.save_global(object, tup) - return - - if type(tup) is not TupleType: - raise PicklingError, "Value returned by %s must be a " \ - "tuple" % reduce - - l = len(tup) - - if (l != 2) and (l != 3): - raise PicklingError, "tuple returned by %s must contain " \ - "only two or three elements" % reduce - - callable = tup[0] - arg_tup = tup[1] - - if l > 2: - state = tup[2] - else: - state = None - - if type(arg_tup) is not TupleType and arg_tup is not None: - raise PicklingError, "Second element of tuple returned " \ - "by %s must be a tuple" % reduce - - self.save_reduce(callable, arg_tup, state) - memo_len = len(memo) - self.write(self.put(memo_len)) - memo[d] = (memo_len, object) - return - - f(self, object) - - def persistent_id(self, object): - return None - - def inst_persistent_id(self, object): - return None - - def save_pers(self, pid): - if not self.bin: - self.write(PERSID + str(pid) + '\n') - else: - self.save(pid, 1) - self.write(BINPERSID) - - def save_reduce(self, callable, arg_tup, state = None): - write = self.write - save = self.save - - save(callable) - save(arg_tup) - write(REDUCE) - - if state is not None: - save(state) - write(BUILD) - - dispatch = {} - - def save_none(self, object): - self.write(NONE) - dispatch[NoneType] = save_none - - def save_int(self, object): - if self.bin: - # If the int is small enough to fit in a signed 4-byte 2's-comp - # format, we can store it more efficiently than the general - # case. - high_bits = object >> 31 # note that Python shift sign-extends - if high_bits == 0 or high_bits == -1: - # All high bits are copies of bit 2**31, so the value - # fits in a 4-byte signed int. - i = mdumps(object)[1:] - assert len(i) == 4 - if i[-2:] == '\000\000': # fits in 2-byte unsigned int - if i[-3] == '\000': # fits in 1-byte unsigned int - self.write(BININT1 + i[0]) - else: - self.write(BININT2 + i[:2]) - else: - self.write(BININT + i) - return - # Text pickle, or int too big to fit in signed 4-byte format. - self.write(INT + `object` + '\n') - dispatch[IntType] = save_int - - def save_long(self, object): - self.write(LONG + `object` + '\n') - dispatch[LongType] = save_long - - def save_float(self, object, pack=struct.pack): - if self.bin: - self.write(BINFLOAT + pack('>d', object)) - else: - self.write(FLOAT + `object` + '\n') - dispatch[FloatType] = save_float - - def save_string(self, object): - d = id(object) - memo = self.memo - - if self.bin: - l = len(object) - s = mdumps(l)[1:] - if l < 256: - self.write(SHORT_BINSTRING + s[0] + object) - else: - self.write(BINSTRING + s + object) - else: - self.write(STRING + `object` + '\n') - - memo_len = len(memo) - self.write(self.put(memo_len)) - memo[d] = (memo_len, object) - dispatch[StringType] = save_string - - def save_unicode(self, object): - d = id(object) - memo = self.memo - - if self.bin: - encoding = object.encode('utf-8') - l = len(encoding) - s = mdumps(l)[1:] - self.write(BINUNICODE + s + encoding) - else: - object = object.replace("\\", "\\u005c") - object = object.replace("\n", "\\u000a") - self.write(UNICODE + object.encode('raw-unicode-escape') + '\n') - - memo_len = len(memo) - self.write(self.put(memo_len)) - memo[d] = (memo_len, object) - dispatch[UnicodeType] = save_unicode - - if StringType == UnicodeType: - # This is true for Jython - def save_string(self, object): - d = id(object) - memo = self.memo - unicode = object.isunicode() - - if self.bin: - if unicode: - object = object.encode("utf-8") - l = len(object) - s = mdumps(l)[1:] - if l < 256 and not unicode: - self.write(SHORT_BINSTRING + s[0] + object) - else: - if unicode: - self.write(BINUNICODE + s + object) - else: - self.write(BINSTRING + s + object) - else: - if unicode: - object = object.replace("\\", "\\u005c") - object = object.replace("\n", "\\u000a") - object = object.encode('raw-unicode-escape') - self.write(UNICODE + object + '\n') - else: - self.write(STRING + `object` + '\n') - - memo_len = len(memo) - self.write(self.put(memo_len)) - memo[d] = (memo_len, object) - dispatch[StringType] = save_string - - def save_tuple(self, object): - - write = self.write - save = self.save - memo = self.memo - - d = id(object) - - write(MARK) - - for element in object: - save(element) - - if len(object) and memo.has_key(d): - if self.bin: - write(POP_MARK + self.get(memo[d][0])) - return - - write(POP * (len(object) + 1) + self.get(memo[d][0])) - return - - memo_len = len(memo) - self.write(TUPLE + self.put(memo_len)) - memo[d] = (memo_len, object) - dispatch[TupleType] = save_tuple - - def save_empty_tuple(self, object): - self.write(EMPTY_TUPLE) - - def save_list(self, object): - d = id(object) - - write = self.write - save = self.save - memo = self.memo - - if self.bin: - write(EMPTY_LIST) - else: - write(MARK + LIST) - - memo_len = len(memo) - write(self.put(memo_len)) - memo[d] = (memo_len, object) - - using_appends = (self.bin and (len(object) > 1)) - - if using_appends: - write(MARK) - - for element in object: - save(element) - - if not using_appends: - write(APPEND) - - if using_appends: - write(APPENDS) - dispatch[ListType] = save_list - - def save_dict(self, object): - d = id(object) - - write = self.write - save = self.save - memo = self.memo - - if self.bin: - write(EMPTY_DICT) - else: - write(MARK + DICT) - - memo_len = len(memo) - self.write(self.put(memo_len)) - memo[d] = (memo_len, object) - - using_setitems = (self.bin and (len(object) > 1)) - - if using_setitems: - write(MARK) - - items = object.items() - for key, value in items: - save(key) - save(value) - - if not using_setitems: - write(SETITEM) - - if using_setitems: - write(SETITEMS) - - dispatch[DictionaryType] = save_dict - if not PyStringMap is None: - dispatch[PyStringMap] = save_dict - - def save_inst(self, object): - d = id(object) - cls = object.__class__ - - memo = self.memo - write = self.write - save = self.save - - if hasattr(object, '__getinitargs__'): - args = object.__getinitargs__() - len(args) # XXX Assert it's a sequence - _keep_alive(args, memo) - else: - args = () - - write(MARK) - - if self.bin: - save(cls) - - for arg in args: - save(arg) - - memo_len = len(memo) - if self.bin: - write(OBJ + self.put(memo_len)) - else: - write(INST + cls.__module__ + '\n' + cls.__name__ + '\n' + - self.put(memo_len)) - - memo[d] = (memo_len, object) - - try: - getstate = object.__getstate__ - except AttributeError: - stuff = object.__dict__ - else: - stuff = getstate() - _keep_alive(stuff, memo) - save(stuff) - write(BUILD) - dispatch[InstanceType] = save_inst - - def save_global(self, object, name = None): - write = self.write - memo = self.memo - - if name is None: - name = object.__name__ - - try: - module = object.__module__ - except AttributeError: - module = whichmodule(object, name) - - try: - __import__(module) - mod = sys.modules[module] - klass = getattr(mod, name) - except (ImportError, KeyError, AttributeError): - raise PicklingError( - "Can't pickle %r: it's not found as %s.%s" % - (object, module, name)) - else: - if klass is not object: - raise PicklingError( - "Can't pickle %r: it's not the same object as %s.%s" % - (object, module, name)) - - memo_len = len(memo) - write(GLOBAL + module + '\n' + name + '\n' + - self.put(memo_len)) - memo[id(object)] = (memo_len, object) - dispatch[ClassType] = save_global - dispatch[FunctionType] = save_global - dispatch[BuiltinFunctionType] = save_global - dispatch[TypeType] = save_global - - -def _keep_alive(x, memo): - """Keeps a reference to the object x in the memo. - - Because we remember objects by their id, we have - to assure that possibly temporary objects are kept - alive by referencing them. - We store a reference at the id of the memo, which should - normally not be used unless someone tries to deepcopy - the memo itself... - """ - try: - memo[id(memo)].append(x) - except KeyError: - # aha, this is the first one :-) - memo[id(memo)]=[x] - - -classmap = {} # called classmap for backwards compatibility - -def whichmodule(func, funcname): - """Figure out the module in which a function occurs. - - Search sys.modules for the module. - Cache in classmap. - Return a module name. - If the function cannot be found, return __main__. - """ - if classmap.has_key(func): - return classmap[func] - - for name, module in sys.modules.items(): - if module is None: - continue # skip dummy package entries - if name != '__main__' and \ - hasattr(module, funcname) and \ - getattr(module, funcname) is func: - break - else: - name = '__main__' - classmap[func] = name - return name - - -class Unpickler: - - def __init__(self, file): - self.readline = file.readline - self.read = file.read - self.memo = {} - - def load(self): - self.mark = object() # any new unique object - self.stack = [] - self.append = self.stack.append - read = self.read - dispatch = self.dispatch - try: - while 1: - key = read(1) - dispatch[key](self) - except _Stop, stopinst: - return stopinst.value - - def marker(self): - stack = self.stack - mark = self.mark - k = len(stack)-1 - while stack[k] is not mark: k = k-1 - return k - - dispatch = {} - - def load_eof(self): - raise EOFError - dispatch[''] = load_eof - - def load_persid(self): - pid = self.readline()[:-1] - self.append(self.persistent_load(pid)) - dispatch[PERSID] = load_persid - - def load_binpersid(self): - stack = self.stack - - pid = stack[-1] - del stack[-1] - - self.append(self.persistent_load(pid)) - dispatch[BINPERSID] = load_binpersid - - def load_none(self): - self.append(None) - dispatch[NONE] = load_none - - def load_int(self): - data = self.readline() - try: - self.append(int(data)) - except ValueError: - self.append(long(data)) - dispatch[INT] = load_int - - def load_binint(self): - self.append(mloads('i' + self.read(4))) - dispatch[BININT] = load_binint - - def load_binint1(self): - self.append(mloads('i' + self.read(1) + '\000\000\000')) - dispatch[BININT1] = load_binint1 - - def load_binint2(self): - self.append(mloads('i' + self.read(2) + '\000\000')) - dispatch[BININT2] = load_binint2 - - def load_long(self): - self.append(long(self.readline()[:-1], 0)) - dispatch[LONG] = load_long - - def load_float(self): - self.append(float(self.readline()[:-1])) - dispatch[FLOAT] = load_float - - def load_binfloat(self, unpack=struct.unpack): - self.append(unpack('>d', self.read(8))[0]) - dispatch[BINFLOAT] = load_binfloat - - def load_string(self): - rep = self.readline()[:-1] - if not self._is_string_secure(rep): - raise ValueError, "insecure string pickle" - self.append(eval(rep, - {'__builtins__': {}})) # Let's be careful - dispatch[STRING] = load_string - - def _is_string_secure(self, s): - """Return true if s contains a string that is safe to eval - - The definition of secure string is based on the implementation - in cPickle. s is secure as long as it only contains a quoted - string and optional trailing whitespace. - """ - q = s[0] - if q not in ("'", '"'): - return 0 - # find the closing quote - offset = 1 - i = None - while 1: - try: - i = s.index(q, offset) - except ValueError: - # if there is an error the first time, there is no - # close quote - if offset == 1: - return 0 - if s[i-1] != '\\': - break - # check to see if this one is escaped - nslash = 0 - j = i - 1 - while j >= offset and s[j] == '\\': - j = j - 1 - nslash = nslash + 1 - if nslash % 2 == 0: - break - offset = i + 1 - for c in s[i+1:]: - if ord(c) > 32: - return 0 - return 1 - - def load_binstring(self): - len = mloads('i' + self.read(4)) - self.append(self.read(len)) - dispatch[BINSTRING] = load_binstring - - def load_unicode(self): - self.append(unicode(self.readline()[:-1],'raw-unicode-escape')) - dispatch[UNICODE] = load_unicode - - def load_binunicode(self): - len = mloads('i' + self.read(4)) - self.append(unicode(self.read(len),'utf-8')) - dispatch[BINUNICODE] = load_binunicode - - def load_short_binstring(self): - len = mloads('i' + self.read(1) + '\000\000\000') - self.append(self.read(len)) - dispatch[SHORT_BINSTRING] = load_short_binstring - - def load_tuple(self): - k = self.marker() - self.stack[k:] = [tuple(self.stack[k+1:])] - dispatch[TUPLE] = load_tuple - - def load_empty_tuple(self): - self.stack.append(()) - dispatch[EMPTY_TUPLE] = load_empty_tuple - - def load_empty_list(self): - self.stack.append([]) - dispatch[EMPTY_LIST] = load_empty_list - - def load_empty_dictionary(self): - self.stack.append({}) - dispatch[EMPTY_DICT] = load_empty_dictionary - - def load_list(self): - k = self.marker() - self.stack[k:] = [self.stack[k+1:]] - dispatch[LIST] = load_list - - def load_dict(self): - k = self.marker() - d = {} - items = self.stack[k+1:] - for i in range(0, len(items), 2): - key = items[i] - value = items[i+1] - d[key] = value - self.stack[k:] = [d] - dispatch[DICT] = load_dict - - def load_inst(self): - k = self.marker() - args = tuple(self.stack[k+1:]) - del self.stack[k:] - module = self.readline()[:-1] - name = self.readline()[:-1] - klass = self.find_class(module, name) - instantiated = 0 - if (not args and type(klass) is ClassType and - not hasattr(klass, "__getinitargs__")): - try: - value = _EmptyClass() - value.__class__ = klass - instantiated = 1 - except RuntimeError: - # In restricted execution, assignment to inst.__class__ is - # prohibited - pass - if not instantiated: - try: - #XXX: This test is deprecated in 2.3, so commenting out. - #if not hasattr(klass, '__safe_for_unpickling__'): - # raise UnpicklingError('%s is not safe for unpickling' % - # klass) - value = apply(klass, args) - except TypeError, err: - raise TypeError, "in constructor for %s: %s" % ( - klass.__name__, str(err)), sys.exc_info()[2] - self.append(value) - dispatch[INST] = load_inst - - def load_obj(self): - stack = self.stack - k = self.marker() - klass = stack[k + 1] - del stack[k + 1] - args = tuple(stack[k + 1:]) - del stack[k:] - instantiated = 0 - if (not args and type(klass) is ClassType and - not hasattr(klass, "__getinitargs__")): - try: - value = _EmptyClass() - value.__class__ = klass - instantiated = 1 - except RuntimeError: - # In restricted execution, assignment to inst.__class__ is - # prohibited - pass - if not instantiated: - value = apply(klass, args) - self.append(value) - dispatch[OBJ] = load_obj - - def load_global(self): - module = self.readline()[:-1] - name = self.readline()[:-1] - klass = self.find_class(module, name) - self.append(klass) - dispatch[GLOBAL] = load_global - - def find_class(self, module, name): - __import__(module) - mod = sys.modules[module] - klass = getattr(mod, name) - return klass - - def load_reduce(self): - stack = self.stack - - callable = stack[-2] - arg_tup = stack[-1] - del stack[-2:] - - #XXX: The __safe_for_unpickling__ test is deprecated in 2.3, so commenting out. - #if type(callable) is not ClassType: - #if not safe_constructors.has_key(callable): - #try: - # safe = callable.__safe_for_unpickling__ - #except AttributeError: - # safe = None - # - #if not safe: - # raise UnpicklingError, "%s is not safe for " \ - # "unpickling" % callable - - if arg_tup is None: - value = callable.__basicnew__() - else: - value = apply(callable, arg_tup) - self.append(value) - dispatch[REDUCE] = load_reduce - - def load_pop(self): - del self.stack[-1] - dispatch[POP] = load_pop - - def load_pop_mark(self): - k = self.marker() - del self.stack[k:] - dispatch[POP_MARK] = load_pop_mark - - def load_dup(self): - self.append(self.stack[-1]) - dispatch[DUP] = load_dup - - def load_get(self): - self.append(self.memo[self.readline()[:-1]]) - dispatch[GET] = load_get - - def load_binget(self): - i = mloads('i' + self.read(1) + '\000\000\000') - self.append(self.memo[`i`]) - dispatch[BINGET] = load_binget - - def load_long_binget(self): - i = mloads('i' + self.read(4)) - self.append(self.memo[`i`]) - dispatch[LONG_BINGET] = load_long_binget - - def load_put(self): - self.memo[self.readline()[:-1]] = self.stack[-1] - dispatch[PUT] = load_put - - def load_binput(self): - i = mloads('i' + self.read(1) + '\000\000\000') - self.memo[`i`] = self.stack[-1] - dispatch[BINPUT] = load_binput - - def load_long_binput(self): - i = mloads('i' + self.read(4)) - self.memo[`i`] = self.stack[-1] - dispatch[LONG_BINPUT] = load_long_binput - - def load_append(self): - stack = self.stack - value = stack[-1] - del stack[-1] - list = stack[-1] - list.append(value) - dispatch[APPEND] = load_append - - def load_appends(self): - stack = self.stack - mark = self.marker() - list = stack[mark - 1] - for i in range(mark + 1, len(stack)): - list.append(stack[i]) - - del stack[mark:] - dispatch[APPENDS] = load_appends - - def load_setitem(self): - stack = self.stack - value = stack[-1] - key = stack[-2] - del stack[-2:] - dict = stack[-1] - dict[key] = value - dispatch[SETITEM] = load_setitem - - def load_setitems(self): - stack = self.stack - mark = self.marker() - dict = stack[mark - 1] - for i in range(mark + 1, len(stack), 2): - dict[stack[i]] = stack[i + 1] - - del stack[mark:] - dispatch[SETITEMS] = load_setitems - - def load_build(self): - stack = self.stack - value = stack[-1] - del stack[-1] - inst = stack[-1] - try: - setstate = inst.__setstate__ - except AttributeError: - try: - inst.__dict__.update(value) - except RuntimeError: - # XXX In restricted execution, the instance's __dict__ is not - # accessible. Use the old way of unpickling the instance - # variables. This is a semantic different when unpickling in - # restricted vs. unrestricted modes. - for k, v in value.items(): - setattr(inst, k, v) - else: - setstate(value) - dispatch[BUILD] = load_build - - def load_mark(self): - self.append(self.mark) - dispatch[MARK] = load_mark - - def load_stop(self): - value = self.stack[-1] - del self.stack[-1] - raise _Stop(value) - dispatch[STOP] = load_stop - -# Helper class for load_inst/load_obj - -class _EmptyClass: - pass - -# Shorthands - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - -def dump(object, file, bin = 0): - Pickler(file, bin).dump(object) - -def dumps(object, bin = 0): - file = StringIO() - Pickler(file, bin).dump(object) - return file.getvalue() - -def load(file): - return Unpickler(file).load() - -def loads(str): - file = StringIO(str) - return Unpickler(file).load() Index: Lib/opcode.py =================================================================== --- Lib/opcode.py (revision 0) +++ Lib/opcode.py (revision 0) @@ -0,0 +1 @@ +# stub opcode module added to allow imports Index: Lib/copy.py =================================================================== --- Lib/copy.py (revision 2831) +++ Lib/copy.py (working copy) @@ -1,330 +0,0 @@ -"""Generic (shallow and deep) copying operations. - -Interface summary: - - import copy - - x = copy.copy(y) # make a shallow copy of y - x = copy.deepcopy(y) # make a deep copy of y - -For module specific errors, copy.error is raised. - -The difference between shallow and deep copying is only relevant for -compound objects (objects that contain other objects, like lists or -class instances). - -- A shallow copy constructs a new compound object and then (to the - extent possible) inserts *the same objects* into in that the - original contains. - -- A deep copy constructs a new compound object and then, recursively, - inserts *copies* into it of the objects found in the original. - -Two problems often exist with deep copy operations that don't exist -with shallow copy operations: - - a) recursive objects (compound objects that, directly or indirectly, - contain a reference to themselves) may cause a recursive loop - - b) because deep copy copies *everything* it may copy too much, e.g. - administrative data structures that should be shared even between - copies - -Python's deep copy operation avoids these problems by: - - a) keeping a table of objects already copied during the current - copying pass - - b) letting user-defined classes override the copying operation or the - set of components copied - -This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. - -Classes can use the same interfaces to control copying that they use -to control pickling: they can define methods called __getinitargs__(), -__getstate__() and __setstate__(). See the documentation for module -"pickle" for information on these methods. -""" - -# XXX need to support copy_reg here too... - -import types - -class Error(Exception): - pass -error = Error # backward compatibility - -try: - from org.python.core import PyStringMap -except ImportError: - PyStringMap = None - -__all__ = ["Error","error","copy","deepcopy"] - -def copy(x): - """Shallow copy operation on arbitrary Python objects. - - See the module's __doc__ string for more info. - """ - - try: - copierfunction = _copy_dispatch[type(x)] - except KeyError: - try: - copier = x.__copy__ - except AttributeError: - raise error, \ - "un(shallow)copyable object of type %s" % type(x) - y = copier() - else: - y = copierfunction(x) - return y - -_copy_dispatch = d = {} - -def _copy_atomic(x): - return x -d[types.NoneType] = _copy_atomic -d[types.IntType] = _copy_atomic -d[types.LongType] = _copy_atomic -d[types.FloatType] = _copy_atomic -d[types.StringType] = _copy_atomic -d[types.UnicodeType] = _copy_atomic -try: - d[types.CodeType] = _copy_atomic -except AttributeError: - pass -d[types.TypeType] = _copy_atomic -d[types.XRangeType] = _copy_atomic -d[types.ClassType] = _copy_atomic - -def _copy_list(x): - return x[:] -d[types.ListType] = _copy_list - -def _copy_tuple(x): - return x[:] -d[types.TupleType] = _copy_tuple - -def _copy_dict(x): - return x.copy() -d[types.DictionaryType] = _copy_dict -if PyStringMap is not None: - d[PyStringMap] = _copy_dict - -def _copy_inst(x): - if hasattr(x, '__copy__'): - return x.__copy__() - if hasattr(x, '__getinitargs__'): - args = x.__getinitargs__() - y = apply(x.__class__, args) - else: - if hasattr(x.__class__, '__del__'): - y = _EmptyClassDel() - else: - y = _EmptyClass() - y.__class__ = x.__class__ - if hasattr(x, '__getstate__'): - state = x.__getstate__() - else: - state = x.__dict__ - if hasattr(y, '__setstate__'): - y.__setstate__(state) - else: - y.__dict__.update(state) - return y -d[types.InstanceType] = _copy_inst - -del d - -def deepcopy(x, memo = None): - """Deep copy operation on arbitrary Python objects. - - See the module's __doc__ string for more info. - """ - - if memo is None: - memo = {} - d = id(x) - if memo.has_key(d): - return memo[d] - try: - copierfunction = _deepcopy_dispatch[type(x)] - except KeyError: - try: - copier = x.__deepcopy__ - except AttributeError: - raise error, \ - "un-deep-copyable object of type %s" % type(x) - y = copier(memo) - else: - y = copierfunction(x, memo) - memo[d] = y - return y - -_deepcopy_dispatch = d = {} - -def _deepcopy_atomic(x, memo): - return x -d[types.NoneType] = _deepcopy_atomic -d[types.IntType] = _deepcopy_atomic -d[types.LongType] = _deepcopy_atomic -d[types.FloatType] = _deepcopy_atomic -d[types.StringType] = _deepcopy_atomic -d[types.UnicodeType] = _deepcopy_atomic -d[types.CodeType] = _deepcopy_atomic -d[types.TypeType] = _deepcopy_atomic -d[types.XRangeType] = _deepcopy_atomic - -def _deepcopy_list(x, memo): - y = [] - memo[id(x)] = y - for a in x: - y.append(deepcopy(a, memo)) - return y -d[types.ListType] = _deepcopy_list - -def _deepcopy_tuple(x, memo): - y = [] - for a in x: - y.append(deepcopy(a, memo)) - d = id(x) - try: - return memo[d] - except KeyError: - pass - for i in range(len(x)): - if x[i] is not y[i]: - y = tuple(y) - break - else: - y = x - memo[d] = y - return y -d[types.TupleType] = _deepcopy_tuple - -def _deepcopy_dict(x, memo): - y = {} - memo[id(x)] = y - for key in x.keys(): - y[deepcopy(key, memo)] = deepcopy(x[key], memo) - return y -d[types.DictionaryType] = _deepcopy_dict -if PyStringMap is not None: - d[PyStringMap] = _deepcopy_dict - -def _keep_alive(x, memo): - """Keeps a reference to the object x in the memo. - - Because we remember objects by their id, we have - to assure that possibly temporary objects are kept - alive by referencing them. - We store a reference at the id of the memo, which should - normally not be used unless someone tries to deepcopy - the memo itself... - """ - try: - memo[id(memo)].append(x) - except KeyError: - # aha, this is the first one :-) - memo[id(memo)]=[x] - -def _deepcopy_inst(x, memo): - if hasattr(x, '__deepcopy__'): - return x.__deepcopy__(memo) - if hasattr(x, '__getinitargs__'): - args = x.__getinitargs__() - _keep_alive(args, memo) - args = deepcopy(args, memo) - y = apply(x.__class__, args) - else: - if hasattr(x.__class__, '__del__'): - y = _EmptyClassDel() - else: - y = _EmptyClass() - y.__class__ = x.__class__ - memo[id(x)] = y - if hasattr(x, '__getstate__'): - state = x.__getstate__() - _keep_alive(state, memo) - else: - state = x.__dict__ - state = deepcopy(state, memo) - if hasattr(y, '__setstate__'): - y.__setstate__(state) - else: - y.__dict__.update(state) - return y -d[types.InstanceType] = _deepcopy_inst - -del d - -del types - -# Helper for instance creation without calling __init__ -class _EmptyClass: - pass - -# Helper for instance creation without calling __init__. Used when -# the source class contains a __del__ attribute. -class _EmptyClassDel: - def __del__(self): - pass - -def _test(): - l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'], - {'abc': 'ABC'}, (), [], {}] - l1 = copy(l) - print l1==l - l1 = map(copy, l) - print l1==l - l1 = deepcopy(l) - print l1==l - class C: - def __init__(self, arg=None): - self.a = 1 - self.arg = arg - if __name__ == '__main__': - import sys - file = sys.argv[0] - else: - file = __file__ - self.fp = open(file) - self.fp.close() - def __getstate__(self): - return {'a': self.a, 'arg': self.arg} - def __setstate__(self, state): - for key in state.keys(): - setattr(self, key, state[key]) - def __deepcopy__(self, memo = None): - new = self.__class__(deepcopy(self.arg, memo)) - new.a = self.a - return new - c = C('argument sketch') - l.append(c) - l2 = copy(l) - print l == l2 - print l - print l2 - l2 = deepcopy(l) - print l == l2 - print l - print l2 - l.append({l[1]: l, 'xyz': l[2]}) - l3 = copy(l) - import repr - print map(repr.repr, l) - print map(repr.repr, l1) - print map(repr.repr, l2) - print map(repr.repr, l3) - l3 = deepcopy(l) - import repr - print map(repr.repr, l) - print map(repr.repr, l1) - print map(repr.repr, l2) - print map(repr.repr, l3) - -if __name__ == '__main__': - _test() Index: Lib/dis.py =================================================================== --- Lib/dis.py (revision 0) +++ Lib/dis.py (revision 0) @@ -0,0 +1 @@ +# stub dis module added to allow imports Index: src/org/python/core/PyInteger.java =================================================================== --- src/org/python/core/PyInteger.java (revision 2831) +++ src/org/python/core/PyInteger.java (working copy) @@ -1058,34 +1058,6 @@ } dict.__setitem__("__nonzero__",new PyMethodDescr("__nonzero__",PyInteger.class,0,0,new exposed___nonzero__(null,null))); - class exposed___reduce__ extends PyBuiltinFunctionNarrow { - - private PyInteger self; - - public PyObject getSelf() { - return self; - } - - exposed___reduce__(PyInteger self,PyBuiltinFunction.Info info) { - super(info); - this.self=self; - } - - public PyBuiltinFunction makeBound(PyObject self) { - return new exposed___reduce__((PyInteger)self,info); - } - - public PyObject __call__() { - return self.int___reduce__(); - } - - public PyObject inst_call(PyObject gself) { - PyInteger self=(PyInteger)gself; - return self.int___reduce__(); - } - - } - dict.__setitem__("__reduce__",new PyMethodDescr("__reduce__",PyInteger.class,0,0,new exposed___reduce__(null,null))); class exposed___repr__ extends PyBuiltinFunctionNarrow { private PyInteger self; @@ -1812,22 +1784,4 @@ public int asInt(int index) { return getValue(); } - - /** - * Used for pickling. - * - * @return a tuple of (class, (Integer)) - */ - public PyObject __reduce__() { - return int___reduce__(); - } - - final PyObject int___reduce__() { - return new PyTuple(new PyObject[]{ - getType(), - new PyTuple(new PyObject[]{ - Py.newInteger(getValue()) - }) - }); - } } Index: src/org/python/core/PyString.java =================================================================== --- src/org/python/core/PyString.java (revision 2831) +++ src/org/python/core/PyString.java (working copy) @@ -285,34 +285,6 @@ } dict.__setitem__("__mul__",new PyMethodDescr("__mul__",PyString.class,1,1,new exposed___mul__(null,null))); - class exposed___reduce__ extends PyBuiltinFunctionNarrow { - - private PyString self; - - public PyObject getSelf() { - return self; - } - - exposed___reduce__(PyString self,PyBuiltinFunction.Info info) { - super(info); - this.self=self; - } - - public PyBuiltinFunction makeBound(PyObject self) { - return new exposed___reduce__((PyString)self,info); - } - - public PyObject __call__() { - return self.str___reduce__(); - } - - public PyObject inst_call(PyObject gself) { - PyString self=(PyString)gself; - return self.str___reduce__(); - } - - } - dict.__setitem__("__reduce__",new PyMethodDescr("__reduce__",PyString.class,0,0,new exposed___reduce__(null,null))); class exposed___rmul__ extends PyBuiltinFunctionNarrow { private PyString self; @@ -3368,19 +3340,6 @@ return seq___getitem__(index); } - /** - * Used for pickling. - * - * @return a tuple of (class, tuple) - */ - public PyObject __reduce__() { - return str___reduce__(); - } - - final PyObject str___reduce__() { - return object___reduce__(); - } - public PyTuple __getnewargs__() { return new PyTuple(new PyObject[]{ new PyString(str_toString()) Index: src/org/python/core/PyObject.java =================================================================== --- src/org/python/core/PyObject.java (revision 2831) +++ src/org/python/core/PyObject.java (working copy) @@ -48,6 +48,67 @@ } dict.__setitem__("__reduce__",new PyMethodDescr("__reduce__",PyObject.class,0,0,new exposed___reduce__(null,null))); + class exposed___reduce_ex__ extends PyBuiltinFunctionNarrow { + + private PyObject self; + + public PyObject getSelf() { + return self; + } + + exposed___reduce_ex__(PyObject self,PyBuiltinFunction.Info info) { + super(info); + this.self=self; + } + + public PyBuiltinFunction makeBound(PyObject self) { + return new exposed___reduce_ex__((PyObject)self,info); + } + + public PyObject __call__(PyObject arg0) { + try { + return self.object___reduce_ex__(arg0.asInt(0)); + } catch (PyObject.ConversionException e) { + String msg; + switch (e.index) { + case 0: + msg="expected an integer"; + break; + default: + msg="xxx"; + } + throw Py.TypeError(msg); + } + } + + public PyObject inst_call(PyObject gself,PyObject arg0) { + PyObject self=(PyObject)gself; + try { + return self.object___reduce_ex__(arg0.asInt(0)); + } catch (PyObject.ConversionException e) { + String msg; + switch (e.index) { + case 0: + msg="expected an integer"; + break; + default: + msg="xxx"; + } + throw Py.TypeError(msg); + } + } + + public PyObject __call__() { + return self.object___reduce_ex__(); + } + + public PyObject inst_call(PyObject gself) { + PyObject self=(PyObject)gself; + return self.object___reduce_ex__(); + } + + } + dict.__setitem__("__reduce_ex__",new PyMethodDescr("__reduce_ex__",PyObject.class,0,1,new exposed___reduce_ex__(null,null))); class exposed___str__ extends PyBuiltinFunctionNarrow { private PyObject self; @@ -2917,7 +2978,7 @@ } /** - * Used for pickling. + * Used for pickling. Default implementation calls __reduce_ex__(0). * * @return a tuple of (class, tuple) */ @@ -2926,12 +2987,151 @@ } final PyObject object___reduce__() { - PyTuple newargs = __getnewargs__(); - return new PyTuple(new PyObject[]{ - getType(), newargs - }); + return object___reduce_ex__(0); } + /** Used for pickling. If the subclass specifies __reduce__, it will + * override __reduce_ex__ in the base-class, even if __reduce_ex__ was + * called with an argument. + * + * @param arg PyInteger specifying reduce algorithm (method without this + * argument defaults to 0). + * @return a tuple of (class, tuple) + */ + public PyObject __reduce_ex__(int arg) { + return object___reduce_ex__(arg); + } + public PyObject __reduce_ex__() { + return object___reduce_ex__(0); + } + final PyObject object___reduce_ex__() { + return object___reduce_ex__(0); + } + final PyObject object___reduce_ex__(int arg) { + PyObject res; + + PyObject clsreduce=this.getType().__findattr__("__reduce__"); + PyObject objreduce=(new PyObject()).getType().__findattr__("__reduce__"); + + if (clsreduce!=objreduce) { + res=this.__reduce__(); + } else if (arg>=2) { + res=reduce_2(); + } else { + PyObject copyreg=__builtin__.__import__("copy_reg", null, null, + Py.EmptyTuple); + PyObject copyreg_reduce=copyreg.__findattr__("_reduce_ex"); + res=copyreg_reduce.__call__(this, new PyInteger(arg)); + } + return res; + } + + private static PyObject slotnames(PyObject cls) { + PyObject slotnames; + + slotnames=cls.__findattr__("__slotnames__"); + if(null!=slotnames) { + return slotnames; + } + + PyObject copyreg=__builtin__.__import__("copy_reg", null, null, + Py.EmptyTuple); + PyObject copyreg_slotnames=copyreg.__findattr__("_slotnames"); + slotnames=copyreg_slotnames.__call__(cls); + if (null!=slotnames && Py.None!=slotnames && + (!(slotnames instanceof PyList))) { + throw Py.TypeError("copy_reg._slotnames didn't return a list or None"); + } + + return slotnames; + } + + private PyObject reduce_2() { + PyObject args, state; + PyObject res=null; + int n,i; + + PyObject cls=this.__findattr__("__class__"); + + PyObject getnewargs=this.__findattr__("__getnewargs__"); + if (null!=getnewargs) { + args=getnewargs.__call__(); + if (null!=args && !(args instanceof PyTuple)) { + throw Py.TypeError("__getnewargs__ should return a tuple"); + } + } else { + args=Py.EmptyTuple; + } + + PyObject getstate=this.__findattr__("__getstate__"); + if (null!=getstate) { + state=getstate.__call__(); + if (null==state) { + return res; + } + } else { + state=this.__findattr__("__dict__"); + if (null==state) { + state=Py.None; + } + + PyObject names=slotnames(cls); + if (null==names) { + return res; + } + + if (names != Py.None) { + if (!(names instanceof PyList)) { + throw Py.AssertionError("slots not a list"); + } + PyObject slots=new PyDictionary(); + + n=0; + for (i=0;i<((PyList)names).size();i++) { + PyObject name=((PyList)names).pyget(i); + PyObject value=this.__findattr__(name.toString()); + if (null==value) { + // do nothing + } else { + slots.__setitem__(name, value); + n++; + } + } + if (n>0) { + state=new PyTuple(new PyObject[] {state, slots}); + } + } + } + PyObject listitems; + PyObject dictitems; + if (!(this instanceof PyList)) { + listitems=Py.None; + } else { + listitems=((PyList)this).__iter__(); + } + if (!(this instanceof PyDictionary)) { + dictitems=Py.None; + } else { + dictitems=((PyDictionary)this).iteritems(); + } + + PyObject copyreg=__builtin__.__import__("copy_reg", null, null, + Py.EmptyTuple); + PyObject newobj=copyreg.__findattr__("__newobj__"); + + n=((PyTuple)args).size(); + PyObject args2[]=new PyObject[n+1]; + args2[0]=cls; + for(i=0;i" || valTable[idx] == null) + PyObject val = valTable[idx]; + if (key == null || key == "" || val == null) continue; idx++; - return Py.newString(key); + + switch(type) { + case VALUES: + return val; + case ITEMS: + return new PyTuple(new PyObject[] { Py.newString(key), + val }); + default: // KEYS + return Py.newString(key); + } } return null; } Index: src/org/python/core/PyComplex.java =================================================================== --- src/org/python/core/PyComplex.java (revision 2831) +++ src/org/python/core/PyComplex.java (working copy) @@ -869,34 +869,6 @@ } dict.__setitem__("__nonzero__",new PyMethodDescr("__nonzero__",PyComplex.class,0,0,new exposed___nonzero__(null,null))); - class exposed___reduce__ extends PyBuiltinFunctionNarrow { - - private PyComplex self; - - public PyObject getSelf() { - return self; - } - - exposed___reduce__(PyComplex self,PyBuiltinFunction.Info info) { - super(info); - this.self=self; - } - - public PyBuiltinFunction makeBound(PyObject self) { - return new exposed___reduce__((PyComplex)self,info); - } - - public PyObject __call__() { - return self.complex___reduce__(); - } - - public PyObject inst_call(PyObject gself) { - PyComplex self=(PyComplex)gself; - return self.complex___reduce__(); - } - - } - dict.__setitem__("__reduce__",new PyMethodDescr("__reduce__",PyComplex.class,0,0,new exposed___reduce__(null,null))); class exposed___repr__ extends PyBuiltinFunctionNarrow { private PyComplex self; @@ -1623,24 +1595,6 @@ return new PyComplex(real, -imag); } - /** - * Used for pickling. - * - * @return a tuple of (class, (Integer)) - */ - public PyObject __reduce__() { - return complex___reduce__(); - } - - final PyObject complex___reduce__() { - return new PyTuple(new PyObject[]{ - getType(), - new PyTuple(new PyObject[]{ - getReal(), getImag() - }) - }); - } - public boolean isMappingType() { return false; } public boolean isSequenceType() { return false; } } Index: src/org/python/core/PyList.java =================================================================== --- src/org/python/core/PyList.java (revision 2831) +++ src/org/python/core/PyList.java (working copy) @@ -892,34 +892,6 @@ } dict.__setitem__("__imul__",new PyMethodDescr("__imul__",PyList.class,1,1,new exposed___imul__(null,null))); - class exposed___reduce__ extends PyBuiltinFunctionNarrow { - - private PyList self; - - public PyObject getSelf() { - return self; - } - - exposed___reduce__(PyList self,PyBuiltinFunction.Info info) { - super(info); - this.self=self; - } - - public PyBuiltinFunction makeBound(PyObject self) { - return new exposed___reduce__((PyList)self,info); - } - - public PyObject __call__() { - return self.list___reduce__(); - } - - public PyObject inst_call(PyObject gself) { - PyList self=(PyList)gself; - return self.list___reduce__(); - } - - } - dict.__setitem__("__reduce__",new PyMethodDescr("__reduce__",PyList.class,0,0,new exposed___reduce__(null,null))); class exposed___mul__ extends PyBuiltinFunctionNarrow { private PyList self; @@ -1711,22 +1683,6 @@ throw Py.TypeError("unhashable type"); } - /** - * Used for pickling. - * - * @return a tuple of (class, tuple) - */ - public PyObject __reduce__() { - return list___reduce__(); - } - - final PyObject list___reduce__() { - PyTuple newargs = __getnewargs__(); - return new PyTuple(new PyObject[]{ - getType(), newargs - }); - } - public PyTuple __getnewargs__() { return new PyTuple(new PyObject[] {new PyTuple(list.getArray())} Index: src/org/python/modules/cPickle.java =================================================================== --- src/org/python/modules/cPickle.java (revision 2831) +++ src/org/python/modules/cPickle.java (working copy) @@ -343,6 +343,10 @@ public static final String[] compatible_formats = new String[] { "1.0", "1.1", "1.2" }; + /** + * Highest protocol version supported. + */ + public static final int HIGHEST_PROTOCOL = 2; public static String[] __depends__ = new String[] { "copy_reg", @@ -450,8 +454,8 @@ PyModule copyreg = (PyModule)importModule("copy_reg"); dispatch_table = (PyDictionary)copyreg.__getattr__("dispatch_table"); - safe_constructors = (PyDictionary) - copyreg.__getattr__("safe_constructors"); + // safe_constructors = (PyDictionary) + // copyreg.__getattr__("safe_constructors"); PickleError = buildClass("PickleError", Py.Exception, "_PickleError", ""); Index: src/org/python/modules/types.java =================================================================== --- src/org/python/modules/types.java (revision 2831) +++ src/org/python/modules/types.java (working copy) @@ -48,7 +48,7 @@ dict.__setitem__("TracebackType", PyType.fromClass(PyTraceback.class)); dict.__setitem__("TupleType", PyType.fromClass(PyTuple.class)); - dict.__setitem__("TypeType", PyType.fromClass(PyJavaClass.class)); + dict.__setitem__("TypeType", PyType.fromClass(PyType.class)); dict.__setitem__("UnboundMethodType", PyType.fromClass(PyMethod.class)); dict.__setitem__("UnicodeType", PyType.fromClass(PyString.class));