__init__.py

Go to the documentation of this file.
00001 __copyright__ = """\
00002 (c). Copyright 1990-2008, Vyper Logix Corp., All Rights Reserved.
00003 
00004 Published under Creative Commons License 
00005 (http://creativecommons.org/licenses/by-nc/3.0/) 
00006 restricted to non-commercial educational use only., 
00007 
00008 See also: http://www.VyperLogix.com and http://www.pypi.info for details.
00009 
00010 THE AUTHOR VYPER LOGIX CORP DISCLAIMS ALL WARRANTIES WITH REGARD TO
00011 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
00012 FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
00013 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
00014 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
00015 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
00016 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
00017 
00018 USE AT YOUR OWN RISK.
00019 """
00020 
00021 import os
00022 import sys
00023 import uuid
00024 import bsddb
00025 import shelve
00026 import types
00027 import marshal
00028 import struct
00029 import re
00030 import pylzma
00031 
00032 from struct import pack, unpack
00033 import zlib
00034 
00035 from vyperlogix.hash.lists import HashedLists
00036 from vyperlogix.hash.lists import HashedLists2
00037 try:
00038     from pyax.datatype.apexdatetime import ApexDatetime
00039 except ImportError:
00040     from datetime import datetime as ApexDatetime
00041 import traceback
00042 from vyperlogix.enum.Enum import *
00043 from vyperlogix.classes import CooperativeClass
00044 from vyperlogix.misc import _utils
00045 from vyperlogix import misc
00046 from vyperlogix.misc import ObjectTypeName
00047 from vyperlogix.misc.ObjectTypeName import __typeName as ObjectTypeName__typeName
00048 from vyperlogix.hash import lists
00049 
00050 from vyperlogix import cerealizer
00051 
00052 try:
00053     from cPickle import Pickler, Unpickler
00054 except ImportError:
00055     from pickle import Pickler, Unpickler
00056 
00057 try:
00058     from cStringIO import StringIO
00059 except ImportError:
00060     from StringIO import StringIO
00061 
00062 dbx_name = lambda name,data_path:os.sep.join([data_path,'.'.join([os.path.basename(name.split('.')[0]),'dbx'])])
00063 
00064 ##
00065 # 
00066 #         Encrypt/decrypt variable length string using XTEA cypher as
00067 #         key generator (OFB mode)
00068 #         * key = 128 bit (16 char) 
00069 #         * iv = 64 bit (8 char)
00070 #         * data = string (any length)
00071 # 
00072 #         >>> import os
00073 #         >>> key = os.urandom(16)
00074 #         >>> iv = os.urandom(8)
00075 #         >>> data = os.urandom(10000)
00076 #         >>> z = crypt(key,data,iv)
00077 #         >>> crypt(key,z,iv) == data
00078 #         True
00079 # 
00080 #     
00081 def crypt(key,data,iv='\00\00\00\00\00\00\00\00',n=32):
00082     def keygen(key,iv,n):
00083         while True:
00084             iv = xtea_encrypt(key,iv,n)
00085             for k in iv:
00086                 yield ord(k)
00087     xor = [ chr(x^y) for (x,y) in zip(map(ord,data),keygen(key,iv,n)) ]
00088     return "".join(xor)
00089 
00090 ##
00091 # 
00092 #         Encrypt 64 bit data block using XTEA block cypher
00093 #         * key = 128 bit (16 char) 
00094 #         * block = 64 bit (8 char)
00095 #         * n = rounds (default 32)
00096 #         * endian = byte order (see 'struct' doc - default big/network) 
00097 # 
00098 #         >>> z = xtea_encrypt('0123456789012345','ABCDEFGH')
00099 #         >>> z.encode('hex')
00100 #         'b67c01662ff6964a'
00101 # 
00102 #         Only need to change byte order if sending/receiving from 
00103 #         alternative endian implementation 
00104 # 
00105 #         >>> z = xtea_encrypt('0123456789012345','ABCDEFGH',endian="<")
00106 #         >>> z.encode('hex')
00107 #         'ea0c3d7c1c22557f'
00108 # 
00109 #     
00110 def xtea_encrypt(key,block,n=32,endian="!"):
00111     v0,v1 = struct.unpack(endian+"2L",block)
00112     k = struct.unpack(endian+"4L",key)
00113     sum,delta,mask = 0L,0x9e3779b9L,0xffffffffL
00114     for round in range(n):
00115         v0 = (v0 + (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
00116         sum = (sum + delta) & mask
00117         v1 = (v1 + (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
00118     return struct.pack(endian+"2L",v0,v1)
00119 
00120 ##
00121 # 
00122 #         Decrypt 64 bit data block using XTEA block cypher
00123 #         * key = 128 bit (16 char) 
00124 #         * block = 64 bit (8 char)
00125 #         * n = rounds (default 32)
00126 #         * endian = byte order (see 'struct' doc - default big/network) 
00127 # 
00128 #         >>> z = 'b67c01662ff6964a'.decode('hex')
00129 #         >>> xtea_decrypt('0123456789012345',z)
00130 #         'ABCDEFGH'
00131 # 
00132 #         Only need to change byte order if sending/receiving from 
00133 #         alternative endian implementation 
00134 # 
00135 #         >>> z = 'ea0c3d7c1c22557f'.decode('hex')
00136 #         >>> xtea_decrypt('0123456789012345',z,endian="<")
00137 #         'ABCDEFGH'
00138 # 
00139 #     
00140 def xtea_decrypt(key,block,n=32,endian="!"):
00141     v0,v1 = struct.unpack(endian+"2L",block)
00142     k = struct.unpack(endian+"4L",key)
00143     delta,mask = 0x9e3779b9L,0xffffffffL
00144     sum = (delta * n) & mask
00145     for round in range(n):
00146         v1 = (v1 - (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
00147         sum = (sum - delta) & mask
00148         v0 = (v0 - (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
00149     return struct.pack(endian+"2L",v0,v1)
00150 
00151 const_class_symbol = '__class__'
00152 
00153 def unique(items):
00154     d = {}
00155     for item in items:
00156         d[item] = 1
00157     return d.keys()
00158 
00159 def fileSize(fname):
00160     statinfo = os.stat(fname)
00161     return statinfo.st_size
00162 
00163 def fullClassName(obj):
00164     return str(type(obj)).split("'")[1]
00165 
00166 def terseClassName(sClassName):
00167     if (misc.isString(sClassName)):
00168         return sClassName.split('.')[-1]
00169     return ''
00170 
00171 def obj2Dict(obj):
00172     d = {}
00173     d[const_class_symbol] = fullClassName(obj)
00174     spam = '_%s' % terseClassName(d[const_class_symbol])
00175     try:
00176         for k,v in obj.__dict__.iteritems():
00177             d[k.replace(spam,'')] = v
00178     except:
00179         o = [n for n in obj]
00180         o.insert(0,type(obj))
00181         return obj2Dict(o)
00182     return d
00183 
00184 def dict2Obj(value):
00185     obj = value
00186     if (isinstance(value,dict)):
00187         if (value.has_key(const_class_symbol)):
00188             cname = value[const_class_symbol]
00189             try:
00190                 toks = cname.split('.')
00191                 s = 'from %s import %s\nobj=%s()' % (toks[0],'.'.join(toks[1:-1]),'.'.join(toks[1:]))
00192                 exec(s)
00193             except:
00194                 obj = None
00195             if (obj):
00196                 for k in [n for n in value.keys() if n != const_class_symbol]:
00197                     if not n.startswith('__'):
00198                         _k = '_%s' % toks[-1]
00199                     else:
00200                         _k = '%s' % (k)
00201                     try:
00202                         isQuoted = misc.isString(value[k])
00203                         _quote = '"' if isQuoted else ''
00204                         s = 'obj.%s=%s%s%s' % (_k.replace('__',''),_quote,value[k],_quote)
00205                         exec(s)
00206                     except AttributeError:
00207                         pass
00208     return obj
00209 
00210 def isAnyAlphaNumeric(token):
00211     for t in token:
00212         if (t.isalnum()):
00213             return True
00214     return False
00215 
00216 def isAllNonAlphaNumeric(token):
00217     for t in token:
00218         if (t.isalnum()):
00219             return False
00220     return True
00221 
00222 # change a hexadecimal string to decimal number and reverse
00223 # check two different representations of the hexadecimal string
00224 # negative values and zero are accepted
00225 
00226 ##
00227 # return the hexadecimal string representation of integer n
00228 def dec2hex(n):
00229     val = '0%X' % n
00230     return val[len(val)-2:]
00231 
00232 ##
00233 # return the integer value of a hexadecimal string s
00234 def hex2dec(s):
00235     return int(s, 16)
00236 
00237 hex_digits = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f']
00238 
00239 def isHexDigits(s):
00240     if (len(s) > 1):
00241         for ch in s:
00242             if (not ch in hex_digits):
00243                 return False
00244         return True
00245     return s in hex_digits
00246 
00247 _base2hex = [(i,dec2hex(i)) for i in xrange(0,256)]
00248 
00249 d_dec2hex = dict(_base2hex)
00250 
00251 d_chr2hex = dict([(chr(t[0]),t[-1]) for t in _base2hex])
00252 
00253 d_hex2dec = lists.asDict(d_dec2hex,insideOut=True)
00254 
00255 def __init_data__():
00256     for k,v in d_hex2dec.iteritems():
00257         d_hex2dec[k] = chr(v)
00258 __init_data__()
00259 
00260 def strToHex(str):
00261     return ''.join([d_chr2hex[ch] for ch in str])
00262 
00263 def hexToStr(hex):
00264     return ''.join([d_hex2dec[hex[i:i+2]] for i in xrange(0,len(hex),2)])
00265 
00266 from types import (
00267     IntType, TupleType, StringType,
00268     FloatType, LongType, ListType,
00269     DictType, NoneType, BooleanType, UnicodeType
00270 )
00271 
00272 class EncodeError(Exception): pass
00273 class DecodeError(Exception): pass
00274 
00275 class CompressionOption(Enum):
00276     no_compression = 0
00277     compression = 1
00278 
00279 HEADER = "SRW3"
00280 
00281 protocol = {
00282     TupleType          :"T",
00283     ListType           :"L",
00284     DictType           :"D",
00285     lists.HashedLists2 :"D",
00286     LongType           :"B",
00287     IntType            :"I",
00288     FloatType          :"F",
00289     StringType         :"S",
00290     ApexDatetime       :"a",
00291     NoneType           :"N",
00292     BooleanType        :"b",
00293     UnicodeType        :"U"
00294 }
00295 
00296 encoder = {}
00297 ##
00298 # Registers an encoder function, for a type, in the global encoder dictionary.
00299 class register_encoder_for_type(object):
00300     def __init__(self, t):
00301         self.type = t
00302     def __call__(self, func):
00303         encoder[self.type] = func
00304         return func
00305 
00306 #contains dictionary of decoding functions, where the dictionary key is the type prefix used.
00307 decoder = {}
00308 ##
00309 # Registers a decoder function, for a prefix, in the global decoder dictionary.
00310 class register_decoder_for_type(object):
00311     def __init__(self, t):
00312         self.prefix = protocol[t]
00313     def __call__(self, func):
00314         decoder[self.prefix] = func
00315         return func
00316 
00317 ## <encoding functions> ##
00318 @register_encoder_for_type(DictType)
00319 @register_encoder_for_type(lists.HashedLists2)
00320 def enc_dict_type(obj):
00321     data = "".join([encoder[type(i)](i) for i in obj.items()])
00322     return "%s%s%s" % (protocol[type(obj)], pack("!L", len(data)), data)
00323 
00324 @register_encoder_for_type(TupleType)
00325 @register_encoder_for_type(ListType)
00326 def enc_list_type(obj):
00327     data = "".join([encoder[type(i)](i) for i in obj])
00328     return "%s%s%s" % (protocol[type(obj)], pack("!L", len(data)), data)
00329 
00330 @register_encoder_for_type(IntType)
00331 def enc_int_type(obj):
00332     return "%s%s" % (protocol[IntType], pack("!i", obj))
00333 
00334 @register_encoder_for_type(FloatType)
00335 def enc_float_type(obj):
00336     return "%s%s" % (protocol[FloatType], pack("!d", obj))
00337 
00338 @register_encoder_for_type(LongType)
00339 def enc_long_type(obj):
00340     obj = hex(obj)[2:-1]
00341     return "%s%s%s" % (protocol[LongType], pack("!L", len(obj)), obj)
00342 
00343 @register_encoder_for_type(UnicodeType)
00344 def enc_unicode_type(obj):
00345     obj = obj.encode('utf-8')
00346     return "%s%s%s" % (protocol[UnicodeType], pack("!L", len(obj)), obj)
00347 
00348 @register_encoder_for_type(StringType)
00349 def enc_string_type(obj):
00350     return "%s%s%s" % (protocol[StringType], pack("!L", len(obj)), obj)
00351 
00352 @register_encoder_for_type(ApexDatetime)
00353 def enc_apex_datetime_type(obj):
00354     obj = str(obj)
00355     return "%s%s%s" % (protocol[ApexDatetime], pack("!L", len(obj)), obj)
00356 
00357 @register_encoder_for_type(NoneType)
00358 def enc_none_type(obj):
00359     return protocol[NoneType]
00360 
00361 @register_encoder_for_type(BooleanType)
00362 def enc_bool_type(obj):
00363     return protocol[BooleanType] + str(int(obj))
00364 
00365 ##
00366 # Encode simple Python types into a binary string.
00367 def dumps(obj, compress=CompressionOption.no_compression, phase=1):
00368     option = "N" if compress.value == CompressionOption.no_compression.value else "Z"
00369     try:
00370         data = encoder[type(obj)](obj)
00371         if compress.value == CompressionOption.compression.value: data = zlib.compress(data)
00372         return "%s%s%s" % (HEADER, option, data)
00373     except KeyError, e:
00374         if (phase == 1):
00375             try:
00376                 data = obj2Dict(obj)
00377                 return dumps(data,compress,phase+1)
00378             except:
00379                 raise EncodeError, "Type not supported. (%s) during phase #%2d" % (e,phase)
00380         else:
00381             raise EncodeError, "Type not supported. (%s) during phase #%2d" % (e,phase)
00382 ## </encoding functions> ##
00383 
00384 ## <decoding functions> ##
00385 def build_sequence(data, cast=list):
00386     size = unpack('!L', data.read(4))[0]
00387     items = []
00388     data_tell = data.tell
00389     data_read = data.read
00390     items_append = items.append
00391     start_position = data.tell()
00392     while (data_tell() - start_position) < size:
00393         T = data_read(1)
00394         value = decoder[T](data)
00395         items_append(value)
00396     return cast(items)
00397 
00398 @register_decoder_for_type(TupleType)
00399 def dec_tuple_type(data):
00400     return build_sequence(data, cast=tuple)
00401 
00402 @register_decoder_for_type(ListType)
00403 def dec_list_type(data):
00404     return build_sequence(data, cast=list)
00405 
00406 @register_decoder_for_type(DictType)
00407 def dec_dict_type(data):
00408     return build_sequence(data, cast=dict)
00409 
00410 @register_decoder_for_type(lists.HashedLists2)
00411 def dec_HashedLists2_type(data):
00412     return build_sequence(data, cast=lists.HashedLists2)
00413 
00414 @register_decoder_for_type(LongType)
00415 def dec_long_type(data):
00416     size = unpack('!L', data.read(4))[0]
00417     value = long(data.read(size),16)
00418     return value
00419 
00420 @register_decoder_for_type(StringType)
00421 def dec_string_type(data):
00422     size = unpack('!L', data.read(4))[0]
00423     value = str(data.read(size))
00424     return value
00425 
00426 @register_decoder_for_type(ApexDatetime)
00427 def dec_apex_datetime_type(data):
00428     value = dec_string_type(data)
00429     return ApexDatetime.fromSfIso(value.split('+')[0])
00430 
00431 @register_decoder_for_type(FloatType)
00432 def dec_float_type(data):
00433     value = unpack('!d', data.read(8))[0]
00434     return value
00435 
00436 @register_decoder_for_type(IntType)
00437 def dec_int_type(data):
00438     value = unpack('!i', data.read(4))[0]
00439     return value
00440 
00441 @register_decoder_for_type(NoneType)
00442 def dec_none_type(data):
00443     return None
00444 
00445 @register_decoder_for_type(BooleanType)
00446 def dec_bool_type(data):
00447     value = int(data.read(1))
00448     return bool(value)
00449 
00450 @register_decoder_for_type(UnicodeType)
00451 def dec_unicode_type(data):
00452     size = unpack('!L', data.read(4))[0]
00453     value = data.read(size).decode('utf-8')
00454     return value
00455 
00456 ##
00457 # 
00458 #     Decode a binary string into the original Python types.
00459 #     
00460 def loads(data,beSilent=False):
00461     buffer = StringIO(data)
00462     header = buffer.read(len(HEADER))
00463     if (not beSilent):
00464         assert header == HEADER
00465     option = buffer.read(1)
00466     decompress = False
00467     if option == "Z":
00468         buffer = StringIO(zlib.decompress(buffer.read()))
00469     try:
00470         value = decoder[buffer.read(1)](buffer)
00471     except KeyError, e:
00472         raise DecodeError, "Type prefix not supported. (%s)" % e
00473 
00474     value = dict2Obj(value)
00475     return value
00476 ## </decoding functions> ##
00477 
00478 class PickleMethods(Enum):
00479     none = 0
00480     useBsdDbShelf = 2**0
00481     useStrings = 2**1
00482     useMarshal = 2**2
00483     useSafeSerializer = 2**3 # (+++) this is very slow !  Make this run faster !
00484     useSimpleJSon = 2**4
00485     useCerealizer = 2**5
00486     useLegacyFileMode = 2**10 # this performs no filename munging - takes the filename given and opens it...
00487     use_lzma = 2**14
00488     use_zlib = 2**15
00489 
00490 class NormalizedKeyOptions(Enum):
00491     via_list = 0
00492     via_dict = 1
00493     use_hash1 = 2**14
00494     use_hash2 = 2**15
00495 
00496 _class_tag = lambda name:''.join([ch for ch in name if (ch.isupper()) or (ch.isdigit())])
00497 class_tag = lambda cls:_class_tag(ObjectTypeName__typeName(cls))
00498 
00499 unlistify = lambda item:item if (not misc.isList(item)) else item[0]
00500 
00501 ##
00502 # PickledHash is a persistent hash with unique keys, see PickledHash2 for the persistent hash that handles duplicated keys with lists for values.
00503 # 
00504 #     dbx = PickledHash(fileName, method=PickleMethods.useStrings)
00505 # 
00506 #     PickleMethods.useBsdDbShelf     = 54x
00507 #     PickleMethods.useStrings        = 26x
00508 #     PickleMethods.useSafeSerializer = 4x
00509 #     PickleMethods.useMarshal        = 1x
00510 #     
00511 class PickledHash(CooperativeClass.Cooperative):
00512     def __init__(self, fileName, method=PickleMethods.useStrings):
00513         from vyperlogix.crypto.Encryptors import Encryptors
00514         self.__method = method
00515         self.__isPickleMethodUseStrings = ((method.value & PickleMethods.useStrings.value) != 0)
00516         self.__isPickleMethodUseLZMA = ((method.value & PickleMethods.use_lzma.value) != 0)
00517         self.__isPickleMethodUseBsdDbShelf = ((method.value & PickleMethods.useBsdDbShelf.value) != 0)
00518         self.__isPickleMethodUseMarshal = ((method.value & PickleMethods.useMarshal.value) != 0)
00519         self.__isPickleMethodUseSafeSerializer = ((method.value & PickleMethods.useSafeSerializer.value) != 0)
00520         self.__isPickleMethodUseCerealizer = ((method.value & PickleMethods.useCerealizer.value) != 0)
00521         self.__isPickleMethodUseSimpleJSon = ((method.value & PickleMethods.useSimpleJSon.value) != 0)
00522         self.__isPickleMethodUseZLIB = (not self.isPickleMethodUseLZMA) and ((method.value & PickleMethods.use_zlib.value) != 0)
00523         self.__isPickleMethodUseLegacyFileMode = ((method.value & PickleMethods.useLegacyFileMode.value) != 0)
00524 
00525         self.__fileName = fileName
00526         if (not self.isPickleMethodUseLegacyFileMode) and (not isFilenameMungedAlready(fileName)):
00527             self.__fileName = self.tag_filename(fileName)
00528         self.__isOpened = False
00529 
00530         self.open()
00531 
00532     def tag_classname(self):
00533         return class_tag(self)
00534 
00535     def tag_filename(self, fname):
00536         return '%s%s%s_%s.%s' % (os.path.dirname(fname),os.sep,os.path.basename(fname).split('.')[0],self.tag_classname(),os.path.basename(fname).split('.')[-1])
00537 
00538     def __repr__(self):
00539         return '(%s) on "%s" storing %d keys using the "%s" method; issue the appropriate method to turn this object into the string you want this to be however there may be a lot of date once this is done.' % (str(self.__class__),self.fileName,len(self.keys()),str(self.method))
00540 
00541     def method():
00542         doc = "method"
00543         def fget(self):
00544             return self.__method
00545         return locals()
00546     method = property(**method())
00547 
00548     def isOpened():
00549         doc = "isOpened"
00550         def fget(self):
00551             return self.__isOpened
00552         return locals()
00553     isOpened = property(**isOpened())
00554 
00555     def fileName():
00556         doc = "fileName"
00557         def fget(self):
00558             return self.__fileName
00559         return locals()
00560     fileName = property(**fileName())
00561 
00562     def db():
00563         doc = "db"
00564         def fget(self):
00565             return self.__db
00566         return locals()
00567     db = property(**db())
00568 
00569     def unPickleItem(self,glob):
00570         return Unpickler(StringIO(glob)).load()
00571 
00572     def pickleItem(self,glob):
00573         io = StringIO()
00574         Pickler(io, -1).dump(glob)
00575         return io.getvalue()
00576 
00577     def unlistify(self,item):
00578         return unlistify(item)
00579 
00580     def __getitem__(self, key):
00581         from vyperlogix.crypto.Encryptors import Encryptors
00582         try:
00583             val = self.__db[key]
00584             if (not self.isPickleMethodUseSafeSerializer):
00585                 if (self.isPickleMethodUseZLIB):
00586                     val = zlib.decompress(val)
00587                 elif (self.isPickleMethodUseLZMA):
00588                     val = pylzma.decompress(val)
00589             if (self.isPickleMethodUseStrings):
00590                 val = val.split(',')
00591                 if (len(val) > 1):
00592                     val = [tuple(x.split('|')) if x.find('|') > -1 else x for x in val]
00593             elif (self.isPickleMethodUseBsdDbShelf):
00594                 val = self.unPickleItem(val)
00595             elif (self.isPickleMethodUseMarshal):
00596                 val = marshal.loads(hexToStr(val))
00597             elif (self.isPickleMethodUseSafeSerializer):
00598                 try:
00599                     val = loads(val,beSilent=True)
00600                 except:
00601                     pass
00602                 if (isinstance(val,dict)):
00603                     d_val = HashedLists2()
00604                     d_val.fromDict(val)
00605                     val = d_val
00606             elif (self.isPickleMethodUseCerealizer):
00607                 val = cerealizer.loads(val)
00608         except Exception, details:
00609             val = 'UNKNOWN value for key (%s) of type "%s" due to ERROR "%s".' % (key,str(key.__class__),str(details))
00610         return val
00611 
00612     def __setitem__(self, key, value):
00613         from vyperlogix.crypto.Encryptors import Encryptors
00614         from vyperlogix.misc import GenPasswd
00615 
00616         key = key if (misc.isString(key)) else str(key)
00617         if (self.has_key(key)) and (value == None):
00618             self.__delitem__(key)
00619         else:
00620             if (misc.isList(value)):
00621                 value = [v if (not lists.can_asDict(v)) else v.asDict() for v in value]
00622             else:
00623                 value = value if (not lists.can_asDict(value)) else value.asDict()
00624             if (self.isPickleMethodUseStrings):
00625                 if (not misc.isString(value)):
00626                     if not misc.isList(value):
00627                         value = list(value) if (not isinstance(value,dict)) else [(k,v) for k,v in value.iteritems()]
00628                     val = ['|'.join([str(x) for x in v]) if isinstance(v,tuple) else str(v) for v in value]
00629                     if (len(val) > 0):
00630                         value = ','.join(val) if (len(val) > 1) else val[0]
00631                     else:
00632                         value = ''
00633             elif (self.isPickleMethodUseMarshal):
00634                 value = strToHex(marshal.dumps(value,2))
00635             elif (self.isPickleMethodUseBsdDbShelf):
00636                 value = self.pickleItem(value)
00637             elif (self.isPickleMethodUseSafeSerializer):
00638                 value = dumps(value,CompressionOption.compression)
00639             elif (self.isPickleMethodUseCerealizer):
00640                 #cls = eval(ObjectTypeName.typeClassName(value))
00641                 #if (not cerealizer.isRegistered(cls)):
00642                     #cerealizer.register(cls)
00643                 value = cerealizer.dumps(value)
00644             if (not self.isPickleMethodUseSafeSerializer):
00645                 if (self.isPickleMethodUseZLIB):
00646                     value = zlib.compress(value,zlib.Z_BEST_COMPRESSION)
00647                 elif (self.isPickleMethodUseLZMA):
00648                     value = pylzma.compress(value, eos=1)
00649             self.__db[key] = value
00650 
00651     def __delitem__(self, key):
00652         del self.__db[key]
00653 
00654     def __str__(self):
00655         return self.__repr__()
00656 
00657     def __len__(self):
00658         return len(self.keys())
00659 
00660     def has_key(self, key):
00661         return self.__db.has_key(key)
00662 
00663     def keys(self):
00664         try:
00665             return self.__db.keys()
00666         except:
00667             pass
00668         return []
00669 
00670     def values(self):
00671         try:
00672             return self.__db.values()
00673         except:
00674             pass
00675         return []
00676 
00677     ##
00678     # 
00679     #   Get a list of keys sorted in a fashion that allows for easier manipulation - 
00680     #   padded or normalized to allow sorting to work.
00681     # 
00682     #   options = see also NormalizedKeyOptions enumeration
00683     #   
00684     def normalizedSortedKeys(self,options=NormalizedKeyOptions.via_list):
00685         from vyperlogix.hash import lists
00686 
00687         try:
00688             _asDict = options.value & NormalizedKeyOptions.via_dict.value
00689         except:
00690             _asDict = False
00691 
00692         try:
00693             _useHash1 = options.value & NormalizedKeyOptions.use_hash1.value
00694         except:
00695             _asDict = False
00696             _useHash1 = False
00697 
00698         try:
00699             _useHash2 = options.value & NormalizedKeyOptions.use_hash2.value
00700         except:
00701             _useHash2 = False
00702 
00703         _useHash2 = ( (not _useHash1) and (not _useHash2) ) or _useHash2
00704         _useHash1 = False if (_useHash1 and _useHash2) else _useHash1
00705 
00706         d_keys = lists.HashedLists() if _useHash1 else lists.HashedLists2() if _useHash2 else {}
00707 
00708         def normalizeKey(k,m):
00709             toks = k.split(',')
00710             n = toks[0]
00711             del toks[0]
00712             getLen = lambda m,n:m-len(n)
00713             formatter = lambda p,m,n,f:p % (' '*getLen(m,n),f(n))
00714             _value = ''
00715             _isString = (misc.isString(n))
00716             _pattern = '%s%s' if _isString else '%s%d'
00717             _func = str if _isString else int
00718             _value = formatter(_pattern,m,n,_func)
00719             toks.insert(0,_value)
00720             s = ','.join(toks)
00721             if (_asDict):
00722                 d_keys[s] = k
00723             return s
00724 
00725         l_keys = [len(k.split(',')[0]) for k in self.keys()]
00726         l_keys.sort()
00727         _max_len = l_keys[-1] if len(l_keys) > 0 else 0
00728         _keys = [normalizeKey(k,_max_len) for k in self.keys()]
00729         _keys.sort()
00730         _keys.reverse()
00731         return _keys if (not _asDict) else d_keys
00732 
00733     def sync(self):
00734         if (self.isOpened):
00735             self.__db.sync()
00736 
00737     def flush(self):
00738         self.sync()
00739 
00740     def iteritems(self):
00741         return ((k,self.__getitem__(k)) for k in self.keys())
00742 
00743     def close(self):
00744         if (self.isOpened):
00745             self.__db.close()
00746             self.__isOpened = False
00747 
00748     def queryANDitems(self,*args):
00749         recs = set()
00750         for arg in args:
00751             items = []
00752             if (self.has_key(arg)):
00753                 items = self[arg]
00754                 if (not misc.isList(items)):
00755                     items = [items]
00756             items = set(items)
00757             if len(recs) == 0:
00758                 recs = items
00759             else:
00760                 recs &= items
00761         return list(recs)
00762 
00763     def queryMostlyANDitems(self,*args):
00764         recs = set()
00765         for arg in args:
00766             items = []
00767             if (self.has_key(arg)):
00768                 items = self[arg]
00769                 if (not misc.isList(items)):
00770                     items = [items]
00771             items = set(items)
00772             if len(recs) == 0:
00773                 recs = items
00774             elif len(recs & items) > 0:
00775                 recs &= items
00776         return list(recs)
00777 
00778     def isPickleMethodUseStrings():
00779         doc = "isPickleMethodUseStrings boolean"
00780         def fget(self):
00781             return self.__isPickleMethodUseStrings
00782         return locals()
00783     isPickleMethodUseStrings = property(**isPickleMethodUseStrings())
00784 
00785     def isPickleMethodUseBsdDbShelf():
00786         doc = "isPickleMethodUseBsdDbShelf boolean"
00787         def fget(self):
00788             return self.__isPickleMethodUseBsdDbShelf
00789         return locals()
00790     isPickleMethodUseBsdDbShelf = property(**isPickleMethodUseBsdDbShelf())
00791 
00792     def isPickleMethodUseLZMA():
00793         doc = "isPickleMethodUseLZMA boolean"
00794         def fget(self):
00795             return self.__isPickleMethodUseLZMA
00796         return locals()
00797     isPickleMethodUseLZMA = property(**isPickleMethodUseLZMA())
00798 
00799     def isPickleMethodUseMarshal():
00800         doc = "isPickleMethodUseMarshal boolean"
00801         def fget(self):
00802             return self.__isPickleMethodUseMarshal
00803         return locals()
00804     isPickleMethodUseMarshal = property(**isPickleMethodUseMarshal())
00805 
00806     def isPickleMethodUseSafeSerializer():
00807         doc = "isPickleMethodUseSafeSerializer boolean"
00808         def fget(self):
00809             return self.__isPickleMethodUseSafeSerializer
00810         return locals()
00811     isPickleMethodUseSafeSerializer = property(**isPickleMethodUseSafeSerializer())
00812 
00813     def isPickleMethodUseCerealizer():
00814         doc = "isPickleMethodUseCerealizer boolean"
00815         def fget(self):
00816             return self.__isPickleMethodUseCerealizer
00817         return locals()
00818     isPickleMethodUseCerealizer = property(**isPickleMethodUseCerealizer())
00819 
00820     def isPickleMethodUseSimpleJSon():
00821         doc = "isPickleMethodUseSimpleJSon boolean"
00822         def fget(self):
00823             return self.__isPickleMethodUseSimpleJSon
00824         return locals()
00825     isPickleMethodUseSimpleJSon = property(**isPickleMethodUseSimpleJSon())
00826 
00827     def isPickleMethodUseZLIB():
00828         doc = "isPickleMethodUseZLIB boolean"
00829         def fget(self):
00830             return self.__isPickleMethodUseZLIB
00831         return locals()
00832     isPickleMethodUseZLIB = property(**isPickleMethodUseZLIB())
00833 
00834     def isPickleMethodUseLegacyFileMode():
00835         doc = "isPickleMethodUseLegacyFileMode boolean"
00836         def fget(self):
00837             return self.__isPickleMethodUseLegacyFileMode
00838         return locals()
00839     isPickleMethodUseLegacyFileMode = property(**isPickleMethodUseLegacyFileMode())
00840 
00841     def open(self):
00842         file_flag = lambda fname:'c' if (not os.path.exists(fname)) else 'rw'
00843         if (not self.isOpened):
00844             if ( (self.isPickleMethodUseStrings) or (self.isPickleMethodUseMarshal) or (self.isPickleMethodUseSafeSerializer) ):
00845                 self.__db = bsddb.btopen(self.fileName,file_flag(self.fileName))
00846                 self.__isOpened = True
00847             elif (self.isPickleMethodUseBsdDbShelf):
00848                 self.__db = shelve.BsdDbShelf(bsddb.btopen(self.fileName,file_flag(self.fileName)),0,True)
00849                 self.__isOpened = True
00850 
00851     def reset(self):
00852         self.close()
00853         os.remove(self.fileName)
00854         self.__isOpened = False
00855         self.open()
00856 
00857     def dump(self,callback=None):
00858         if (self.isOpened):
00859             import pprint
00860             tName = os.sep.join([os.path.dirname(self.fileName),'.'.join([os.path.basename(self.fileName).split('.')[0],'txt'])])
00861             fHand = open(tName,'w')
00862             pp = pprint.PrettyPrinter(indent=4,width=80)
00863             print >>fHand, '(%s) :: (%s) :: dbx=(%s)' % (__name__,self.fileName,str(self))
00864             for k,v in self.iteritems():
00865                 if (callback):
00866                     try:
00867                         print >>fHand, '%s :: %s' % (k,callback(v))
00868                     except:
00869                         print >>fHand, '%s :: %s' % (k,pp.pformat(v))
00870             print >>fHand
00871             print >>fHand, '='*60
00872             print >>fHand
00873             fHand.flush()
00874             fHand.close()
00875 
00876 ##
00877 # PickledHash2 allows keys to be duplicated with values being placed in lists when keys are duplicated.
00878 # 
00879 #     dbx = PickledHash2(fileName, method=PickleMethods.useStrings)
00880 # 
00881 #     PickleMethods.useBsdDbShelf     = 54x
00882 #     PickleMethods.useStrings        = 26x
00883 #     PickleMethods.useSafeSerializer = 4x
00884 #     PickleMethods.useMarshal        = 1x
00885 #     
00886 class PickledHash2(PickledHash):
00887     def __init__(self, fileName, method=PickleMethods.useBsdDbShelf):
00888         _isProperType = lambda obj:(ObjectTypeName.typeClassName(obj).find('Enum.EnumInstance') > -1)
00889         isProperType = _isProperType(method)
00890         _isProperValue = lambda obj:((obj.value & PickleMethods.useBsdDbShelf.value) != 0)
00891         isProperValue = False
00892         if (isProperType):
00893             isProperValue = _isProperValue(method)
00894         if (not isProperType) or (not isProperValue):
00895             if (not isProperType):
00896                 method = PickleMethods.useBsdDbShelf
00897                 isProperValue = _isProperValue(method)
00898             if (not isProperValue):
00899                 method |= PickleMethods.useBsdDbShelf
00900         return super(PickledHash2, self).__init__(fileName,method)
00901 
00902     def __getitem__(self, key):
00903         return [] if (not super(PickledHash2, self).has_key(key)) else super(PickledHash2, self).__getitem__(key)
00904 
00905     def __setitem__(self, key, value):
00906         key = key if (misc.isString(key)) else str(key)
00907         if (self.has_key(key)):
00908             bucket = super(PickledHash2, self).__getitem__(key)
00909             if (misc.isList(bucket)):
00910                 bucket.append(value)
00911                 super(PickledHash2, self).__setitem__(key,bucket)
00912             else:
00913                 super(PickledHash2, self).__setitem__(key,[value])
00914         else:
00915             super(PickledHash2, self).__setitem__(key,value)
00916 
00917 ##
00918 # PickledFastHash2 allows keys to be duplicated with values being placed in lists when keys are duplicated.
00919 # 
00920 #     dbx = PickledFastHash2(fileName) ... uses PickleMethods.useBsdDbShelf because this method runs faster than all the other methods.
00921 # 
00922 #     Works the same as lists.HashedLists()
00923 # 
00924 #     PickleMethods.useBsdDbShelf     = 54x
00925 #     PickleMethods.useStrings        = 26x
00926 #     PickleMethods.useSafeSerializer = 4x
00927 #     PickleMethods.useMarshal        = 1x
00928 #     
00929 class PickledFastHash2(PickledHash2):
00930     def __init__(self, fileName, method=PickleMethods.useBsdDbShelf):
00931         return super(PickledFastHash2, self).__init__(fileName,method)
00932 
00933 ##
00934 # PickledFastCompressedHash2 allows keys to be duplicated with values being placed in lists when keys are duplicated.
00935 # 
00936 #     dbx = PickledFastCompressedHash2(fileName) ... uses PickleMethods.useBsdDbShelf because this method runs faster than all the other methods.
00937 # 
00938 #     Works the same as lists.HashedLists()
00939 # 
00940 #     PickleMethods.useBsdDbShelf     = 54x
00941 #     PickleMethods.useStrings        = 26x
00942 #     PickleMethods.useSafeSerializer = 4x
00943 #     PickleMethods.useMarshal        = 1x
00944 #     
00945 class PickledFastCompressedHash2(PickledFastHash2):
00946     def __init__(self, fileName):
00947         e = PickleMethods.useBsdDbShelf | PickleMethods.use_zlib
00948         super(PickledFastCompressedHash2, self).__init__(fileName,e)
00949 
00950 ##
00951 # PickledLzmaHash2 allows keys to be duplicated with values being placed in lists when keys are duplicated.
00952 # 
00953 #     dbx = PickledLzmaHash2(fileName) ... uses PickleMethods.useBsdDbShelf because this method runs faster than all the other methods.
00954 # 
00955 #     Works the same as lists.HashedLists()
00956 # 
00957 #     PickleMethods.useBsdDbShelf     = 54x
00958 #     PickleMethods.useStrings        = 26x
00959 #     PickleMethods.useSafeSerializer = 4x
00960 #     PickleMethods.useMarshal        = 1x
00961 #     
00962 class PickledLzmaHash2(PickledFastHash2):
00963     def __init__(self, fileName):
00964         e = PickleMethods.useBsdDbShelf | PickleMethods.use_lzma
00965         super(PickledLzmaHash2, self).__init__(fileName,e)
00966 
00967 __classes = [PickledHash, PickledHash2, PickledFastHash2, PickledFastCompressedHash2, PickledFastHash2, PickledLzmaHash2]
00968 __classes_tags = ['_'+_class_tag(n.split('.')[len(n.split('.'))-1:][0]) for n in [ObjectTypeName._typeName(cls) for cls in __classes]]
00969 
00970 def isFilenameMungedAlready(fname):
00971     return (any([fname.find(f) > -1 for f in __classes_tags]))
00972 
00973 def getMungedFilenameFor(filename):
00974     _root = os.path.dirname(filename)
00975     fname = os.path.splitext(os.path.basename(filename))[0]
00976     ext = os.path.splitext(filename)[-1]
00977     _files = [os.sep.join([_root,f]) for f in os.listdir(_root) if (f.startswith(fname)) and (f.endswith(ext))]
00978     return filename if (len(_files) == 0) else _files[0]
00979 
00980 ##
00981 # Uses the filename to determine which class should be used to open the database file.  Fails with a list if filename has more than one variation present in the same folder.
00982 def openPickledHashBasedOnFilename(filename, method=PickleMethods.none):
00983     def deMungeFileName(fname):
00984         if (isFilenameMungedAlready(fname)):
00985             toks = fname.split('_')
00986             if (len(toks) > 2):
00987                 while (len(toks) > 2):
00988                     toks[0] = '_'.join(toks[0:2])
00989                     del toks[1]
00990             _toks = toks[-1].split('.')
00991             _fname = '.'.join([toks[:len(toks)-1][0],_toks[-1]])
00992             _tag = '_'+_toks[0]
00993             return (fname,_fname,_tag)
00994         return (None, None)
00995 
00996     dname = os.path.dirname(filename)
00997     if (len(dname) == 0):
00998         dname = os.path.abspath('.')
00999     _obj = None
01000     _tag = ''
01001     fname = os.path.basename(filename)
01002     fname, _fname, _tag = deMungeFileName(fname)
01003     toks = fname.split('.')
01004     if (len(toks) > 1):
01005         toks[-1] = '.'+toks[-1]
01006     files = [deMungeFileName(f) for f in os.listdir(dname)]
01007     files = [f[1] for f in files if (f[0] == fname) and (f[-1] == _tag)]
01008     if (len(files) == 1):
01009         if (len(_tag) == 0):
01010             return openPickledHashBasedOnFilename(os.sep.join([dname,files[0]]),method=method)
01011         i = misc.findInListSafely(__classes_tags,_tag)
01012         if (i > -1):
01013             info_string = ''
01014             toks = ObjectTypeName._typeName(__classes[i]).split('.')
01015             className = toks[len(toks)-1:][0]
01016             try:
01017                 s = '%s(filename,method=method)' % (className)
01018                 _obj = eval(s)
01019             except TypeError:
01020                 try:
01021                     s = '%s(filename)' % (className)
01022                     _obj = eval(s)
01023                 except Exception, details:
01024                     info_string = str(details)
01025         else:
01026             raise ValueError('(%s) :: Cannot figure-out the class name based on "%s", recommend working this out on you own because you seemed to have written some bad code or maybe "%s".' % (misc.funcName(),_tag,info_string))
01027     else:
01028         raise ValueError('(%s) :: Too %s files (%d) named like "%s" %s for %s, recommend using the class name "%s" and open it yourself.' % (misc.funcName(),'many' if (len(files) > 1) else 'few',len(files),str(files),str(toks),filename,_tag))
01029     return _obj
01030 
01031 def put_data(_fname,key,value,fOut=None,isUnique=True):
01032     dbx = PickledFastCompressedHash2(_fname)
01033     try:
01034         value = value if (not misc.isList(value)) else value[0]
01035         if (isUnique) and (dbx.has_key(key)):
01036             del dbx[key]
01037         dbx[key] = value
01038     except Exception, details:
01039         from vyperlogix.misc import _utils
01040         fOut = sys.stderr if (fOut is None) else fOut
01041         print >>fOut, _utils.formattedException(details)
01042     finally:
01043         dbx.close()
01044 
01045 def get_data(_fname,key,fOut=None,isUnique=True):
01046     dbx = PickledFastCompressedHash2(_fname)
01047     value = None
01048     try:
01049         value = dbx[key]
01050         if (isUnique):
01051             value = value if (not misc.isList(value)) else None if (len(value) == 0) else value[0]
01052     except Exception, details:
01053         from vyperlogix.misc import _utils
01054         fOut = sys.stderr if (fOut is None) else fOut
01055         print >>fOut, _utils.formattedException(details)
01056     finally:
01057         dbx.close()
01058     return value
01059 
01060 if (__name__ == '__main__'):
01061     import sys
01062     print >>sys.stdout, __copyright__
01063     print >>sys.stderr, __copyright__
01064 
01065     #dbx = openPickledHashBasedOnFilename('Z:\\@myMagma\\python-local-new-trunk\\test\\win32\\logs\\2008-07-31_07_55_58\\dbx\\CaseWatcher2Cases.dbx')
01066     #lists.prettyPrint(dbx,title='%s'%(dbx.fileName))
01067     #dbx.close()
01068     #pass
01069 
01070 

© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved; If you reference this document or any part of this document you must use the citation verbatim (including the link) "© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved."

Notice: This source code contained in this document is NOT open source and is NOT being distributed as open source.

122,241 lines of code and growing...