author | Adrien Di Mascio <Adrien.DiMascio@logilab.fr> |
Mon, 10 Nov 2008 19:33:55 +0100 | |
changeset 16 | a70ece4d9d1a |
parent 0 | b97547f5f1fa |
child 447 | 0e52d72104a6 |
permissions | -rw-r--r-- |
"""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" from datetime import datetime, time, date from mx.DateTime import DateTime, Date, Time def mx2datetime(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 datetime return datetime(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)) def datetime2mx(datetimeobj, yamstype=None): """converts a mx date object (DateTime, Date or Time) into a regular python datetime object """ if yamstype is None: yamstype = guess_yamstype_from_date(datetimeobj) assert yamstype is not None if yamstype == 'Datetime': # don't use date, db model doesn't actually support it, only datetime return DateTime(datetimeobj.year, datetimeobj.month, datetimeobj.day, datetimeobj.hour, datetimeobj.minute, int(datetimeobj.second)) elif yamstype == 'Date': return Date(datetimeobj.year, datetimeobj.month, datetimeobj.day) # XXX don't support time either, what should we do here ? return Time(datetimeobj.hour, datetimeobj.minute, int(datetimeobj.second)) def guess_yamstype_for_date(datetimeobj): """guesses yams correct type according to `datetimeobj`'s type""" if isinstance(datetimeobj, datetime): return 'Datetime' elif isinstance(datetimeobj, date): return 'Date' elif isinstance(datetimeobj, time): return 'Time' return None def use_mx_for_dates(func): """decorator to convert func's return value into mx objects instead of datetime objects """ def wrapper(*args, **kwargs): value = func(*args, **kwargs) yamstype = guess_yamstype_for_date(value) if yamstype is None: return value return datetime2mx(value, yamstype) return wrapper try: # WARNING: do not import the google's db module here since it will take # precedence over our own db submodule from google.appengine.api.datastore import Key, Get, Query from google.appengine.api.datastore_errors import BadKeyError except ImportError: # not in google app environment pass else: import os _SS = os.environ.get('SERVER_SOFTWARE') if _SS is None: MODE = 'test' elif _SS.startswith('Dev'): MODE = 'dev' else: MODE = 'prod' from cubicweb.server import SOURCE_TYPES from cubicweb.goa.gaesource import GAESource SOURCE_TYPES['gae'] = GAESource def do_monkey_patch(): # monkey patch yams Bytes validator since it should take a bytes string with gae # and not a StringIO def check_bytes(eschema, value): """check value is a bytes string""" return isinstance(value, str) from yams import constraints constraints.BASE_CHECKERS['Bytes'] = check_bytes def rql_for_eid(eid): return 'Any X WHERE X eid "%s"' % eid from cubicweb.common import uilib uilib.rql_for_eid = rql_for_eid def typed_eid(eid): try: return str(Key(eid)) except BadKeyError: raise ValueError(eid) import cubicweb cubicweb.typed_eid = typed_eid # XXX monkey patch cubicweb.schema.CubicWebSchema to have string eid with # optional cardinality (since eid is set after the validation) import re from yams import buildobjs as ybo def add_entity_type(self, edef): edef.name = edef.name.encode() assert re.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) if not eschema.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] = eschema return eschema from cubicweb.schema import CubicWebSchema CubicWebSchema.add_entity_type = add_entity_type # don't reset vreg on repository set_schema from cubicweb.server import repository orig_set_schema = repository.Repository.set_schema def set_schema(self, schema, resetvreg=True): orig_set_schema(self, schema, False) repository.Repository.set_schema = set_schema # deactivate function ensuring relation cardinality consistency repository.del_existing_rel_if_needed = lambda *args: None def get_cubes(self): """return the list of top level cubes used by this instance""" config = self.config cubes = config['included-cubes'] + config['included-yams-cubes'] return config.expand_cubes(cubes) repository.Repository.get_cubes = get_cubes from rql import RQLHelper RQLHelper.simplify = lambda x,r: None # activate entity caching on the server side def set_entity_cache(self, entity): self._query_data.setdefault('_eid_cache', {})[entity.eid] = entity def entity_cache(self, eid): return self._query_data['_eid_cache'][eid] def drop_entity_cache(self, eid=None): if eid is None: self._query_data['_eid_cache'] = {} elif '_eid_cache' in self._query_data: self._query_data['_eid_cache'].pop(eid, None) def datastore_get(self, key): if isinstance(key, basestring): key = Key(key) try: gentity = self._query_data['_key_cache'][key] #self.critical('cached %s', gentity) except KeyError: gentity = Get(key) #self.critical('Get %s', gentity) self._query_data.setdefault('_key_cache', {})[key] = gentity return gentity def clear_datastore_cache(self, key=None): if key is None: self._query_data['_key_cache'] = {} else: if isinstance(key, basestring): key = Key(key) self._query_data['_key_cache'].pop(key, None) from cubicweb.server.session import Session Session.set_entity_cache = set_entity_cache Session.entity_cache = entity_cache Session.drop_entity_cache = drop_entity_cache Session.datastore_get = datastore_get Session.clear_datastore_cache = clear_datastore_cache from docutils.frontend import OptionParser # avoid a call to expanduser which is not available under gae def get_standard_config_files(self): return self.standard_config_files OptionParser.get_standard_config_files = get_standard_config_files