Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 # This will attempt to import the actual App Engine modules, and if it fails, | 5 # This will attempt to import the actual App Engine modules, and if it fails, |
| 6 # they will be replaced with fake modules. This is useful during testing. | 6 # they will be replaced with fake modules. This is useful during testing. |
| 7 try: | 7 try: |
| 8 import google.appengine.ext.blobstore as blobstore | 8 import google.appengine.ext.blobstore as blobstore |
| 9 from google.appengine.ext.blobstore.blobstore import BlobReferenceProperty | 9 from google.appengine.ext.blobstore.blobstore import BlobReferenceProperty |
| 10 import google.appengine.ext.db as db | 10 import google.appengine.ext.db as db |
| 11 import google.appengine.ext.webapp as webapp | 11 import google.appengine.ext.webapp as webapp |
| 12 import google.appengine.api.files as files | 12 import google.appengine.api.files as files |
| 13 import google.appengine.api.memcache as memcache | 13 import google.appengine.api.memcache as memcache |
| 14 import google.appengine.api.urlfetch as urlfetch | 14 import google.appengine.api.urlfetch as urlfetch |
| 15 except ImportError: | 15 except ImportError: |
| 16 import re | 16 import re |
| 17 | 17 |
| 18 from future import Future | |
| 19 | |
| 18 FAKE_URL_FETCHER_CONFIGURATION = None | 20 FAKE_URL_FETCHER_CONFIGURATION = None |
| 19 | 21 |
| 20 def ConfigureFakeUrlFetch(configuration): | 22 def ConfigureFakeUrlFetch(configuration): |
| 21 """|configuration| is a dictionary mapping strings to fake urlfetch classes. | 23 """|configuration| is a dictionary mapping strings to fake urlfetch classes. |
| 22 A fake urlfetch class just needs to have a fetch method. The keys of the | 24 A fake urlfetch class just needs to have a fetch method. The keys of the |
| 23 dictionary are treated as regex, and they are matched with the URL to | 25 dictionary are treated as regex, and they are matched with the URL to |
| 24 determine which fake urlfetch is used. | 26 determine which fake urlfetch is used. |
| 25 """ | 27 """ |
| 26 global FAKE_URL_FETCHER_CONFIGURATION | 28 global FAKE_URL_FETCHER_CONFIGURATION |
| 27 FAKE_URL_FETCHER_CONFIGURATION = dict( | 29 FAKE_URL_FETCHER_CONFIGURATION = dict( |
| 28 (re.compile(k), v) for k, v in configuration.iteritems()) | 30 (re.compile(k), v) for k, v in configuration.iteritems()) |
| 29 | 31 |
| 30 def _GetConfiguration(key): | 32 def _GetConfiguration(key): |
| 31 if not FAKE_URL_FETCHER_CONFIGURATION: | 33 if not FAKE_URL_FETCHER_CONFIGURATION: |
| 32 raise ValueError('No fake fetch paths have been configured. ' | 34 raise ValueError('No fake fetch paths have been configured. ' |
| 33 'See ConfigureFakeUrlFetch in appengine_wrappers.py.') | 35 'See ConfigureFakeUrlFetch in appengine_wrappers.py.') |
| 34 for k, v in FAKE_URL_FETCHER_CONFIGURATION.iteritems(): | 36 for k, v in FAKE_URL_FETCHER_CONFIGURATION.iteritems(): |
| 35 if k.match(key): | 37 if k.match(key): |
| 36 return v | 38 return v |
| 37 return None | 39 return None |
| 38 | 40 |
| 41 class _RPC(object): | |
| 42 def __init__(self, result=None): | |
| 43 self.result = result | |
| 44 | |
| 45 def get_result(self): | |
| 46 return self.result | |
| 47 | |
| 39 class FakeUrlFetch(object): | 48 class FakeUrlFetch(object): |
| 40 """A fake urlfetch module that uses the current | 49 """A fake urlfetch module that uses the current |
| 41 |FAKE_URL_FETCHER_CONFIGURATION| to map urls to fake fetchers. | 50 |FAKE_URL_FETCHER_CONFIGURATION| to map urls to fake fetchers. |
| 42 """ | 51 """ |
| 43 class _Response(object): | 52 class _Response(object): |
| 44 def __init__(self, content): | 53 def __init__(self, content): |
| 45 self.content = content | 54 self.content = content |
| 46 self.headers = { 'content-type': 'none' } | 55 self.headers = { 'content-type': 'none' } |
| 47 self.status_code = 200 | 56 self.status_code = 200 |
| 48 | 57 |
| 49 class _RPC(object): | |
| 50 def __init__(self): | |
| 51 self.result = None | |
| 52 | |
| 53 def wait(self): | |
| 54 pass | |
| 55 | |
| 56 def get_result(self): | |
| 57 return self.result | |
| 58 | |
| 59 def fetch(self, url): | 58 def fetch(self, url): |
| 60 return self._Response(_GetConfiguration(url).fetch(url)) | 59 return self._Response(_GetConfiguration(url).fetch(url)) |
| 61 | 60 |
| 62 def create_rpc(self): | 61 def create_rpc(self): |
| 63 return self._RPC() | 62 return _RPC() |
| 64 | 63 |
| 65 def make_fetch_call(self, rpc, url): | 64 def make_fetch_call(self, rpc, url): |
| 66 rpc.result = self.fetch(url) | 65 rpc.result = self.fetch(url) |
| 67 urlfetch = FakeUrlFetch() | 66 urlfetch = FakeUrlFetch() |
| 68 | 67 |
| 69 class NotImplemented(object): | 68 class NotImplemented(object): |
| 70 def __getattr__(self, attr): | 69 def __getattr__(self, attr): |
| 71 raise NotImplementedError() | 70 raise NotImplementedError() |
| 72 | 71 |
| 73 blobstore = NotImplemented() | 72 blobstore = NotImplemented() |
| 74 files = NotImplemented() | 73 files = NotImplemented() |
| 75 | 74 |
| 76 class InMemoryMemcache(object): | 75 class InMemoryMemcache(object): |
| 77 """A memcache that stores items in memory instead of using the memcache | 76 """A fake memcache that does nothing. AppEngineMemcache already stores items |
| 78 module. | 77 in local memory. |
| 79 """ | 78 """ |
| 80 def __init__(self): | 79 class Client(object): |
| 81 self._cache = {} | 80 def set_multi_async(self, mapping, namespace='', time=300): |
|
not at google - send to devlin
2012/08/20 05:27:10
300 looks especially arbitrary here. Make it 0 or
cduvall
2012/08/20 21:28:09
Done.
| |
| 81 return | |
| 82 | 82 |
| 83 def set(self, key, value, namespace, time=60): | 83 def get_multi_async(self, keys, namespace='', time=300): |
| 84 if namespace not in self._cache: | 84 return _RPC(result=dict((k, None) for k in keys)) |
| 85 self._cache[namespace] = {} | |
| 86 self._cache[namespace][key] = value | |
| 87 | 85 |
| 88 def get(self, key, namespace): | 86 def set(self, key, value, namespace='', time=300): |
| 89 if namespace not in self._cache: | 87 return |
| 90 return None | 88 |
| 91 return self._cache[namespace].get(key, None) | 89 def get(self, key, namespace='', time=300): |
| 90 return None | |
| 92 | 91 |
| 93 def delete(self, key, namespace): | 92 def delete(self, key, namespace): |
| 94 if namespace in self._cache: | 93 return |
| 95 self._cache[namespace].pop(key) | |
| 96 memcache = InMemoryMemcache() | 94 memcache = InMemoryMemcache() |
| 97 | 95 |
| 98 # A fake webapp.RequestHandler class for Handler to extend. | |
| 99 class webapp(object): | 96 class webapp(object): |
| 100 class RequestHandler(object): | 97 class RequestHandler(object): |
| 98 """A fake webapp.RequestHandler class for Handler to extend. | |
| 99 """ | |
| 101 def __init__(self, request, response): | 100 def __init__(self, request, response): |
| 102 self.request = request | 101 self.request = request |
| 103 self.response = response | 102 self.response = response |
| 104 | 103 |
| 105 def redirect(self, path): | 104 def redirect(self, path): |
| 106 self.request.path = path | 105 self.request.path = path |
| 107 | 106 |
| 108 class _Db_Result(object): | 107 class _Db_Result(object): |
| 109 def get(self): | 108 def get(self): |
| 110 return [] | 109 return [] |
| 111 | 110 |
| 112 class db(object): | 111 class db(object): |
| 113 class StringProperty(object): | 112 class StringProperty(object): |
| 114 pass | 113 pass |
| 115 | 114 |
| 116 class Model(object): | 115 class Model(object): |
| 117 @staticmethod | 116 @staticmethod |
| 118 def gql(*args): | 117 def gql(*args): |
| 119 return _Db_Result() | 118 return _Db_Result() |
| 120 | 119 |
| 121 class BlobReferenceProperty(object): | 120 class BlobReferenceProperty(object): |
| 122 pass | 121 pass |
| OLD | NEW |