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

rowset.py (18743B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\common\script\sys\rowset.py
      2 import _weakref
      3 import __builtin__
      4 import types
      5 import string
      6 import weakref
      7 import sys
      8 import uthread
      9 import copy
     10 import blue
     11 from carbon.common.script.sys.row import Row as utilRow
     12 import log
     13 
     14 def Select(selection, headers, iterator, options):
     15     if len(selection) == 1:
     16         i = headers.index(selection[0])
     17         if options.get('line', False):
     18             return [ (line, line[i]) for line in iterator ]
     19         else:
     20             return [ line[i] for line in iterator ]
     21     else:
     22         indices = []
     23         for header in selection:
     24             indices.append(headers.index(header))
     25 
     26         if options.get('line', False):
     27             return [ (line, [ line[i] for i in indices ]) for line in iterator ]
     28         return [ [ line[i] for i in indices ] for line in iterator ]
     29 
     30 
     31 class Rowset:
     32     __passbyvalue__ = 1
     33     __immutable__ = weakref.WeakKeyDictionary()
     34     RowClass = utilRow
     35 
     36     def __init__(self, hd = None, li = None, RowClass = utilRow):
     37         if hd is None:
     38             hd = []
     39         if li is None:
     40             li = []
     41         self.header = hd
     42         self.lines = li
     43         self.RowClass = RowClass
     44 
     45     def Clone(self):
     46         return Rowset(copy.copy(self.header), copy.copy(self.lines), self.RowClass)
     47 
     48     def IsImmutable(self):
     49         return self in self.__immutable__
     50 
     51     def MakeImmutable(self):
     52         if self not in self.__immutable__:
     53             self.__immutable__[self] = [{}, {}]
     54 
     55     def __str__(self):
     56         try:
     57             stuff = []
     58             for eachRow in self:
     59                 stuff.append(strx(eachRow))
     60 
     61             return '<Rowset: header=%s, data=["' % strx(self.header) + string.join(stuff, '","') + '"]>'
     62         except:
     63             sys.exc_clear()
     64             return 'Rowset, hd=' + strx(self.header)
     65 
     66     def __len__(self):
     67         return len(self.lines)
     68 
     69     def RenameField(self, oldName, newName):
     70         if self in self.__immutable__:
     71             raise RuntimeError('Immutable Rowsets may not be modified')
     72         for i in range(len(self.header)):
     73             if self.header[i] == oldName:
     74                 self.header[i] = newName
     75                 return
     76 
     77         log.LogTraceback()
     78         raise RuntimeError('No Such Field')
     79 
     80     def AddField(self, fieldName, value):
     81         if self in self.__immutable__:
     82             raise RuntimeError('Immutable Rowsets may not be modified')
     83         if len(self.lines) and type(self.lines[0]) == type(()):
     84             raise RuntimeError('CannotAddFieldsToATupleRowset', self)
     85         self.header.append(fieldName)
     86         for l in self.lines:
     87             l.append(value)
     88 
     89     def RemoveField(self, fieldName):
     90         if self in self.__immutable__:
     91             raise RuntimeError('Immutable Rowsets may not be modified')
     92         if len(self.lines) and type(self.lines[0]) == type(()):
     93             raise RuntimeError('CannotRemoveFieldsFromATupleRowset', self)
     94         idx = self.header.index(fieldName)
     95         del self.header[idx]
     96         for l in self.lines:
     97             del l[idx]
     98 
     99     def find(self, column, value):
    100         h = self.header.index(column)
    101         for i in xrange(len(self.lines)):
    102             if self.lines[i][h] == value:
    103                 return i
    104 
    105         return -1
    106 
    107     def Select(self, *selection, **options):
    108         return Select(selection, self.header, self.lines, options)
    109 
    110     def __getitem__(self, index):
    111         return self.RowClass(self.header, self.lines[index])
    112 
    113     def __setitem__(self, i, v):
    114         if self in self.__immutable__:
    115             raise RuntimeError('Immutable Rowsets may not be modified')
    116         if type(v) == types.InstanceType:
    117             self[i] = v.line
    118             return
    119         if len(v):
    120             if len(v) > len(self.header):
    121                 raise RuntimeError('Too many columns, got %s, fields are %s' % (len(v), self.header))
    122             self.lines[i] = list(v) + [None] * (len(self.header) - len(v))
    123         else:
    124             self.lines[i] = [None] * len(self.header)
    125 
    126     def __getslice__(self, i, j):
    127         return Rowset(self.header, self.lines[i:j], self.RowClass)
    128 
    129     def __delitem__(self, index):
    130         if self in self.__immutable__:
    131             raise RuntimeError('Immutable Rowsets may not be modified')
    132         del self.lines[index]
    133 
    134     def sort(self, f = None):
    135         if self in self.__immutable__:
    136             raise RuntimeError('Immutable Rowsets may not be modified')
    137         if f is not None:
    138             self.lines.sort(f)
    139         else:
    140             self.lines.sort()
    141 
    142     def extend(self, other):
    143         if self in self.__immutable__:
    144             raise RuntimeError('Immutable Rowsets may not be modified')
    145         self.lines.extend(other.lines)
    146 
    147     def remove(self, row):
    148         if self in self.__immutable__:
    149             raise RuntimeError('Immutable Rowsets may not be modified')
    150         try:
    151             self.lines.remove(row.line)
    152         except ValueError:
    153             sys.exc_clear()
    154         except AttributeError:
    155             sys.exc_clear()
    156             self.lines.remove(row)
    157 
    158     def pop(self, idx):
    159         if self in self.__immutable__:
    160             raise RuntimeError('Immutable Rowsets may not be modified')
    161         return self.RowClass(self.header, self.lines.pop(idx))
    162 
    163     def InsertNew(self, *args):
    164         if self in self.__immutable__:
    165             raise RuntimeError('Immutable Rowsets may not be modified')
    166         if len(args):
    167             if len(args) > len(self.header):
    168                 raise RuntimeError('Too many arguments, got %s, fields are %s' % (len(args), self.header))
    169             self.lines.append(list(args) + [None] * (len(self.header) - len(args)))
    170         else:
    171             self.lines.append([None] * len(self.header))
    172         return self[-1]
    173 
    174     def Sort(self, colname, asc = 1):
    175         ret = self[:]
    176         if asc:
    177             ret.lines.sort(lambda a, b, colid = self.header.index(colname): -(a[colid] < b[colid]))
    178         else:
    179             ret.lines.sort(lambda b, a, colid = self.header.index(colname): -(a[colid] < b[colid]))
    180         return ret
    181 
    182     def Index(self, colname):
    183         if self in self.__immutable__:
    184             uthread.Lock(self, '__immutable__', colname)
    185             try:
    186                 if colname not in self.__immutable__[self][0]:
    187                     ret = IndexRowset(self.header, self.lines, colname)
    188                     self.__immutable__[self][0][colname] = ret
    189                     ret.MakeImmutable()
    190                 return self.__immutable__[self][0][colname]
    191             finally:
    192                 uthread.UnLock(self, '__immutable__', colname)
    193 
    194         else:
    195             return IndexRowset(self.header, self.lines, colname)
    196 
    197     def Filter(self, colname, colname2 = None):
    198         if self in self.__immutable__:
    199             k = (colname, colname2)
    200             uthread.Lock(self, '__immutable__', k)
    201             try:
    202                 if k not in self.__immutable__[self][1]:
    203                     ret = FilterRowset(self.header, self.lines, colname, idName2=colname2)
    204                     ret.MakeImmutable()
    205                     self.__immutable__[self][1][k] = ret
    206                 return self.__immutable__[self][1][k]
    207             finally:
    208                 uthread.UnLock(self, '__immutable__', k)
    209 
    210         else:
    211             return FilterRowset(self.header, self.lines, colname, idName2=colname2)
    212 
    213     def append(self, row):
    214         if self in self.__immutable__:
    215             raise RuntimeError('Immutable Rowsets may not be modified')
    216         if type(row) == type([]):
    217             if len(row) != len(self.header):
    218                 raise RuntimeError('Invalid row length for appending', self, row)
    219             self.lines.append(row)
    220         else:
    221             if len(self.header) != len(row.header):
    222                 raise RuntimeError('Invalid header for appending', self, row)
    223             self.lines.append(row.line)
    224 
    225 
    226 class IndexOrFilterRowsetIterator:
    227 
    228     def __init__(self, rowset, iterator):
    229         self.rowset = _weakref.proxy(rowset)
    230         self.iterator = iterator
    231 
    232     def next(self):
    233         return self.rowset.RowClass(self.rowset.header, self.iterator.next())
    234 
    235 
    236 class IndexRowset:
    237     __passbyvalue__ = 1
    238     __immutable__ = weakref.WeakKeyDictionary()
    239     RowClass = utilRow
    240     stacktraceCnt = 0
    241 
    242     def __init__(self, header = None, li = (), idName = None, RowClass = utilRow, dict = None):
    243         if dict is not None:
    244             self.items = dict
    245         elif header is not None and li is not None:
    246             idfield = header.index(idName)
    247             self.items = __builtin__.dict([ (i[idfield], i) for i in li ])
    248         else:
    249             self.items = {}
    250         self.header = header
    251         self.RowClass = RowClass
    252         self.idName = idName
    253 
    254     def GetKeyColumn(self):
    255         return self.idName
    256 
    257     def GetLine(self, key):
    258         return self.items[key]
    259 
    260     def Clone(self):
    261         return IndexRowset(copy.copy(self.header), None, self.idName, self.RowClass, copy.copy(self.items))
    262 
    263     def IsImmutable(self):
    264         return self in self.__immutable__
    265 
    266     def MakeImmutable(self):
    267         if self not in self.__immutable__:
    268             self.__immutable__[self] = 1
    269 
    270     def Select(self, *selection, **options):
    271         return Select(selection, self.header, self.items.itervalues(), options)
    272 
    273     def __iter__(self):
    274         return iter(self.items)
    275 
    276     def __contains__(self, key):
    277         return key in self.items
    278 
    279     def __getitem__(self, i):
    280         return self.RowClass(self.header, self.items[i])
    281 
    282     def __len__(self):
    283         return len(self.items)
    284 
    285     def values(self):
    286         return Rowset(self.header, self.items.values(), self.RowClass)
    287 
    288     def itervalues(self):
    289         return self.values()
    290 
    291     def keys(self):
    292         return self.items.keys()
    293 
    294     def iterkeys(self):
    295         return self.items.iterkeys()
    296 
    297     def iteritems(self):
    298         return self.items.iteritems()
    299 
    300     def has_key(self, key):
    301         return key in self.items
    302 
    303     def __setitem__(self, ind, row):
    304         if self in self.__immutable__:
    305             raise RuntimeError('Immutable IndexRowsets may not be modified')
    306         if type(row) == type([]):
    307             self.items[ind] = row
    308         else:
    309             if hasattr(row, '__columns__'):
    310                 rowHeader = row.__columns__
    311                 rowLine = list(row)
    312             else:
    313                 rowHeader = row.header
    314                 rowLine = row.line
    315             if len(self.header) != len(rowHeader):
    316                 line = [None] * len(self.header)
    317                 for i in range(len(self.header)):
    318                     cname = self.header[i]
    319                     try:
    320                         idx = rowHeader.index(cname)
    321                     except ValueError:
    322                         raise RuntimeError('Mismatched row headers - game is broken', self.header, rowHeader)
    323 
    324                     line[i] = rowLine[idx]
    325 
    326                 if self.stacktraceCnt < 2:
    327                     log.LogTraceback('rowset')
    328                     self.stacktraceCnt += 1
    329                 self.items[ind] = line
    330             else:
    331                 self.items[ind] = rowLine
    332 
    333     def __delitem__(self, ind):
    334         if self in self.__immutable__:
    335             raise RuntimeError('Immutable IndexRowsets may not be modified')
    336         del self.items[ind]
    337 
    338     def Sort(self, colname):
    339         ret = self.values()
    340         return ret.Sort(colname)
    341 
    342     def get(self, ind, defValue):
    343         try:
    344             return self[ind]
    345         except:
    346             sys.exc_clear()
    347             return defValue
    348 
    349     def UpdateLI(self, lines, indexName, overWrite = 0):
    350         if self in self.__immutable__:
    351             raise RuntimeError('Immutable IndexRowsets may not be modified')
    352         ind = self.header.index(indexName)
    353         for i in lines:
    354             if not (not overWrite and i[ind] in self.items):
    355                 self.items[i[ind]] = i
    356 
    357     def Map(self, indexes):
    358         ret = Rowset(self.header, [])
    359         for i in indexes:
    360             if i in self:
    361                 ret.append(self[i])
    362 
    363         return ret
    364 
    365     def __str__(self):
    366         stuff = {}
    367         for key in self.iterkeys():
    368             eachRow = self[key]
    369             stuff[key] = eachRow
    370 
    371         return '<IndexRowset: header=%s, data=' % strx(self.header) + strx(stuff).replace('"', '') + '>'
    372 
    373 
    374 class FilterRowset:
    375     __guid__ = 'util.FilterRowset'
    376     __passbyvalue__ = 1
    377     __immutable__ = weakref.WeakKeyDictionary()
    378     RowClass = utilRow
    379 
    380     def __init__(self, header = None, li = None, idName = None, RowClass = utilRow, idName2 = None, dict = None):
    381         items = {}
    382         self.RowClass = RowClass
    383         if dict is not None:
    384             items = dict
    385         elif header is not None:
    386             if not idName2:
    387                 idfield = header.index(idName)
    388                 for i in li:
    389                     id = i[idfield]
    390                     if id in items:
    391                         items[id].append(i)
    392                     else:
    393                         items[id] = [i]
    394 
    395             else:
    396                 idfield = header.index(idName)
    397                 idfield2 = header.index(idName2)
    398                 for i in li:
    399                     id = i[idfield]
    400                     if id in items:
    401                         items[id][i[idfield2]] = i
    402                     else:
    403                         items[id] = {i[idfield2]: i}
    404 
    405         self.items = items
    406         self.header = header
    407         self.idName = idName
    408         self.idName2 = idName2
    409 
    410     def Clone(self):
    411         return FilterRowset(copy.copy(self.header), None, self.idName, self.RowClass, self.idName2, dict=copy.deepcopy(self.items))
    412 
    413     def IsImmutable(self):
    414         return self in self.__immutable__
    415 
    416     def MakeImmutable(self):
    417         if self not in self.__immutable__:
    418             self.__immutable__[self] = 1
    419 
    420     def __iter__(self):
    421         return IndexOrFilterRowsetIterator(self, self.items.iterkeys())
    422 
    423     def __contains__(self, key):
    424         return key in self.items
    425 
    426     def has_key(self, key):
    427         return key in self.items
    428 
    429     def get(self, key, val):
    430         try:
    431             return self[key]
    432         except:
    433             sys.exc_clear()
    434             return val
    435 
    436     def keys(self):
    437         return self.items.keys()
    438 
    439     def iterkeys(self):
    440         return self.items.iterkeys()
    441 
    442     def __getitem__(self, i):
    443         if self.idName2:
    444             return IndexRowset(self.header, None, self.idName2, self.RowClass, self.items.get(i, {}))
    445         return Rowset(self.header, self.items.get(i, []), self.RowClass)
    446 
    447     def __len__(self):
    448         return len(self.items)
    449 
    450     def Sort(self, colname):
    451         ret = Rowset(self.header, self.items.values(), self.RowClass)
    452         return ret.Sort(colname)
    453 
    454     def GetIndexKeys(self):
    455         if self.idName2 is not None:
    456             return (self.idName, self.idName2)
    457         return (self.idName,)
    458 
    459     def GetLines(self, idValue, idValue2 = None):
    460         if self.idName2 is not None:
    461             return self.items[idValue][idValue2]
    462         return self.items[idValue]
    463 
    464 
    465 def RowsInit(rows, columns):
    466     header = None
    467     if type(rows) is types.TupleType:
    468         header = rows[0]
    469         rows = rows[1]
    470     if rows:
    471         first = rows[0]
    472         if type(first) != blue.DBRow:
    473             raise AttributeError('Not DBRow. Initialization requires a non-empty list of DBRows')
    474         header = first.__header__
    475     elif header:
    476         if type(header) != blue.DBRowDescriptor:
    477             raise AttributeError('expected (DBRowDesciptor, [])')
    478     if header:
    479         columns = header.Keys()
    480     return (rows, columns, header)
    481 
    482 
    483 class RowDict(dict):
    484     __guid__ = 'dbutil.RowDict'
    485     __passbyvalue__ = 1
    486     slots = ['columns', 'header', 'key']
    487 
    488     def __init__(self, rowList, key, columns = None):
    489         dict.__init__(self)
    490         rows, self.columns, self.header = RowsInit(rowList, columns)
    491         if key not in self.columns:
    492             raise AttributeError('Indexing key not found in row')
    493         self.key = key
    494         for row in rows:
    495             self[row[key]] = row
    496 
    497     def ReIndex(self, key):
    498         if key not in self.columns:
    499             raise AttributeError('Indexing key not found in columns')
    500         vals = self.values()
    501         self.clear()
    502         self.key = key
    503         for row in vals:
    504             self[row[self.key]] = row
    505 
    506     def Add(self, row):
    507         if type(row) != blue.DBRow:
    508             raise AttributeError('Not DBRow')
    509         if row.__columns__ != self.columns:
    510             raise ValueError('Incompatible rows')
    511         if self.header is None:
    512             self.header = row.__header__
    513         self[row[self.key]] = row
    514 
    515 
    516 class RowList(list):
    517     __guid__ = 'dbutil.RowList'
    518     __passbyvalue__ = 1
    519     slots = ['header', 'columns']
    520 
    521     def __init__(self, rowList, columns = None):
    522         list.__init__(self)
    523         rows, self.columns, self.header = RowsInit(rowList, columns)
    524         self[:] = rows
    525 
    526     def append(self, row):
    527         if type(row) != blue.DBRow:
    528             raise ValueError('Not DBRow')
    529         if row.__columns__ != self.columns:
    530             raise ValueError('Incompatible headers')
    531         if self.header is None:
    532             self.header = row.__header__
    533         list.append(self, row)
    534 
    535 
    536 class IndexedRows(dict):
    537     __guid__ = 'util.IndexedRows'
    538     __passbyvalue__ = 1
    539 
    540     def __init__(self, rows = [], keys = None):
    541         self.InsertMany(keys, rows)
    542 
    543     def InsertMany(self, keys, rows):
    544         for r in rows:
    545             self.Insert(keys, r)
    546 
    547     def Insert(self, keys, e):
    548         key, rkeys = keys[0], keys[1:]
    549         if rkeys:
    550             if e[key] not in self:
    551                 self[e[key]] = IndexedRows()
    552             self[e[key]].Insert(rkeys, e)
    553         else:
    554             self[e[key]] = e
    555 
    556 
    557 class IndexedRowLists(dict):
    558     __guid__ = 'util.IndexedRowLists'
    559     __passbyvalue__ = 1
    560 
    561     def __init__(self, rows = [], keys = None):
    562         self.header = []
    563         self.InsertMany(keys, rows)
    564 
    565     def InsertMany(self, keys, rows):
    566         for r in rows:
    567             self.Insert(keys, r)
    568 
    569     def Insert(self, keys, e):
    570         key, rkeys = keys[0], keys[1:]
    571         self.header = [key]
    572         if rkeys:
    573             if e[key] not in self:
    574                 self[e[key]] = IndexedRowLists()
    575             self[e[key]].Insert(rkeys, e)
    576         else:
    577             if e[key] not in self:
    578                 self[e[key]] = []
    579             self[e[key]].append(e)
    580 
    581     def GetIndexKeys(self):
    582         l = self.header[:]
    583         for v in self.itervalues():
    584             if isinstance(v, self.__class__):
    585                 l.extend(v.GetIndexKeys())
    586             break
    587 
    588         return l
    589 
    590     def GetLines(self, firstKey, *nextKeys):
    591         ret = self[firstKey]
    592         if len(nextKeys):
    593             return ret.GetLines(*nextKeys)
    594         return ret