"""cubicweb on google appengine:organization: Logilab:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"fromdatetimeimportdatetime,time,datefrommx.DateTimeimportDateTime,Date,Timedefmx2datetime(mxobj,yamstype):"""converts a mx date object (DateTime, Date or Time) into a regular python datetime object """#if yamstype == 'Datetime':# don't use date, db model doesn't actually support it, only datetimereturndatetime(mxobj.year,mxobj.month,mxobj.day,mxobj.hour,mxobj.minute,int(mxobj.second))# elif yamstype == 'Date':# return date(mxobj.year, mxobj.month, mxobj.day)# # XXX don't support time either, what should we do here ?# return time(mxobj.hour, mxobj.minute, int(mxobj.second))defdatetime2mx(datetimeobj,yamstype=None):"""converts a mx date object (DateTime, Date or Time) into a regular python datetime object """ifyamstypeisNone:yamstype=guess_yamstype_for_date(datetimeobj)assertyamstypeisnotNoneifyamstype=='Datetime':# don't use date, db model doesn't actually support it, only datetimereturnDateTime(datetimeobj.year,datetimeobj.month,datetimeobj.day,datetimeobj.hour,datetimeobj.minute,int(datetimeobj.second))elifyamstype=='Date':returnDate(datetimeobj.year,datetimeobj.month,datetimeobj.day)# XXX don't support time either, what should we do here ?returnTime(datetimeobj.hour,datetimeobj.minute,int(datetimeobj.second))defguess_yamstype_for_date(datetimeobj):"""guesses yams correct type according to `datetimeobj`'s type"""ifisinstance(datetimeobj,datetime):return'Datetime'elifisinstance(datetimeobj,date):return'Date'elifisinstance(datetimeobj,time):return'Time'returnNonedefuse_mx_for_dates(func):"""decorator to convert func's return value into mx objects instead of datetime objects """defwrapper(*args,**kwargs):value=func(*args,**kwargs)yamstype=guess_yamstype_for_date(value)ifyamstypeisNone:returnvaluereturndatetime2mx(value,yamstype)returnwrappertry:# WARNING: do not import the google's db module here since it will take# precedence over our own db submodulefromgoogle.appengine.api.datastoreimportKey,Get,Queryfromgoogle.appengine.api.datastore_errorsimportBadKeyErrorexceptImportError:# not in google app environmentpasselse:importos_SS=os.environ.get('SERVER_SOFTWARE')if_SSisNone:MODE='test'elif_SS.startswith('Dev'):MODE='dev'else:MODE='prod'fromcubicweb.serverimportSOURCE_TYPESfromcubicweb.goa.gaesourceimportGAESourceSOURCE_TYPES['gae']=GAESourcedefdo_monkey_patch():# monkey patch yams Bytes validator since it should take a bytes string with gae# and not a StringIOdefcheck_bytes(eschema,value):"""check value is a bytes string"""returnisinstance(value,str)fromyamsimportconstraintsconstraints.BASE_CHECKERS['Bytes']=check_bytesdefrql_for_eid(eid):return'Any X WHERE X eid "%s"'%eidfromcubicweb.commonimportuilibuilib.rql_for_eid=rql_for_eiddeftyped_eid(eid):try:returnstr(Key(eid))exceptBadKeyError:raiseValueError(eid)importcubicwebcubicweb.typed_eid=typed_eid# XXX monkey patch cubicweb.schema.CubicWebSchema to have string eid with# optional cardinality (since eid is set after the validation)importrefromyamsimportbuildobjsasybodefadd_entity_type(self,edef):edef.name=edef.name.encode()assertre.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$',edef.name),repr(edef.name)eschema=super(CubicWebSchema,self).add_entity_type(edef)ifnoteschema.is_final():# automatically add the eid relation to non final entity types rdef=ybo.RelationDefinition(eschema.type,'eid','Bytes',cardinality='?1',uid=True)self.add_relation_def(rdef)rdef=ybo.RelationDefinition(eschema.type,'identity',eschema.type)self.add_relation_def(rdef)self._eid_index[eschema.eid]=eschemareturneschemafromcubicweb.schemaimportCubicWebSchemaCubicWebSchema.add_entity_type=add_entity_type# don't reset vreg on repository set_schemafromcubicweb.serverimportrepositoryorig_set_schema=repository.Repository.set_schemadefset_schema(self,schema,resetvreg=True):orig_set_schema(self,schema,False)repository.Repository.set_schema=set_schema# deactivate function ensuring relation cardinality consistencyrepository.del_existing_rel_if_needed=lambda*args:Nonedefget_cubes(self):"""return the list of top level cubes used by this instance"""config=self.configcubes=config['included-cubes']+config['included-yams-cubes']returnconfig.expand_cubes(cubes)repository.Repository.get_cubes=get_cubesfromrqlimportRQLHelperRQLHelper.simplify=lambdax,r:None# activate entity caching on the server sidedefset_entity_cache(self,entity):self._query_data.setdefault('_eid_cache',{})[entity.eid]=entitydefentity_cache(self,eid):returnself._query_data['_eid_cache'][eid]defdrop_entity_cache(self,eid=None):ifeidisNone:self._query_data['_eid_cache']={}elif'_eid_cache'inself._query_data:self._query_data['_eid_cache'].pop(eid,None)defdatastore_get(self,key):ifisinstance(key,basestring):key=Key(key)try:gentity=self._query_data['_key_cache'][key]#self.critical('cached %s', gentity)exceptKeyError:gentity=Get(key)#self.critical('Get %s', gentity)self._query_data.setdefault('_key_cache',{})[key]=gentityreturngentitydefclear_datastore_cache(self,key=None):ifkeyisNone:self._query_data['_key_cache']={}else:ifisinstance(key,basestring):key=Key(key)self._query_data['_key_cache'].pop(key,None)fromcubicweb.server.sessionimportSessionSession.set_entity_cache=set_entity_cacheSession.entity_cache=entity_cacheSession.drop_entity_cache=drop_entity_cacheSession.datastore_get=datastore_getSession.clear_datastore_cache=clear_datastore_cachefromdocutils.frontendimportOptionParser# avoid a call to expanduser which is not available under gaedefget_standard_config_files(self):returnself.standard_config_filesOptionParser.get_standard_config_files=get_standard_config_files