Skip to content
This repository was archived by the owner on Jan 12, 2022. It is now read-only.

Commit 7e41394

Browse files
committed
Merge pull request #87 from GoogleCloudPlatform/update_compat
updating compat to 0.64
2 parents 8fb176a + 50a5dcf commit 7e41394

14 files changed

Lines changed: 243 additions & 69 deletions

File tree

appengine-compat/exported_appengine_sdk/google/appengine/api/blobstore/blobstore.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ def create_upload_url(success_path,
253253
max_bytes_total: The maximum size in bytes that the aggregate sizes of all
254254
of the blobs in the upload can be or None for no maximum size.
255255
rpc: Optional UserRPC object.
256-
gs_bucket_name: The Google Storage bucket name that the blobs should be
257-
uploaded to. The application's service account must have the correct
258-
permissions to write to this bucket. The bucket name may be of the foramt
256+
gs_bucket_name: The Google Cloud Storage bucket name that the blobs should
257+
be uploaded to. The application's service account must have the correct
258+
permissions to write to this bucket. The bucket name may be of the format
259259
'bucket/path/', in which case the included path will be prepended to the
260260
uploaded object name.
261261
@@ -290,9 +290,9 @@ def create_upload_url_async(success_path,
290290
max_bytes_total: The maximum size in bytes that the aggregate sizes of all
291291
of the blobs in the upload can be or None for no maximum size.
292292
rpc: Optional UserRPC object.
293-
gs_bucket_name: The Google Storage bucket name that the blobs should be
294-
uploaded to. The application's service account must have the correct
295-
permissions to write to this bucket. The bucket name may be of the foramt
293+
gs_bucket_name: The Google Cloud Storage bucket name that the blobs should
294+
be uploaded to. The application's service account must have the correct
295+
permissions to write to this bucket. The bucket name may be of the format
296296
'bucket/path/', in which case the included path will be prepended to the
297297
uploaded object name.
298298

appengine-compat/exported_appengine_sdk/google/appengine/api/datastore.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@ class DatastoreAdapter(datastore_rpc.AbstractAdapter):
338338
entity_pb.Index_Property.DESCENDING: Index.DESCENDING
339339
}
340340

341+
def __init__(self, _id_resolver=None):
342+
super(DatastoreAdapter, self).__init__(_id_resolver)
343+
341344
def key_to_pb(self, key):
342345
return key._Key__reference
343346

@@ -384,7 +387,11 @@ def __InitConnection():
384387

385388
if os.getenv(_ENV_KEY) and hasattr(_thread_local, 'connection_stack'):
386389
return
387-
_thread_local.connection_stack = [datastore_rpc.Connection(adapter=_adapter)]
390+
391+
_thread_local.connection_stack = [
392+
datastore_rpc._CreateDefaultConnection(datastore_rpc.Connection,
393+
adapter=_adapter)]
394+
388395

389396
os.environ[_ENV_KEY] = '1'
390397

appengine-compat/exported_appengine_sdk/google/appengine/datastore/datastore_rpc.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2664,6 +2664,168 @@ def __rollback_hook(self, rpc):
26642664
self.check_rpc_success(rpc)
26652665

26662666

2667+
_DATASTORE_APP_ID_ENV = 'DATASTORE_APP_ID'
2668+
_DATASTORE_PROJECT_ID_ENV = 'DATASTORE_PROJECT_ID'
2669+
_DATASTORE_ADDITIONAL_APP_IDS_ENV = 'DATASTORE_ADDITIONAL_APP_IDS'
2670+
_DATASTORE_USE_PROJECT_ID_AS_APP_ID_ENV = 'DATASTORE_USE_PROJECT_ID_AS_APP_ID'
2671+
2672+
2673+
2674+
def _CreateDefaultConnection(connection_fn, **kwargs):
2675+
"""Creates a new connection to Datastore.
2676+
2677+
Uses environment variables to determine if the connection should be made
2678+
to Cloud Datastore v1beta3 or to Datastore's private App Engine API.
2679+
If DATASTORE_PROJECT_ID exists, connect to Datastore v1beta3. In this case,
2680+
either DATASTORE_APP_ID or DATASTORE_USE_PROJECT_ID_AS_APP_ID must be set to
2681+
indicate what the environment's application should be.
2682+
2683+
Args:
2684+
connection_fn: The function to use to create the connection.
2685+
**kwargs: Addition arguments to pass to the connection_fn.
2686+
2687+
Raises:
2688+
ValueError: If DATASTORE_PROJECT_ID is set but DATASTORE_APP_ID or
2689+
DATASTORE_USE_PROJECT_ID_AS_APP_ID is not. If DATASTORE_APP_ID doesn't
2690+
resolve to DATASTORE_PROJECT_ID. If DATASTORE_APP_ID doesn't match
2691+
an existing APPLICATION_ID.
2692+
2693+
Returns:
2694+
the connection object returned from connection_fn.
2695+
"""
2696+
datastore_app_id = os.environ.get(_DATASTORE_APP_ID_ENV, None)
2697+
datastore_project_id = os.environ.get(_DATASTORE_PROJECT_ID_ENV, None)
2698+
if datastore_app_id or datastore_project_id:
2699+
2700+
app_id_override = bool(os.environ.get(
2701+
_DATASTORE_USE_PROJECT_ID_AS_APP_ID_ENV, False))
2702+
if not datastore_app_id and not app_id_override:
2703+
raise ValueError('Could not determine app id. To use project id (%s) '
2704+
'instead, set %s=true. This will affect the '
2705+
'serialized form of entities and should not be used '
2706+
'if serialized entities will be shared between '
2707+
'code running on App Engine and code running off '
2708+
'App Engine. Alternatively, set %s=<app id>.'
2709+
% (datastore_project_id,
2710+
_DATASTORE_USE_PROJECT_ID_AS_APP_ID_ENV,
2711+
_DATASTORE_APP_ID_ENV))
2712+
elif datastore_app_id:
2713+
if app_id_override:
2714+
raise ValueError('App id was provided (%s) but %s was set to true. '
2715+
'Please unset either %s or %s.' %
2716+
(datastore_app_id,
2717+
_DATASTORE_USE_PROJECT_ID_AS_APP_ID_ENV,
2718+
_DATASTORE_APP_ID_ENV,
2719+
_DATASTORE_USE_PROJECT_ID_AS_APP_ID_ENV))
2720+
elif datastore_project_id:
2721+
2722+
id_resolver = datastore_pbs.IdResolver([datastore_app_id])
2723+
if (datastore_project_id !=
2724+
id_resolver.resolve_project_id(datastore_app_id)):
2725+
raise ValueError('App id "%s" does not match project id "%s".'
2726+
% (datastore_app_id, datastore_project_id))
2727+
2728+
datastore_app_id = datastore_app_id or datastore_project_id
2729+
additional_app_str = os.environ.get(_DATASTORE_ADDITIONAL_APP_IDS_ENV, '')
2730+
additional_apps = (app.strip() for app in additional_app_str.split(','))
2731+
return _CreateCloudDatastoreConnection(connection_fn,
2732+
datastore_app_id,
2733+
additional_apps,
2734+
kwargs)
2735+
return connection_fn(**kwargs)
2736+
2737+
2738+
2739+
def _CreateCloudDatastoreConnection(connection_fn,
2740+
app_id,
2741+
external_app_ids,
2742+
kwargs):
2743+
"""Creates a new context to connect to a remote Cloud Datastore instance.
2744+
2745+
This should only be used outside of Google App Engine.
2746+
2747+
Args:
2748+
connection_fn: A connection function which accepts both an _api_version
2749+
and an _id_resolver argument.
2750+
app_id: The application id to connect to. This differs from the project
2751+
id as it may have an additional prefix, e.g. "s~" or "e~".
2752+
external_app_ids: A list of apps that may be referenced by data in your
2753+
application. For example, if you are connected to s~my-app and store keys
2754+
for s~my-other-app, you should include s~my-other-app in the external_apps
2755+
list.
2756+
kwargs: The additional kwargs to pass to the connection_fn.
2757+
2758+
Raises:
2759+
ValueError: if the app_id provided doesn't match the current environment's
2760+
APPLICATION_ID.
2761+
2762+
Returns:
2763+
An ndb.Context that can connect to a Remote Cloud Datastore. You can use
2764+
this context by passing it to ndb.set_context.
2765+
"""
2766+
2767+
2768+
from google.appengine.datastore import cloud_datastore_v1_remote_stub
2769+
2770+
if not datastore_pbs._CLOUD_DATASTORE_ENABLED:
2771+
raise datastore_errors.BadArgumentError(
2772+
datastore_pbs.MISSING_CLOUD_DATASTORE_MESSAGE)
2773+
2774+
current_app_id = os.environ.get('APPLICATION_ID', None)
2775+
if current_app_id and current_app_id != app_id:
2776+
2777+
2778+
raise ValueError('Cannot create a Cloud Datastore context that connects '
2779+
'to an application (%s) that differs from the application '
2780+
'already connected to (%s).' % (app_id, current_app_id))
2781+
os.environ['APPLICATION_ID'] = app_id
2782+
2783+
id_resolver = datastore_pbs.IdResolver((app_id,) + tuple(external_app_ids))
2784+
project_id = id_resolver.resolve_project_id(app_id)
2785+
endpoint = googledatastore.helper.get_project_endpoint_from_env(project_id)
2786+
datastore = googledatastore.Datastore(
2787+
project_endpoint=endpoint,
2788+
credentials=googledatastore.helper.get_credentials_from_env())
2789+
kwargs['_api_version'] = _CLOUD_DATASTORE_V1
2790+
kwargs['_id_resolver'] = id_resolver
2791+
conn = connection_fn(**kwargs)
2792+
2793+
2794+
2795+
try:
2796+
stub = cloud_datastore_v1_remote_stub.CloudDatastoreV1RemoteStub(datastore)
2797+
apiproxy_stub_map.apiproxy.RegisterStub(_CLOUD_DATASTORE_V1,
2798+
stub)
2799+
except:
2800+
pass
2801+
2802+
2803+
2804+
try:
2805+
apiproxy_stub_map.apiproxy.RegisterStub('memcache', _ThrowingStub())
2806+
except:
2807+
pass
2808+
try:
2809+
apiproxy_stub_map.apiproxy.RegisterStub('taskqueue', _ThrowingStub())
2810+
except:
2811+
pass
2812+
2813+
return conn
2814+
2815+
2816+
class _ThrowingStub(object):
2817+
"""A Stub implementation which always throws a NotImplementedError."""
2818+
2819+
2820+
def MakeSyncCall(self, service, call, request, response):
2821+
raise NotImplementedError('In order to use %s.%s you must '
2822+
'install the Remote API.' % (service, call))
2823+
2824+
2825+
def CreateRPC(self):
2826+
return apiproxy_rpc.RPC(stub=self)
2827+
2828+
26672829

26682830

26692831

appengine-compat/exported_appengine_sdk/google/appengine/ext/vmruntime/callback.py

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,44 +28,31 @@
2828
_callback_storage = {}
2929

3030

31-
class OnlyOneCallbackPerRequestException(Exception):
32-
"""Raised when a second callback is set in a single request."""
33-
34-
3531
def SetRequestEndCallback(callback):
3632
"""Stores a callback by the request ID.
3733
3834
The request ID currently uses the cloud trace ID.
3935
4036
Args:
4137
callback: A zero-argument callable whose return value is unused.
42-
43-
Raises:
44-
OnlyOneCallbackPerRequestException: Raised on registering second callback.
4538
"""
4639
key = _GetRequestId()
4740

4841

4942

5043

5144
if key:
52-
53-
54-
55-
56-
57-
if key not in _callback_storage:
58-
_callback_storage[key] = callback
59-
else:
60-
raise OnlyOneCallbackPerRequestException()
45+
_callback_storage.setdefault(key, []).append(callback)
6146

6247

6348
def InvokeCallbacks():
64-
"""Invokes the callback associated with the current request ID."""
49+
"""Invokes the callbacks associated with the current request ID."""
6550

6651
key = _GetRequestId()
6752
if key in _callback_storage:
68-
_callback_storage[key]()
53+
for callback in _callback_storage[key]:
54+
callback()
55+
6956
del _callback_storage[key]
7057

7158

appengine-compat/exported_appengine_sdk/google/appengine/tools/dev-channel-js.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,9 @@ goog.array.copyByIndex = function(arr, index_arr) {
15201520
});
15211521
return result;
15221522
};
1523+
goog.array.concatMap = function(arr, f, opt_obj) {
1524+
return goog.array.concat.apply([], goog.array.map(arr, f, opt_obj));
1525+
};
15231526
goog.dom.TagName = {A:"A", ABBR:"ABBR", ACRONYM:"ACRONYM", ADDRESS:"ADDRESS", APPLET:"APPLET", AREA:"AREA", ARTICLE:"ARTICLE", ASIDE:"ASIDE", AUDIO:"AUDIO", B:"B", BASE:"BASE", BASEFONT:"BASEFONT", BDI:"BDI", BDO:"BDO", BIG:"BIG", BLOCKQUOTE:"BLOCKQUOTE", BODY:"BODY", BR:"BR", BUTTON:"BUTTON", CANVAS:"CANVAS", CAPTION:"CAPTION", CENTER:"CENTER", CITE:"CITE", CODE:"CODE", COL:"COL", COLGROUP:"COLGROUP", COMMAND:"COMMAND", DATA:"DATA", DATALIST:"DATALIST", DD:"DD", DEL:"DEL", DETAILS:"DETAILS", DFN:"DFN",
15241527
DIALOG:"DIALOG", DIR:"DIR", DIV:"DIV", DL:"DL", DT:"DT", EM:"EM", EMBED:"EMBED", FIELDSET:"FIELDSET", FIGCAPTION:"FIGCAPTION", FIGURE:"FIGURE", FONT:"FONT", FOOTER:"FOOTER", FORM:"FORM", FRAME:"FRAME", FRAMESET:"FRAMESET", H1:"H1", H2:"H2", H3:"H3", H4:"H4", H5:"H5", H6:"H6", HEAD:"HEAD", HEADER:"HEADER", HGROUP:"HGROUP", HR:"HR", HTML:"HTML", I:"I", IFRAME:"IFRAME", IMG:"IMG", INPUT:"INPUT", INS:"INS", ISINDEX:"ISINDEX", KBD:"KBD", KEYGEN:"KEYGEN", LABEL:"LABEL", LEGEND:"LEGEND", LI:"LI", LINK:"LINK",
15251528
MAP:"MAP", MARK:"MARK", MATH:"MATH", MENU:"MENU", META:"META", METER:"METER", NAV:"NAV", NOFRAMES:"NOFRAMES", NOSCRIPT:"NOSCRIPT", OBJECT:"OBJECT", OL:"OL", OPTGROUP:"OPTGROUP", OPTION:"OPTION", OUTPUT:"OUTPUT", P:"P", PARAM:"PARAM", PRE:"PRE", PROGRESS:"PROGRESS", Q:"Q", RP:"RP", RT:"RT", RUBY:"RUBY", S:"S", SAMP:"SAMP", SCRIPT:"SCRIPT", SECTION:"SECTION", SELECT:"SELECT", SMALL:"SMALL", SOURCE:"SOURCE", SPAN:"SPAN", STRIKE:"STRIKE", STRONG:"STRONG", STYLE:"STYLE", SUB:"SUB", SUMMARY:"SUMMARY",

0 commit comments

Comments
 (0)