NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

copy.py (9056B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\copy.py
      2 import types
      3 import weakref
      4 from copy_reg import dispatch_table
      5 
      6 class Error(Exception):
      7     pass
      8 
      9 
     10 error = Error
     11 try:
     12     from org.python.core import PyStringMap
     13 except ImportError:
     14     PyStringMap = None
     15 
     16 __all__ = ['Error', 'copy', 'deepcopy']
     17 
     18 def copy(x):
     19     cls = type(x)
     20     copier = _copy_dispatch.get(cls)
     21     if copier:
     22         return copier(x)
     23     copier = getattr(cls, '__copy__', None)
     24     if copier:
     25         return copier(x)
     26     reductor = dispatch_table.get(cls)
     27     if reductor:
     28         rv = reductor(x)
     29     else:
     30         reductor = getattr(x, '__reduce_ex__', None)
     31         if reductor:
     32             rv = reductor(2)
     33         else:
     34             reductor = getattr(x, '__reduce__', None)
     35             if reductor:
     36                 rv = reductor()
     37             else:
     38                 raise Error('un(shallow)copyable object of type %s' % cls)
     39     return _reconstruct(x, rv, 0)
     40 
     41 
     42 _copy_dispatch = d = {}
     43 
     44 def _copy_immutable(x):
     45     return x
     46 
     47 
     48 for t in (type(None),
     49  int,
     50  long,
     51  float,
     52  bool,
     53  str,
     54  tuple,
     55  frozenset,
     56  type,
     57  xrange,
     58  types.ClassType,
     59  types.BuiltinFunctionType,
     60  type(Ellipsis),
     61  types.FunctionType,
     62  weakref.ref):
     63     d[t] = _copy_immutable
     64 
     65 for name in ('ComplexType', 'UnicodeType', 'CodeType'):
     66     t = getattr(types, name, None)
     67     if t is not None:
     68         d[t] = _copy_immutable
     69 
     70 def _copy_with_constructor(x):
     71     return type(x)(x)
     72 
     73 
     74 for t in (list, dict, set):
     75     d[t] = _copy_with_constructor
     76 
     77 def _copy_with_copy_method(x):
     78     return x.copy()
     79 
     80 
     81 if PyStringMap is not None:
     82     d[PyStringMap] = _copy_with_copy_method
     83 
     84 def _copy_inst(x):
     85     if hasattr(x, '__copy__'):
     86         return x.__copy__()
     87     if hasattr(x, '__getinitargs__'):
     88         args = x.__getinitargs__()
     89         y = x.__class__(*args)
     90     else:
     91         y = _EmptyClass()
     92         y.__class__ = x.__class__
     93     if hasattr(x, '__getstate__'):
     94         state = x.__getstate__()
     95     else:
     96         state = x.__dict__
     97     if hasattr(y, '__setstate__'):
     98         y.__setstate__(state)
     99     else:
    100         y.__dict__.update(state)
    101     return y
    102 
    103 
    104 d[types.InstanceType] = _copy_inst
    105 del d
    106 
    107 def deepcopy(x, memo = None, _nil = []):
    108     if memo is None:
    109         memo = {}
    110     d = id(x)
    111     y = memo.get(d, _nil)
    112     if y is not _nil:
    113         return y
    114     cls = type(x)
    115     copier = _deepcopy_dispatch.get(cls)
    116     if copier:
    117         y = copier(x, memo)
    118     else:
    119         try:
    120             issc = issubclass(cls, type)
    121         except TypeError:
    122             issc = 0
    123 
    124         if issc:
    125             y = _deepcopy_atomic(x, memo)
    126         else:
    127             copier = getattr(x, '__deepcopy__', None)
    128             if copier:
    129                 y = copier(memo)
    130             else:
    131                 reductor = dispatch_table.get(cls)
    132                 if reductor:
    133                     rv = reductor(x)
    134                 else:
    135                     reductor = getattr(x, '__reduce_ex__', None)
    136                     if reductor:
    137                         rv = reductor(2)
    138                     else:
    139                         reductor = getattr(x, '__reduce__', None)
    140                         if reductor:
    141                             rv = reductor()
    142                         else:
    143                             raise Error('un(deep)copyable object of type %s' % cls)
    144                 y = _reconstruct(x, rv, 1, memo)
    145     memo[d] = y
    146     _keep_alive(x, memo)
    147     return y
    148 
    149 
    150 _deepcopy_dispatch = d = {}
    151 
    152 def _deepcopy_atomic(x, memo):
    153     return x
    154 
    155 
    156 d[type(None)] = _deepcopy_atomic
    157 d[type(Ellipsis)] = _deepcopy_atomic
    158 d[int] = _deepcopy_atomic
    159 d[long] = _deepcopy_atomic
    160 d[float] = _deepcopy_atomic
    161 d[bool] = _deepcopy_atomic
    162 try:
    163     d[complex] = _deepcopy_atomic
    164 except NameError:
    165     pass
    166 
    167 d[str] = _deepcopy_atomic
    168 try:
    169     d[unicode] = _deepcopy_atomic
    170 except NameError:
    171     pass
    172 
    173 try:
    174     d[types.CodeType] = _deepcopy_atomic
    175 except AttributeError:
    176     pass
    177 
    178 d[type] = _deepcopy_atomic
    179 d[xrange] = _deepcopy_atomic
    180 d[types.ClassType] = _deepcopy_atomic
    181 d[types.BuiltinFunctionType] = _deepcopy_atomic
    182 d[types.FunctionType] = _deepcopy_atomic
    183 d[weakref.ref] = _deepcopy_atomic
    184 
    185 def _deepcopy_list(x, memo):
    186     y = []
    187     memo[id(x)] = y
    188     for a in x:
    189         y.append(deepcopy(a, memo))
    190 
    191     return y
    192 
    193 
    194 d[list] = _deepcopy_list
    195 
    196 def _deepcopy_tuple(x, memo):
    197     y = []
    198     for a in x:
    199         y.append(deepcopy(a, memo))
    200 
    201     d = id(x)
    202     try:
    203         return memo[d]
    204     except KeyError:
    205         pass
    206 
    207     for i in range(len(x)):
    208         if x[i] is not y[i]:
    209             y = tuple(y)
    210             break
    211     else:
    212         y = x
    213 
    214     memo[d] = y
    215     return y
    216 
    217 
    218 d[tuple] = _deepcopy_tuple
    219 
    220 def _deepcopy_dict(x, memo):
    221     y = {}
    222     memo[id(x)] = y
    223     for key, value in x.iteritems():
    224         y[deepcopy(key, memo)] = deepcopy(value, memo)
    225 
    226     return y
    227 
    228 
    229 d[dict] = _deepcopy_dict
    230 if PyStringMap is not None:
    231     d[PyStringMap] = _deepcopy_dict
    232 
    233 def _deepcopy_method(x, memo):
    234     return type(x)(x.im_func, deepcopy(x.im_self, memo), x.im_class)
    235 
    236 
    237 _deepcopy_dispatch[types.MethodType] = _deepcopy_method
    238 
    239 def _keep_alive(x, memo):
    240     try:
    241         memo[id(memo)].append(x)
    242     except KeyError:
    243         memo[id(memo)] = [x]
    244 
    245 
    246 def _deepcopy_inst(x, memo):
    247     if hasattr(x, '__deepcopy__'):
    248         return x.__deepcopy__(memo)
    249     if hasattr(x, '__getinitargs__'):
    250         args = x.__getinitargs__()
    251         args = deepcopy(args, memo)
    252         y = x.__class__(*args)
    253     else:
    254         y = _EmptyClass()
    255         y.__class__ = x.__class__
    256     memo[id(x)] = y
    257     if hasattr(x, '__getstate__'):
    258         state = x.__getstate__()
    259     else:
    260         state = x.__dict__
    261     state = deepcopy(state, memo)
    262     if hasattr(y, '__setstate__'):
    263         y.__setstate__(state)
    264     else:
    265         y.__dict__.update(state)
    266     return y
    267 
    268 
    269 d[types.InstanceType] = _deepcopy_inst
    270 
    271 def _reconstruct(x, info, deep, memo = None):
    272     if isinstance(info, str):
    273         return x
    274     if memo is None:
    275         memo = {}
    276     n = len(info)
    277     callable, args = info[:2]
    278     if n > 2:
    279         state = info[2]
    280     else:
    281         state = {}
    282     if n > 3:
    283         listiter = info[3]
    284     else:
    285         listiter = None
    286     if n > 4:
    287         dictiter = info[4]
    288     else:
    289         dictiter = None
    290     if deep:
    291         args = deepcopy(args, memo)
    292     y = callable(*args)
    293     memo[id(x)] = y
    294     if state:
    295         if deep:
    296             state = deepcopy(state, memo)
    297         if hasattr(y, '__setstate__'):
    298             y.__setstate__(state)
    299         else:
    300             if isinstance(state, tuple) and len(state) == 2:
    301                 state, slotstate = state
    302             else:
    303                 slotstate = None
    304             if state is not None:
    305                 y.__dict__.update(state)
    306             if slotstate is not None:
    307                 for key, value in slotstate.iteritems():
    308                     setattr(y, key, value)
    309 
    310     if listiter is not None:
    311         for item in listiter:
    312             if deep:
    313                 item = deepcopy(item, memo)
    314             y.append(item)
    315 
    316     if dictiter is not None:
    317         for key, value in dictiter:
    318             if deep:
    319                 key = deepcopy(key, memo)
    320                 value = deepcopy(value, memo)
    321             y[key] = value
    322 
    323     return y
    324 
    325 
    326 del d
    327 del types
    328 
    329 class _EmptyClass:
    330     pass
    331 
    332 
    333 def _test():
    334     l = [None,
    335      1,
    336      2L,
    337      3.14,
    338      'xyzzy',
    339      (1, 2L),
    340      [3.14, 'abc'],
    341      {'abc': 'ABC'},
    342      (),
    343      [],
    344      {}]
    345     l1 = copy(l)
    346     print l1 == l
    347     l1 = map(copy, l)
    348     print l1 == l
    349     l1 = deepcopy(l)
    350     print l1 == l
    351 
    352     class C:
    353 
    354         def __init__(self, arg = None):
    355             self.a = 1
    356             self.arg = arg
    357             if __name__ == '__main__':
    358                 import sys
    359                 file = sys.argv[0]
    360             else:
    361                 file = __file__
    362             self.fp = open(file)
    363             self.fp.close()
    364 
    365         def __getstate__(self):
    366             return {'a': self.a,
    367              'arg': self.arg}
    368 
    369         def __setstate__(self, state):
    370             for key, value in state.iteritems():
    371                 setattr(self, key, value)
    372 
    373         def __deepcopy__(self, memo = None):
    374             new = self.__class__(deepcopy(self.arg, memo))
    375             new.a = self.a
    376             return new
    377 
    378     c = C('argument sketch')
    379     l.append(c)
    380     l2 = copy(l)
    381     print l == l2
    382     print l
    383     print l2
    384     l2 = deepcopy(l)
    385     print l == l2
    386     print l
    387     print l2
    388     l.append({l[1]: l,
    389      'xyz': l[2]})
    390     l3 = copy(l)
    391     import repr
    392     print map(repr.repr, l)
    393     print map(repr.repr, l1)
    394     print map(repr.repr, l2)
    395     print map(repr.repr, l3)
    396     l3 = deepcopy(l)
    397     import repr
    398     print map(repr.repr, l)
    399     print map(repr.repr, l1)
    400     print map(repr.repr, l2)
    401     print map(repr.repr, l3)
    402 
    403     class odict(dict):
    404 
    405         def __init__(self, d = {}):
    406             self.a = 99
    407             dict.__init__(self, d)
    408 
    409         def __setitem__(self, k, i):
    410             dict.__setitem__(self, k, i)
    411             self.a
    412 
    413     o = odict({'A': 'B'})
    414     x = deepcopy(o)
    415     print (o, x)
    416 
    417 
    418 if __name__ == '__main__':
    419     _test()