Enable Enterprise enrollment on desktop builds.
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / appengine_wrappers.py
blob46502c81e0c6cde06cd3ff3a7f1992e68d451939
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import os
7 from app_yaml_helper import AppYamlHelper
9 def GetAppVersion():
10 if 'CURRENT_VERSION_ID' in os.environ:
11 # The version ID looks like 2-0-25.36712548, we only want the 2-0-25.
12 return os.environ['CURRENT_VERSION_ID'].split('.', 1)[0]
13 # Not running on appengine, get it from the app.yaml file ourselves.
14 app_yaml_path = os.path.join(os.path.split(__file__)[0], 'app.yaml')
15 with open(app_yaml_path, 'r') as app_yaml:
16 return AppYamlHelper.ExtractVersion(app_yaml.read())
18 def IsDeadlineExceededError(error):
19 '''A general way of determining whether |error| is a DeadlineExceededError,
20 since there are 3 different types thrown by AppEngine and we might as well
21 handle them all the same way. For more info see:
22 https://developers.google.com/appengine/articles/deadlineexceedederrors
23 '''
24 return type(error).__name__ == 'DeadlineExceededError'
26 def IsDownloadError(error):
27 return type(error).__name__ == 'DownloadError'
29 # This will attempt to import the actual App Engine modules, and if it fails,
30 # they will be replaced with fake modules. This is useful during testing.
31 try:
32 import google.appengine.api.files as files
33 import google.appengine.api.logservice as logservice
34 import google.appengine.api.memcache as memcache
35 import google.appengine.api.urlfetch as urlfetch
36 import google.appengine.ext.blobstore as blobstore
37 from google.appengine.ext.blobstore.blobstore import BlobReferenceProperty
38 import google.appengine.ext.db as db
39 import webapp2
40 except ImportError:
41 import re
42 from StringIO import StringIO
44 FAKE_URL_FETCHER_CONFIGURATION = None
46 def ConfigureFakeUrlFetch(configuration):
47 """|configuration| is a dictionary mapping strings to fake urlfetch classes.
48 A fake urlfetch class just needs to have a fetch method. The keys of the
49 dictionary are treated as regex, and they are matched with the URL to
50 determine which fake urlfetch is used.
51 """
52 global FAKE_URL_FETCHER_CONFIGURATION
53 FAKE_URL_FETCHER_CONFIGURATION = dict(
54 (re.compile(k), v) for k, v in configuration.iteritems())
56 def _GetConfiguration(key):
57 if not FAKE_URL_FETCHER_CONFIGURATION:
58 raise ValueError('No fake fetch paths have been configured. '
59 'See ConfigureFakeUrlFetch in appengine_wrappers.py.')
60 for k, v in FAKE_URL_FETCHER_CONFIGURATION.iteritems():
61 if k.match(key):
62 return v
63 raise ValueError('No configuration found for %s' % key)
65 class _RPC(object):
66 def __init__(self, result=None):
67 self.result = result
69 def get_result(self):
70 return self.result
72 def wait(self):
73 pass
75 class FakeUrlFetch(object):
76 """A fake urlfetch module that uses the current
77 |FAKE_URL_FETCHER_CONFIGURATION| to map urls to fake fetchers.
78 """
79 class DownloadError(Exception):
80 pass
82 class _Response(object):
83 def __init__(self, content):
84 self.content = content
85 self.headers = {'Content-Type': 'none'}
86 self.status_code = 200
88 def fetch(self, url, **kwargs):
89 url = url.split('?', 1)[0]
90 response = self._Response(_GetConfiguration(url).fetch(url))
91 if response.content is None:
92 response.status_code = 404
93 return response
95 def create_rpc(self):
96 return _RPC()
98 def make_fetch_call(self, rpc, url, **kwargs):
99 rpc.result = self.fetch(url)
100 urlfetch = FakeUrlFetch()
102 _BLOBS = {}
103 class FakeBlobstore(object):
104 class BlobNotFoundError(Exception):
105 pass
107 class BlobReader(object):
108 def __init__(self, blob_key):
109 self._data = _BLOBS[blob_key].getvalue()
111 def read(self):
112 return self._data
114 blobstore = FakeBlobstore()
116 class FakeFileInterface(object):
117 """This class allows a StringIO object to be used in a with block like a
118 file.
120 def __init__(self, io):
121 self._io = io
123 def __exit__(self, *args):
124 pass
126 def write(self, data):
127 self._io.write(data)
129 def __enter__(self, *args):
130 return self._io
132 class FakeFiles(object):
133 _next_blobstore_key = 0
134 class blobstore(object):
135 @staticmethod
136 def create():
137 FakeFiles._next_blobstore_key += 1
138 return FakeFiles._next_blobstore_key
140 @staticmethod
141 def get_blob_key(filename):
142 return filename
144 def open(self, filename, mode):
145 _BLOBS[filename] = StringIO()
146 return FakeFileInterface(_BLOBS[filename])
148 def GetBlobKeys(self):
149 return _BLOBS.keys()
151 def finalize(self, filename):
152 pass
154 files = FakeFiles()
156 class Logservice(object):
157 AUTOFLUSH_ENABLED = True
159 def flush(self):
160 pass
162 logservice = Logservice()
164 class InMemoryMemcache(object):
165 """An in-memory memcache implementation.
167 def __init__(self):
168 self._namespaces = {}
170 class Client(object):
171 def set_multi_async(self, mapping, namespace='', time=0):
172 for k, v in mapping.iteritems():
173 memcache.set(k, v, namespace=namespace, time=time)
175 def get_multi_async(self, keys, namespace='', time=0):
176 return _RPC(result=dict(
177 (k, memcache.get(k, namespace=namespace, time=time)) for k in keys))
179 def set(self, key, value, namespace='', time=0):
180 self._GetNamespace(namespace)[key] = value
182 def get(self, key, namespace='', time=0):
183 return self._GetNamespace(namespace).get(key)
185 def delete(self, key, namespace=''):
186 self._GetNamespace(namespace).pop(key, None)
188 def delete_multi(self, keys, namespace=''):
189 for k in keys:
190 self.delete(k, namespace=namespace)
192 def _GetNamespace(self, namespace):
193 if namespace not in self._namespaces:
194 self._namespaces[namespace] = {}
195 return self._namespaces[namespace]
197 memcache = InMemoryMemcache()
199 class webapp2(object):
200 class RequestHandler(object):
201 """A fake webapp2.RequestHandler class for Handler to extend.
203 def __init__(self, request, response):
204 self.request = request
205 self.response = response
206 self.response.status = 200
208 def redirect(self, path, permanent=False):
209 self.response.status = 301 if permanent else 302
210 self.response.headers['Location'] = path
212 class _Db_Result(object):
213 def __init__(self, data):
214 self._data = data
216 class _Result(object):
217 def __init__(self, value):
218 self.value = value
220 def get(self):
221 return self._Result(self._data)
223 class db(object):
224 _store = {}
226 class StringProperty(object):
227 pass
229 class BlobProperty(object):
230 pass
232 class Key(object):
233 def __init__(self, key):
234 self._key = key
236 @staticmethod
237 def from_path(model_name, path):
238 return db.Key('%s/%s' % (model_name, path))
240 def __eq__(self, obj):
241 return self.__class__ == obj.__class__ and self._key == obj._key
243 def __hash__(self):
244 return hash(self._key)
246 def __str__(self):
247 return str(self._key)
249 class Model(object):
250 key = None
252 def __init__(self, **optargs):
253 cls = self.__class__
254 for k, v in optargs.iteritems():
255 assert hasattr(cls, k), '%s does not define property %s' % (
256 cls.__name__, k)
257 setattr(self, k, v)
259 @staticmethod
260 def gql(query, key):
261 return _Db_Result(db._store.get(key))
263 def put(self):
264 db._store[self.key_] = self.value
266 @staticmethod
267 def get_async(key):
268 return _RPC(result=db._store.get(key))
270 @staticmethod
271 def delete_async(key):
272 db._store.pop(key, None)
273 return _RPC()
275 @staticmethod
276 def put_async(value):
277 db._store[value.key] = value
278 return _RPC()
280 class BlobReferenceProperty(object):
281 pass