appengine-python-standard 1.2.0b0__tar.gz → 1.3.0b0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {appengine_python_standard-1.2.0b0/src/appengine_python_standard.egg-info → appengine_python_standard-1.3.0b0}/PKG-INFO +2 -1
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/setup.py +2 -1
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0/src/appengine_python_standard.egg-info}/PKG-INFO +2 -1
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/appengine_python_standard.egg-info/requires.txt +1 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/mail.py +9 -68
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/modules/modules.py +366 -17
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/LICENSE +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/README.md +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/setup.cfg +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/appengine_python_standard.egg-info/SOURCES.txt +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/appengine_python_standard.egg-info/dependency_links.txt +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/appengine_python_standard.egg-info/namespace_packages.txt +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/appengine_python_standard.egg-info/top_level.txt +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/compat.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/constants.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/dfa.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/dottreegen.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/exceptions.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/extras.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/main.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/recognizers.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/streams.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/tokens.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/tree.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/antlr3/treewizard.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/definition.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/descriptor.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/descriptor2py.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/gen_protorpc.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/generate.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/generate_proto.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/generate_python.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/message_types.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/messages.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/non_sdk_imports.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/protobuf.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/protobuf_base.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/protojson.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/protourlencode.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/registry.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/remote.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/transport.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/wsgi/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/wsgi/service.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/_internal/protorpc/wsgi/util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/api_base_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/api_testutil.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/apiproxy_rpc.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/apiproxy_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/apiproxy_stub_map.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/_metadata_server.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/app_identity.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/app_identity_defaultcredentialsbased_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/app_identity_keybased_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/app_identity_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/app_identity_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/app_identity/app_identity_stub_base.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/appinfo.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/appinfo_errors.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/backendinfo.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/background_thread/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/background_thread/background_thread.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/blob_storage.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/blobstore.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/blobstore_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/blobstore_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/blobstore_stub_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/dict_blob_storage.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/blobstore/file_blob_storage.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/capabilities/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/capabilities/capability_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/capabilities/capability_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/cmp_compat.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/croninfo.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/datastore.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/datastore_admin.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/datastore_entities.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/datastore_errors.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/datastore_file_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/datastore_types.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/dispatchinfo.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/full_app_id.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/images/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/images/image_comparison.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/images/images_blob_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/images/images_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/images/images_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/lib_config.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/mail_errors.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/mail_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/mail_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/mail_stub_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/memcache/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/memcache/memcache_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/memcache/memcache_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/memcache/memcache_stub_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/module_testutil.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/modules/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/modules/modules_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/modules/modules_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/namespace_manager/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/namespace_manager/namespace_manager.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/oauth/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/oauth/oauth_api.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/queueinfo.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/request_info.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/runtime/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/runtime/runtime.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/ExpressionLexer.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/ExpressionParser.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/QueryLexer.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/QueryParser.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/expression_parser.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/geo_util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/query_parser.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/search.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/search_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/search_util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/simple_search_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/stub/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/stub/document_matcher.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/stub/expression_evaluator.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/stub/simple_facet.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/stub/simple_tokenizer.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/stub/tokens.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/search/unicode_util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/stublib.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/system/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/system/system_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/system/system_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/taskqueue/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/taskqueue/taskqueue.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/taskqueue/taskqueue_service_bytes_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/taskqueue/taskqueue_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/titanoboa_request_info.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/urlfetch.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/urlfetch_errors.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/urlfetch_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/urlfetch_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/user_service_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/user_service_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/users.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/validation.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/yaml_builder.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/yaml_errors.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/yaml_listener.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/yaml_object.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/api/yaml_test_util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/base/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/base/capabilities_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/action_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/cloud_datastore_v1_remote_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/cloud_datastore_v1_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/cloud_datastore_validator.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_index.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_index_xml.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_pb.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_pbs.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_query.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_rpc.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_stub_index.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_stub_util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_v3_bytes_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_v4_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_v4_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/datastore_v4_validator.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/document_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/entity_bytes_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/entity_v4_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/snapshot_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/datastore/sortable_pb_encoder.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/blobstore/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/blobstore/blobstore.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/db/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/db/metadata.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/db/polymodel.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/db/stats.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/db/sync.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/deferred/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/deferred/deferred.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/gql/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/key_range/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/blobstore.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/context.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/django_middleware.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/eventloop.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/key.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/key_test.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/metadata.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/model.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/msgprop.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/polymodel.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/query.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/stats.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/tasklets.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/test_utils.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/ndb/utils.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/remote_api/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/remote_api/remote_api_bytes_pb2.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/ext/testbed/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/apiproxy.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/apiproxy_errors.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/background.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/callback.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/context/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/context/ctx_test_util.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/context/gae_headers.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/context/wsgi.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/default_api_stub.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/initialize.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/middlewares.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/request_environment.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/runtime/thread_hooks.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/tools/__init__.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/tools/app_engine_config_exception.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/tools/os_compat.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/tools/queue_xml_parser.py +0 -0
- {appengine_python_standard-1.2.0b0 → appengine_python_standard-1.3.0b0}/src/google/appengine/tools/xml_parser_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: appengine-python-standard
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0b0
|
|
4
4
|
Summary: Google App Engine services SDK for Python 3
|
|
5
5
|
Home-page: https://github.com/GoogleCloudPlatform/appengine-python-standard
|
|
6
6
|
Author: Google LLC
|
|
@@ -22,6 +22,7 @@ Requires-Dist: ruamel.yaml>=0.17.7
|
|
|
22
22
|
Requires-Dist: six>=1.15.0
|
|
23
23
|
Requires-Dist: urllib3<2,>=1.26.2
|
|
24
24
|
Requires-Dist: legacy-cgi>=2.6.2; python_version >= "3.10"
|
|
25
|
+
Requires-Dist: google-api-python-client
|
|
25
26
|
Dynamic: author
|
|
26
27
|
Dynamic: classifier
|
|
27
28
|
Dynamic: description
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="appengine-python-standard",
|
|
8
|
-
version="1.
|
|
8
|
+
version="1.3.0-beta",
|
|
9
9
|
author="Google LLC",
|
|
10
10
|
description="Google App Engine services SDK for Python 3",
|
|
11
11
|
long_description=long_description,
|
|
@@ -27,6 +27,7 @@ setuptools.setup(
|
|
|
27
27
|
"six>=1.15.0",
|
|
28
28
|
"urllib3>=1.26.2,<2",
|
|
29
29
|
"legacy-cgi>=2.6.2; python_version>='3.10'",
|
|
30
|
+
"google-api-python-client"
|
|
30
31
|
],
|
|
31
32
|
classifiers=[
|
|
32
33
|
"Programming Language :: Python :: 3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: appengine-python-standard
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0b0
|
|
4
4
|
Summary: Google App Engine services SDK for Python 3
|
|
5
5
|
Home-page: https://github.com/GoogleCloudPlatform/appengine-python-standard
|
|
6
6
|
Author: Google LLC
|
|
@@ -22,6 +22,7 @@ Requires-Dist: ruamel.yaml>=0.17.7
|
|
|
22
22
|
Requires-Dist: six>=1.15.0
|
|
23
23
|
Requires-Dist: urllib3<2,>=1.26.2
|
|
24
24
|
Requires-Dist: legacy-cgi>=2.6.2; python_version >= "3.10"
|
|
25
|
+
Requires-Dist: google-api-python-client
|
|
25
26
|
Dynamic: author
|
|
26
27
|
Dynamic: classifier
|
|
27
28
|
Dynamic: description
|
|
@@ -45,8 +45,6 @@ from email.mime.multipart import MIMEMultipart
|
|
|
45
45
|
from email.mime.text import MIMEText
|
|
46
46
|
import functools
|
|
47
47
|
import logging
|
|
48
|
-
import os
|
|
49
|
-
import smtplib
|
|
50
48
|
import typing
|
|
51
49
|
|
|
52
50
|
from google.appengine.api import api_base_pb2
|
|
@@ -1199,77 +1197,20 @@ class _EmailMessageBase(object):
|
|
|
1199
1197
|
return self.to_mime_message()
|
|
1200
1198
|
|
|
1201
1199
|
def send(self, make_sync_call=apiproxy_stub_map.MakeSyncCall):
|
|
1202
|
-
"""Sends an email message via the Mail API
|
|
1203
|
-
|
|
1204
|
-
If the 'USE_SMTP_MAIL_SERVICE' environment variable is set to 'true', this
|
|
1205
|
-
method will send the email via SMTP using credentials from other
|
|
1206
|
-
environment variables. Otherwise, it falls back to the App Engine Mail API.
|
|
1200
|
+
"""Sends an email message via the Mail API.
|
|
1207
1201
|
|
|
1208
1202
|
Args:
|
|
1209
1203
|
make_sync_call: Method that will make a synchronous call to the API proxy.
|
|
1210
1204
|
"""
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
mime_message = self.to_mime_message()
|
|
1214
|
-
|
|
1215
|
-
# The Bcc header should not be in the final message.
|
|
1216
|
-
if 'Bcc' in mime_message:
|
|
1217
|
-
del mime_message['Bcc']
|
|
1218
|
-
|
|
1219
|
-
recipients = []
|
|
1220
|
-
if isinstance(self, AdminEmailMessage):
|
|
1221
|
-
admin_emails = os.environ.get('APPENGINE_ADMIN_EMAIL_RECIPIENTS')
|
|
1222
|
-
if admin_emails:
|
|
1223
|
-
recipients.extend(admin_emails.split(','))
|
|
1224
|
-
else:
|
|
1225
|
-
if hasattr(self, 'to'):
|
|
1226
|
-
recipients.extend(_email_sequence(self.to))
|
|
1227
|
-
if hasattr(self, 'cc'):
|
|
1228
|
-
recipients.extend(_email_sequence(self.cc))
|
|
1229
|
-
if hasattr(self, 'bcc'):
|
|
1230
|
-
recipients.extend(_email_sequence(self.bcc))
|
|
1231
|
-
|
|
1232
|
-
if not recipients:
|
|
1233
|
-
raise MissingRecipientsError()
|
|
1234
|
-
|
|
1235
|
-
try:
|
|
1236
|
-
host = os.environ['APPENGINE_SMTP_HOST']
|
|
1237
|
-
port = int(os.environ.get('APPENGINE_SMTP_PORT', 587))
|
|
1238
|
-
user = os.environ.get('APPENGINE_SMTP_USER')
|
|
1239
|
-
password = os.environ.get('APPENGINE_SMTP_PASSWORD')
|
|
1240
|
-
use_tls = os.environ.get('APPENGINE_SMTP_USE_TLS', 'true').lower() == 'true'
|
|
1241
|
-
|
|
1242
|
-
with smtplib.SMTP(host, port) as server:
|
|
1243
|
-
if use_tls:
|
|
1244
|
-
server.starttls()
|
|
1245
|
-
if user and password:
|
|
1246
|
-
server.login(user, password)
|
|
1247
|
-
server.send_message(mime_message, from_addr=self.sender, to_addrs=recipients)
|
|
1248
|
-
logging.info('Email sent successfully via SMTP.')
|
|
1249
|
-
|
|
1250
|
-
except smtplib.SMTPAuthenticationError as e:
|
|
1251
|
-
logging.error('SMTP authentication failed: %s', e.smtp_error)
|
|
1252
|
-
raise InvalidSenderError(f'SMTP authentication failed: {e.smtp_error}')
|
|
1253
|
-
except (smtplib.SMTPException, OSError) as e:
|
|
1254
|
-
logging.error('Failed to send email via SMTP: %s', e)
|
|
1255
|
-
raise Error(f'Failed to send email via SMTP: {e}')
|
|
1256
|
-
except KeyError as e:
|
|
1257
|
-
logging.error('Missing required SMTP environment variable: %s', e)
|
|
1258
|
-
raise Error(f'Missing required SMTP environment variable: {e}')
|
|
1205
|
+
message = self.ToProto()
|
|
1206
|
+
response = api_base_pb2.VoidProto()
|
|
1259
1207
|
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
make_sync_call('mail', self._API_CALL, message, response)
|
|
1267
|
-
logging.info('Email sent successfully via App Engine Mail API.')
|
|
1268
|
-
except apiproxy_errors.ApplicationError as e:
|
|
1269
|
-
logging.error('App Engine Mail API error: %s', e)
|
|
1270
|
-
if e.application_error in ERROR_MAP:
|
|
1271
|
-
raise ERROR_MAP[e.application_error](e.error_detail)
|
|
1272
|
-
raise e
|
|
1208
|
+
try:
|
|
1209
|
+
make_sync_call('mail', self._API_CALL, message, response)
|
|
1210
|
+
except apiproxy_errors.ApplicationError as e:
|
|
1211
|
+
if e.application_error in ERROR_MAP:
|
|
1212
|
+
raise ERROR_MAP[e.application_error](e.error_detail)
|
|
1213
|
+
raise e
|
|
1273
1214
|
|
|
1274
1215
|
|
|
1275
1216
|
def Send(self, *args, **kwds):
|
|
@@ -22,6 +22,20 @@ Using the Modules guide:
|
|
|
22
22
|
https://cloud.google.com/appengine/docs/standard/python/using-the-modules-api.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
+
import logging
|
|
26
|
+
import os
|
|
27
|
+
import threading
|
|
28
|
+
|
|
29
|
+
from google.appengine.api import apiproxy_stub_map
|
|
30
|
+
from google.appengine.api.modules import modules_service_pb2
|
|
31
|
+
from google.appengine.runtime import apiproxy_errors
|
|
32
|
+
from googleapiclient import discovery, errors, http
|
|
33
|
+
from google_auth_httplib2 import AuthorizedHttp
|
|
34
|
+
import google.auth
|
|
35
|
+
import six
|
|
36
|
+
import httplib2
|
|
37
|
+
|
|
38
|
+
|
|
25
39
|
__all__ = [
|
|
26
40
|
'Error',
|
|
27
41
|
'InvalidModuleError',
|
|
@@ -46,16 +60,6 @@ __all__ = [
|
|
|
46
60
|
'get_hostname'
|
|
47
61
|
]
|
|
48
62
|
|
|
49
|
-
import logging
|
|
50
|
-
import os
|
|
51
|
-
|
|
52
|
-
import six
|
|
53
|
-
|
|
54
|
-
from google.appengine.api import apiproxy_stub_map
|
|
55
|
-
from google.appengine.api.modules import modules_service_pb2
|
|
56
|
-
from google.appengine.runtime import apiproxy_errors
|
|
57
|
-
|
|
58
|
-
|
|
59
63
|
class Error(Exception):
|
|
60
64
|
"""Base-class for errors in this module."""
|
|
61
65
|
|
|
@@ -79,6 +83,28 @@ class UnexpectedStateError(Error):
|
|
|
79
83
|
class TransientError(Error):
|
|
80
84
|
"""A transient error was encountered, retry the operation."""
|
|
81
85
|
|
|
86
|
+
def _has_opted_in():
|
|
87
|
+
return (os.environ.get('APPENGINE_MODULES_USE_ADMIN_API', 'false').lower() == 'true')
|
|
88
|
+
|
|
89
|
+
def _raise_error(e):
|
|
90
|
+
# Translate HTTP errors to the exceptions expected by the API
|
|
91
|
+
if e.resp.status == 400:
|
|
92
|
+
raise InvalidInstancesError(e) from e
|
|
93
|
+
elif e.resp.status == 404:
|
|
94
|
+
raise InvalidVersionError(e) from e
|
|
95
|
+
elif e.resp.status >= 500:
|
|
96
|
+
raise TransientError(e) from e
|
|
97
|
+
else:
|
|
98
|
+
raise Error(e) from e
|
|
99
|
+
|
|
100
|
+
def _get_project_id():
|
|
101
|
+
project_id = os.environ.get('GAE_PROJECT') or os.environ.get(
|
|
102
|
+
'GOOGLE_CLOUD_PROJECT'
|
|
103
|
+
)
|
|
104
|
+
if project_id is None:
|
|
105
|
+
app_id = os.environ.get('GAE_APPLICATION')
|
|
106
|
+
project_id = app_id.split('~', 1)[1]
|
|
107
|
+
return project_id
|
|
82
108
|
|
|
83
109
|
def get_current_module_name():
|
|
84
110
|
"""Returns the module name of the current instance.
|
|
@@ -120,16 +146,44 @@ def get_current_instance_id():
|
|
|
120
146
|
return os.environ.get('GAE_INSTANCE') or os.environ.get('INSTANCE_ID', None)
|
|
121
147
|
|
|
122
148
|
|
|
149
|
+
class _ThreadedRpc:
|
|
150
|
+
"""A class to emulate the UserRPC object for threaded operations."""
|
|
151
|
+
|
|
152
|
+
def __init__(self, target):
|
|
153
|
+
self.thread = threading.Thread(target=self._run_target, args=(target,))
|
|
154
|
+
self.exception = None
|
|
155
|
+
self.done = threading.Event()
|
|
156
|
+
self.thread.start()
|
|
157
|
+
|
|
158
|
+
def _run_target(self, target):
|
|
159
|
+
try:
|
|
160
|
+
target()
|
|
161
|
+
except Exception as e:
|
|
162
|
+
self.exception = e
|
|
163
|
+
finally:
|
|
164
|
+
self.done.set()
|
|
165
|
+
|
|
166
|
+
def wait(self):
|
|
167
|
+
self.done.wait()
|
|
168
|
+
|
|
169
|
+
def check_success(self):
|
|
170
|
+
if self.exception:
|
|
171
|
+
raise self.exception
|
|
172
|
+
|
|
173
|
+
def get_result(self):
|
|
174
|
+
self.wait()
|
|
175
|
+
self.check_success()
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
|
|
123
179
|
def _GetRpc():
|
|
124
180
|
return apiproxy_stub_map.UserRPC('modules')
|
|
125
181
|
|
|
126
|
-
|
|
127
182
|
def _MakeAsyncCall(method, request, response, get_result_hook):
|
|
128
183
|
rpc = _GetRpc()
|
|
129
184
|
rpc.make_call(method, request, response, get_result_hook)
|
|
130
185
|
return rpc
|
|
131
186
|
|
|
132
|
-
|
|
133
187
|
_MODULE_SERVICE_ERROR_MAP = {
|
|
134
188
|
modules_service_pb2.ModulesServiceError.INVALID_INSTANCES:
|
|
135
189
|
InvalidInstancesError,
|
|
@@ -143,7 +197,6 @@ _MODULE_SERVICE_ERROR_MAP = {
|
|
|
143
197
|
UnexpectedStateError
|
|
144
198
|
}
|
|
145
199
|
|
|
146
|
-
|
|
147
200
|
def _CheckAsyncResult(rpc, expected_application_errors,
|
|
148
201
|
ignored_application_errors):
|
|
149
202
|
try:
|
|
@@ -158,6 +211,14 @@ def _CheckAsyncResult(rpc, expected_application_errors,
|
|
|
158
211
|
raise mapped_error()
|
|
159
212
|
raise Error(e)
|
|
160
213
|
|
|
214
|
+
def _get_admin_api_client_with_useragent(methodName):
|
|
215
|
+
userAgent = 'appengine-modules-api-python-client/' + methodName
|
|
216
|
+
http_client = httplib2.Http(timeout=60)
|
|
217
|
+
http_client = http.set_user_agent(http_client, userAgent)
|
|
218
|
+
credentials,_ = google.auth.default()
|
|
219
|
+
authorized_http = AuthorizedHttp(credentials, http=http_client)
|
|
220
|
+
client = discovery.build('appengine', 'v1', http=authorized_http)
|
|
221
|
+
return client
|
|
161
222
|
|
|
162
223
|
def get_modules():
|
|
163
224
|
"""Returns a list of all modules for the application.
|
|
@@ -167,8 +228,29 @@ def get_modules():
|
|
|
167
228
|
application. The 'default' module will be included if it exists, as will
|
|
168
229
|
the name of the module that is associated with the instance that calls
|
|
169
230
|
this function.
|
|
231
|
+
|
|
232
|
+
Raises:
|
|
233
|
+
Error: If the configured project ID is invalid.
|
|
234
|
+
TransientError: If there is an issue fetching the information.
|
|
170
235
|
"""
|
|
236
|
+
if not _has_opted_in():
|
|
237
|
+
return get_modules_legacy()
|
|
238
|
+
|
|
239
|
+
project_id = _get_project_id()
|
|
240
|
+
client = _get_admin_api_client_with_useragent('get_modules')
|
|
241
|
+
request = client.apps().services().list(appsId=project_id)
|
|
242
|
+
|
|
243
|
+
try:
|
|
244
|
+
response = request.execute()
|
|
245
|
+
except errors.HttpError as e:
|
|
246
|
+
if e.resp.status == 404:
|
|
247
|
+
raise Error(f"Project '{project_id}' not found.") from e
|
|
248
|
+
_raise_error(e)
|
|
249
|
+
|
|
250
|
+
return [service['id'] for service in response.get('services', [])]
|
|
171
251
|
|
|
252
|
+
#Legacy get_modules implementation
|
|
253
|
+
def get_modules_legacy():
|
|
172
254
|
def _ResultHook(rpc):
|
|
173
255
|
_CheckAsyncResult(rpc, [], {})
|
|
174
256
|
|
|
@@ -181,6 +263,7 @@ def get_modules():
|
|
|
181
263
|
_ResultHook).get_result()
|
|
182
264
|
|
|
183
265
|
|
|
266
|
+
|
|
184
267
|
def get_versions(module=None):
|
|
185
268
|
"""Returns a list of versions for a given module.
|
|
186
269
|
|
|
@@ -196,7 +279,27 @@ def get_versions(module=None):
|
|
|
196
279
|
`InvalidModuleError` if the given module isn't valid, `TransientError` if
|
|
197
280
|
there is an issue fetching the information.
|
|
198
281
|
"""
|
|
282
|
+
if not _has_opted_in():
|
|
283
|
+
return get_versions_legacy(module=module)
|
|
284
|
+
|
|
285
|
+
if not module:
|
|
286
|
+
module = os.environ.get('GAE_SERVICE', 'default')
|
|
287
|
+
|
|
288
|
+
project_id = _get_project_id()
|
|
289
|
+
client = _get_admin_api_client_with_useragent('get_versions')
|
|
290
|
+
request = client.apps().services().versions().list(
|
|
291
|
+
appsId=project_id, servicesId=module, view='FULL'
|
|
292
|
+
)
|
|
293
|
+
try:
|
|
294
|
+
response = request.execute()
|
|
295
|
+
except errors.HttpError as e:
|
|
296
|
+
if e.resp.status == 404:
|
|
297
|
+
raise InvalidModuleError(f"") from e
|
|
298
|
+
_raise_error(e)
|
|
199
299
|
|
|
300
|
+
return [version['id'] for version in response.get('versions', [])]
|
|
301
|
+
|
|
302
|
+
def get_versions_legacy(module=None):
|
|
200
303
|
def _ResultHook(rpc):
|
|
201
304
|
mapped_errors = [
|
|
202
305
|
modules_service_pb2.ModulesServiceError.INVALID_MODULE,
|
|
@@ -212,7 +315,8 @@ def get_versions(module=None):
|
|
|
212
315
|
request.module = module
|
|
213
316
|
response = modules_service_pb2.GetVersionsResponse()
|
|
214
317
|
return _MakeAsyncCall('GetVersions', request, response,
|
|
215
|
-
_ResultHook).get_result()
|
|
318
|
+
_ResultHook).get_result()
|
|
319
|
+
|
|
216
320
|
|
|
217
321
|
|
|
218
322
|
def get_default_version(module=None):
|
|
@@ -230,6 +334,46 @@ def get_default_version(module=None):
|
|
|
230
334
|
if no default version could be found.
|
|
231
335
|
"""
|
|
232
336
|
|
|
337
|
+
if not _has_opted_in():
|
|
338
|
+
return get_default_version_legacy(module=module)
|
|
339
|
+
|
|
340
|
+
if not module:
|
|
341
|
+
module = os.environ.get('GAE_SERVICE', 'default')
|
|
342
|
+
project = _get_project_id()
|
|
343
|
+
client = _get_admin_api_client_with_useragent('get_default_version')
|
|
344
|
+
request = client.apps().services().get(
|
|
345
|
+
appsId=project, servicesId=module)
|
|
346
|
+
|
|
347
|
+
try:
|
|
348
|
+
response = request.execute()
|
|
349
|
+
except errors.HttpError as e:
|
|
350
|
+
if e.resp.status == 404:
|
|
351
|
+
raise InvalidModuleError(f"") from e
|
|
352
|
+
_raise_error(e)
|
|
353
|
+
|
|
354
|
+
allocations = response.get('split', {}).get('allocations')
|
|
355
|
+
maxAlloc = -1
|
|
356
|
+
retVersion = None
|
|
357
|
+
|
|
358
|
+
if allocations:
|
|
359
|
+
for version, allocation in allocations.items():
|
|
360
|
+
if allocation == 1.0:
|
|
361
|
+
retVersion = version
|
|
362
|
+
break
|
|
363
|
+
|
|
364
|
+
if allocation > maxAlloc:
|
|
365
|
+
retVersion = version
|
|
366
|
+
maxAlloc = allocation
|
|
367
|
+
elif allocation == maxAlloc:
|
|
368
|
+
if version < retVersion:
|
|
369
|
+
retVersion = version
|
|
370
|
+
|
|
371
|
+
if retVersion is None:
|
|
372
|
+
raise InvalidVersionError(f"Could not determine default version for module '{module}'.")
|
|
373
|
+
|
|
374
|
+
return retVersion
|
|
375
|
+
|
|
376
|
+
def get_default_version_legacy(module):
|
|
233
377
|
def _ResultHook(rpc):
|
|
234
378
|
mapped_errors = [
|
|
235
379
|
modules_service_pb2.ModulesServiceError.INVALID_MODULE,
|
|
@@ -269,7 +413,34 @@ def get_num_instances(
|
|
|
269
413
|
Raises:
|
|
270
414
|
`InvalidVersionError` on invalid input.
|
|
271
415
|
"""
|
|
416
|
+
if not _has_opted_in():
|
|
417
|
+
return get_num_instances_legacy(module=module, version=version)
|
|
418
|
+
|
|
419
|
+
if module is None:
|
|
420
|
+
module = get_current_module_name()
|
|
421
|
+
|
|
422
|
+
if version is None:
|
|
423
|
+
version = get_current_version_name()
|
|
272
424
|
|
|
425
|
+
project_id = _get_project_id()
|
|
426
|
+
client = _get_admin_api_client_with_useragent('get_num_instances')
|
|
427
|
+
request = client.apps().services().versions().get(
|
|
428
|
+
appsId=project_id, servicesId=module, versionsId=version)
|
|
429
|
+
|
|
430
|
+
try:
|
|
431
|
+
response = request.execute()
|
|
432
|
+
except errors.HttpError as e:
|
|
433
|
+
if e.resp.status == 404:
|
|
434
|
+
raise InvalidModuleError(f"") from e
|
|
435
|
+
_raise_error(e)
|
|
436
|
+
|
|
437
|
+
if 'manualScaling' not in response:
|
|
438
|
+
raise InvalidVersionError(f"")
|
|
439
|
+
|
|
440
|
+
return response['manualScaling'].get('instances')
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def get_num_instances_legacy(module, version):
|
|
273
444
|
def _ResultHook(rpc):
|
|
274
445
|
mapped_errors = [modules_service_pb2.ModulesServiceError.INVALID_VERSION]
|
|
275
446
|
_CheckAsyncResult(rpc, mapped_errors, {})
|
|
@@ -285,6 +456,23 @@ def get_num_instances(
|
|
|
285
456
|
_ResultHook).get_result()
|
|
286
457
|
|
|
287
458
|
|
|
459
|
+
def _admin_api_version_patch(project_id, module, version, body, update_mask):
|
|
460
|
+
methodName = ''
|
|
461
|
+
if 'manualScaling' in body:
|
|
462
|
+
methodName = 'set_num_instances'
|
|
463
|
+
elif 'servingStatus' in body and body['servingStatus'] == 'SERVING':
|
|
464
|
+
methodName = 'start_version'
|
|
465
|
+
elif 'servingStatus' in body and body['servingStatus'] == 'STOPPED':
|
|
466
|
+
methodName = 'stop_version'
|
|
467
|
+
|
|
468
|
+
client = _get_admin_api_client_with_useragent(methodName)
|
|
469
|
+
client.apps().services().versions().patch(
|
|
470
|
+
appsId=project_id,
|
|
471
|
+
servicesId=module,
|
|
472
|
+
versionsId=version,
|
|
473
|
+
updateMask=update_mask,
|
|
474
|
+
body=body).execute()
|
|
475
|
+
|
|
288
476
|
def set_num_instances(
|
|
289
477
|
instances,
|
|
290
478
|
module=None,
|
|
@@ -324,6 +512,33 @@ def set_num_instances_async(
|
|
|
324
512
|
A `UserRPC` to set the number of instances on the module version.
|
|
325
513
|
"""
|
|
326
514
|
|
|
515
|
+
if not _has_opted_in():
|
|
516
|
+
return set_num_instances_async_legacy(instances=instances, module=module, version=version)
|
|
517
|
+
|
|
518
|
+
if not isinstance(instances, six.integer_types):
|
|
519
|
+
raise TypeError("'instances' arg must be of type long or int.")
|
|
520
|
+
|
|
521
|
+
project_id = _get_project_id()
|
|
522
|
+
if module is None:
|
|
523
|
+
module = get_current_module_name()
|
|
524
|
+
if version is None:
|
|
525
|
+
version = get_current_version_name()
|
|
526
|
+
|
|
527
|
+
def run_request():
|
|
528
|
+
"""This function will be executed in a separate thread."""
|
|
529
|
+
try:
|
|
530
|
+
body = {
|
|
531
|
+
'manualScaling': {
|
|
532
|
+
'instances': instances
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
_admin_api_version_patch(project_id, module, version, body, 'manualScaling.instances')
|
|
536
|
+
except errors.HttpError as e:
|
|
537
|
+
_raise_error(e)
|
|
538
|
+
|
|
539
|
+
return _ThreadedRpc(target=run_request)
|
|
540
|
+
|
|
541
|
+
def set_num_instances_async_legacy(instances, module, version):
|
|
327
542
|
def _ResultHook(rpc):
|
|
328
543
|
mapped_errors = [
|
|
329
544
|
modules_service_pb2.ModulesServiceError.INVALID_VERSION,
|
|
@@ -370,7 +585,28 @@ def start_version_async(
|
|
|
370
585
|
Returns:
|
|
371
586
|
A `UserRPC` to start all instances for the given module version.
|
|
372
587
|
"""
|
|
373
|
-
|
|
588
|
+
if not _has_opted_in():
|
|
589
|
+
return start_version_async_legacy(module=module, version=version)
|
|
590
|
+
|
|
591
|
+
if module is None:
|
|
592
|
+
module = get_current_module_name()
|
|
593
|
+
|
|
594
|
+
if version is None:
|
|
595
|
+
version = get_current_version_name()
|
|
596
|
+
project_id = _get_project_id()
|
|
597
|
+
def run_request():
|
|
598
|
+
"""This function will be executed in a separate thread."""
|
|
599
|
+
try:
|
|
600
|
+
body = {
|
|
601
|
+
'servingStatus': 'SERVING'
|
|
602
|
+
}
|
|
603
|
+
_admin_api_version_patch(project_id, module, version, body, 'servingStatus')
|
|
604
|
+
except errors.HttpError as e:
|
|
605
|
+
_raise_error(e)
|
|
606
|
+
|
|
607
|
+
return _ThreadedRpc(target=run_request)
|
|
608
|
+
|
|
609
|
+
def start_version_async_legacy(module, version):
|
|
374
610
|
def _ResultHook(rpc):
|
|
375
611
|
mapped_errors = [
|
|
376
612
|
modules_service_pb2.ModulesServiceError.INVALID_VERSION,
|
|
@@ -389,7 +625,6 @@ def start_version_async(
|
|
|
389
625
|
response = modules_service_pb2.StartModuleResponse()
|
|
390
626
|
return _MakeAsyncCall('StartModule', request, response, _ResultHook)
|
|
391
627
|
|
|
392
|
-
|
|
393
628
|
def stop_version(
|
|
394
629
|
module=None,
|
|
395
630
|
version=None):
|
|
@@ -422,6 +657,28 @@ def stop_version_async(
|
|
|
422
657
|
A `UserRPC` to stop all instances for the given module version.
|
|
423
658
|
"""
|
|
424
659
|
|
|
660
|
+
if not _has_opted_in():
|
|
661
|
+
return stop_version_async_legacy(module=module, version=version)
|
|
662
|
+
|
|
663
|
+
if module is None:
|
|
664
|
+
module = get_current_module_name()
|
|
665
|
+
|
|
666
|
+
if version is None:
|
|
667
|
+
version = get_current_version_name()
|
|
668
|
+
project_id = _get_project_id()
|
|
669
|
+
def run_request():
|
|
670
|
+
"""This function will be executed in a separate thread."""
|
|
671
|
+
try:
|
|
672
|
+
body = {
|
|
673
|
+
'servingStatus': 'STOPPED'
|
|
674
|
+
}
|
|
675
|
+
_admin_api_version_patch(project_id, module, version, body, 'servingStatus')
|
|
676
|
+
except errors.HttpError as e:
|
|
677
|
+
_raise_error(e)
|
|
678
|
+
|
|
679
|
+
return _ThreadedRpc(target=run_request)
|
|
680
|
+
|
|
681
|
+
def stop_version_async_legacy(module, version):
|
|
425
682
|
def _ResultHook(rpc):
|
|
426
683
|
mapped_errors = [
|
|
427
684
|
modules_service_pb2.ModulesServiceError.INVALID_VERSION,
|
|
@@ -433,7 +690,7 @@ def stop_version_async(
|
|
|
433
690
|
(module, version)
|
|
434
691
|
}
|
|
435
692
|
_CheckAsyncResult(rpc, mapped_errors, expected_errors)
|
|
436
|
-
|
|
693
|
+
|
|
437
694
|
request = modules_service_pb2.StopModuleRequest()
|
|
438
695
|
if module:
|
|
439
696
|
request.module = module
|
|
@@ -443,6 +700,10 @@ def stop_version_async(
|
|
|
443
700
|
return _MakeAsyncCall('StopModule', request, response, _ResultHook)
|
|
444
701
|
|
|
445
702
|
|
|
703
|
+
def _construct_hostname(*hostname_parts):
|
|
704
|
+
"""Constructs a hostname for the given module, version, and instance."""
|
|
705
|
+
return ".".join(hostname_parts)
|
|
706
|
+
|
|
446
707
|
def get_hostname(
|
|
447
708
|
module=None,
|
|
448
709
|
version=None,
|
|
@@ -467,7 +728,95 @@ def get_hostname(
|
|
|
467
728
|
InvalidInstancesError: if the given instance value is invalid.
|
|
468
729
|
TypeError: if the given instance type is invalid.
|
|
469
730
|
"""
|
|
731
|
+
if not _has_opted_in():
|
|
732
|
+
return get_hostname_legacy(module=module, version=version, instance=instance)
|
|
470
733
|
|
|
734
|
+
if instance is not None:
|
|
735
|
+
try:
|
|
736
|
+
instance_id = int(instance)
|
|
737
|
+
if instance_id < 0:
|
|
738
|
+
raise ValueError
|
|
739
|
+
except (ValueError, TypeError) as e:
|
|
740
|
+
raise InvalidInstancesError("Instance must be a non-negative integer.") from e
|
|
741
|
+
|
|
742
|
+
project_id = _get_project_id()
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
req_module = module or get_current_module_name()
|
|
746
|
+
req_version = version or get_current_version_name()
|
|
747
|
+
|
|
748
|
+
try:
|
|
749
|
+
services = get_modules()
|
|
750
|
+
client = _get_admin_api_client_with_useragent('get_hostname')
|
|
751
|
+
request = client.apps().get(appsId=project_id)
|
|
752
|
+
|
|
753
|
+
response = request.execute()
|
|
754
|
+
default_hostname = response.get('defaultHostname')
|
|
755
|
+
|
|
756
|
+
except errors.HttpError as e:
|
|
757
|
+
_raise_error(e)
|
|
758
|
+
|
|
759
|
+
if req_module not in services:
|
|
760
|
+
raise InvalidModuleError(f"")
|
|
761
|
+
# Legacy Applications (Without "Engines")
|
|
762
|
+
if len(services) == 1 and services[0] == 'default':
|
|
763
|
+
if req_module != 'default':
|
|
764
|
+
raise InvalidModuleError(f"Module '{req_module}' not found.")
|
|
765
|
+
hostname_parts = [req_version, default_hostname]
|
|
766
|
+
if instance:
|
|
767
|
+
return _construct_hostname(instance, req_version, default_hostname)
|
|
768
|
+
return _construct_hostname(req_version, default_hostname)
|
|
769
|
+
|
|
770
|
+
if instance is not None:
|
|
771
|
+
try:
|
|
772
|
+
# Get version details to check scaling and instance count
|
|
773
|
+
version_request = discovery.build('appengine', 'v1').apps().services().versions().get(
|
|
774
|
+
appsId=project_id, servicesId=req_module, versionsId=req_version, view='FULL')
|
|
775
|
+
version_details = version_request.execute()
|
|
776
|
+
|
|
777
|
+
if 'manualScaling' not in version_details:
|
|
778
|
+
raise InvalidInstancesError(
|
|
779
|
+
"Instance-specific hostnames are only available for manually scaled services.")
|
|
780
|
+
|
|
781
|
+
num_instances = version_details['manualScaling'].get('instances', 0)
|
|
782
|
+
if int(instance) >= num_instances:
|
|
783
|
+
raise InvalidInstancesError(
|
|
784
|
+
"The specified instance does not exist for this module/version.")
|
|
785
|
+
|
|
786
|
+
return _construct_hostname(instance, req_version, req_module, default_hostname)
|
|
787
|
+
|
|
788
|
+
except errors.HttpError as e:
|
|
789
|
+
if e.resp.status == 404:
|
|
790
|
+
raise InvalidModuleError(
|
|
791
|
+
f"Module '{req_module}' or version '{req_version}' not found.") from e
|
|
792
|
+
_raise_error(e)
|
|
793
|
+
|
|
794
|
+
# Request with no explicit version and no instance.
|
|
795
|
+
if version is None:
|
|
796
|
+
try:
|
|
797
|
+
# Get all versions for the target module.
|
|
798
|
+
versions_list = get_versions(module=req_module)
|
|
799
|
+
|
|
800
|
+
# Create a set of version IDs for efficient lookup.
|
|
801
|
+
existing_version_ids = set(versions_list)
|
|
802
|
+
|
|
803
|
+
# Check if the version from the current context exists in the target module.
|
|
804
|
+
if req_version in existing_version_ids:
|
|
805
|
+
return _construct_hostname(req_version, req_module, default_hostname)
|
|
806
|
+
else:
|
|
807
|
+
# If the current version does not exist on the target module,
|
|
808
|
+
# return a hostname without a version.
|
|
809
|
+
return _construct_hostname(req_module, default_hostname)
|
|
810
|
+
|
|
811
|
+
except errors.HttpError as e:
|
|
812
|
+
if e.resp.status == 404:
|
|
813
|
+
raise InvalidModuleError(f"Module '{req_module}' not found.") from e
|
|
814
|
+
_raise_error(e)
|
|
815
|
+
|
|
816
|
+
# Request with a version but no instance
|
|
817
|
+
return _construct_hostname(version, req_module, default_hostname)
|
|
818
|
+
|
|
819
|
+
def get_hostname_legacy(module, version, instance):
|
|
471
820
|
def _ResultHook(rpc):
|
|
472
821
|
mapped_errors = [
|
|
473
822
|
modules_service_pb2.ModulesServiceError.INVALID_MODULE,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|