goa/__init__.py
changeset 6366 1806148d6ce8
parent 6333 e3994fcc21c3
parent 6365 a15cc5e16178
child 6367 d4c485ec1ca1
equal deleted inserted replaced
6333:e3994fcc21c3 6366:1806148d6ce8
     1 # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     3 #
       
     4 # This file is part of CubicWeb.
       
     5 #
       
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
       
     7 # terms of the GNU Lesser General Public License as published by the Free
       
     8 # Software Foundation, either version 2.1 of the License, or (at your option)
       
     9 # any later version.
       
    10 #
       
    11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT
       
    12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
       
    14 # details.
       
    15 #
       
    16 # You should have received a copy of the GNU Lesser General Public License along
       
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
       
    18 """cubicweb on google appengine
       
    19 
       
    20 """
       
    21 __docformat__ = "restructuredtext en"
       
    22 
       
    23 
       
    24 try:
       
    25     # WARNING: do not import the google's db module here since it will take
       
    26     #          precedence over our own db submodule
       
    27     from google.appengine.api.datastore import Key, Get, Query
       
    28     from google.appengine.api.datastore_errors import BadKeyError
       
    29 except ImportError:
       
    30     # not in google app environment
       
    31     pass
       
    32 else:
       
    33 
       
    34     import os
       
    35     _SS = os.environ.get('SERVER_SOFTWARE')
       
    36     if _SS is None:
       
    37         MODE = 'test'
       
    38     elif _SS.startswith('Dev'):
       
    39         MODE = 'dev'
       
    40     else:
       
    41         MODE = 'prod'
       
    42 
       
    43     from cubicweb.server import SOURCE_TYPES
       
    44     from cubicweb.goa.gaesource import GAESource
       
    45     SOURCE_TYPES['gae'] = GAESource
       
    46 
       
    47 
       
    48     def do_monkey_patch():
       
    49 
       
    50         # monkey patch yams Bytes validator since it should take a bytes string with gae
       
    51         # and not a StringIO
       
    52         def check_bytes(eschema, value):
       
    53             """check value is a bytes string"""
       
    54             return isinstance(value, str)
       
    55         from yams import constraints
       
    56         constraints.BASE_CHECKERS['Bytes'] = check_bytes
       
    57 
       
    58         def rql_for_eid(eid):
       
    59             return 'Any X WHERE X eid "%s"' % eid
       
    60         from cubicweb import uilib
       
    61         uilib.rql_for_eid = rql_for_eid
       
    62 
       
    63         def typed_eid(eid):
       
    64             try:
       
    65                 return str(Key(eid))
       
    66             except BadKeyError:
       
    67                 raise ValueError(eid)
       
    68         import cubicweb
       
    69         cubicweb.typed_eid = typed_eid
       
    70 
       
    71         # XXX monkey patch cubicweb.schema.CubicWebSchema to have string eid with
       
    72         #     optional cardinality (since eid is set after the validation)
       
    73 
       
    74         import re
       
    75         from yams import buildobjs as ybo
       
    76 
       
    77         def add_entity_type(self, edef):
       
    78             edef.name = edef.name.encode()
       
    79             assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name)
       
    80             eschema = super(CubicWebSchema, self).add_entity_type(edef)
       
    81             if not eschema.final:
       
    82                 # automatically add the eid relation to non final entity types
       
    83                 rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Bytes',
       
    84                                               cardinality='?1', uid=True)
       
    85                 self.add_relation_def(rdef)
       
    86                 rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type)
       
    87                 self.add_relation_def(rdef)
       
    88             self._eid_index[eschema.eid] = eschema
       
    89             return eschema
       
    90 
       
    91         from cubicweb.schema import CubicWebSchema
       
    92         CubicWebSchema.add_entity_type = add_entity_type
       
    93 
       
    94 
       
    95         # don't reset vreg on repository set_schema
       
    96         from cubicweb.server import repository
       
    97         orig_set_schema = repository.Repository.set_schema
       
    98         def set_schema(self, schema, resetvreg=True):
       
    99             orig_set_schema(self, schema, False)
       
   100         repository.Repository.set_schema = set_schema
       
   101         # deactivate function ensuring relation cardinality consistency
       
   102         repository.del_existing_rel_if_needed = lambda *args: None
       
   103 
       
   104         def get_cubes(self):
       
   105             """return the list of top level cubes used by this instance"""
       
   106             config = self.config
       
   107             cubes = config['included-cubes'] + config['included-yams-cubes']
       
   108             return config.expand_cubes(cubes)
       
   109         repository.Repository.get_cubes = get_cubes
       
   110 
       
   111         from rql import RQLHelper
       
   112         RQLHelper.simplify = lambda x, r: None
       
   113 
       
   114         # activate entity caching on the server side
       
   115 
       
   116         def set_entity_cache(self, entity):
       
   117             self.transaction_data.setdefault('_eid_cache', {})[entity.eid] = entity
       
   118 
       
   119         def entity_cache(self, eid):
       
   120             return self.transaction_data['_eid_cache'][eid]
       
   121 
       
   122         def drop_entity_cache(self, eid=None):
       
   123             if eid is None:
       
   124                 self.transaction_data['_eid_cache'] = {}
       
   125             elif '_eid_cache' in self.transaction_data:
       
   126                 self.transaction_data['_eid_cache'].pop(eid, None)
       
   127 
       
   128         def datastore_get(self, key):
       
   129             if isinstance(key, basestring):
       
   130                 key = Key(key)
       
   131             try:
       
   132                 gentity = self.transaction_data['_key_cache'][key]
       
   133                 #self.critical('cached %s', gentity)
       
   134             except KeyError:
       
   135                 gentity = Get(key)
       
   136                 #self.critical('Get %s', gentity)
       
   137                 self.transaction_data.setdefault('_key_cache', {})[key] = gentity
       
   138             return gentity
       
   139 
       
   140         def clear_datastore_cache(self, key=None):
       
   141             if key is None:
       
   142                 self.transaction_data['_key_cache'] = {}
       
   143             else:
       
   144                 if isinstance(key, basestring):
       
   145                     key = Key(key)
       
   146                 self.transaction_data['_key_cache'].pop(key, None)
       
   147 
       
   148         from cubicweb.server.session import Session
       
   149         Session.set_entity_cache = set_entity_cache
       
   150         Session.entity_cache = entity_cache
       
   151         Session.drop_entity_cache = drop_entity_cache
       
   152         Session.datastore_get = datastore_get
       
   153         Session.clear_datastore_cache = clear_datastore_cache
       
   154 
       
   155         from docutils.frontend import OptionParser
       
   156         # avoid a call to expanduser which is not available under gae
       
   157         def get_standard_config_files(self):
       
   158             return self.standard_config_files
       
   159         OptionParser.get_standard_config_files = get_standard_config_files