blob: a286056f49030d2ac9c39fa8febd6c63d6d9e4d2 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2016 Google Inc. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Module for setting up App Engine library paths.
15
16This module searches for the root of the App Engine Python SDK or Google Cloud
17SDK and computes a list of library paths and adds them to sys.path. This is
18necessary for two reasons:
19
201. The endpointscfg tool imports user code and therefore must be able to
21 import modules used in the app.
222. As a consequence of the first item, we must call an App Engine method to
23 set up service stubs in case an app's initialization code utilizes an App
24 Engine service. For example, there exists an App Engine version of pytz
25 which uses memcache and users may use it at the global level because it
26 seems to be declarative.
27"""
28import logging
29import os
30import sys
31
32_PYTHON_EXTENSIONS_WARNING = """
33Found Cloud SDK, but App Engine Python Extensions are not
34installed. If you encounter errors, please run:
35 $ gcloud components install app-engine-python
36""".strip()
37
38
39_IMPORT_ERROR_WARNING = """
40Could not import App Engine Python libraries. If you encounter
41errors, please make sure that the SDK binary path is in your PATH environment
42variable or that the ENDPOINTS_GAE_SDK variable points to a valid SDK root.
43""".strip()
44
45
46_NOT_FOUND_WARNING = """
47Could not find either the Cloud SDK or the App Engine Python SDK.
48If you encounter errors, please make sure that the SDK binary path is in your
49PATH environment variable or that the ENDPOINTS_GAE_SDK variable points to a
50valid SDK root.""".strip()
51
52
53_NO_FIX_SYS_PATH_WARNING = """
54Could not find the fix_sys_path() function in dev_appserver.
55If you encounter errors, please make sure that your Google App Engine SDK is
56up-to-date.""".strip()
57
58
59def _FindSdkPath():
60 environ_sdk = os.environ.get('ENDPOINTS_GAE_SDK')
61 if environ_sdk:
62 maybe_cloud_sdk = os.path.join(environ_sdk, 'platform', 'google_appengine')
63 if os.path.exists(maybe_cloud_sdk):
64 return maybe_cloud_sdk
65 return environ_sdk
66
67 for path in os.environ['PATH'].split(os.pathsep):
68 if os.path.exists(os.path.join(path, 'dev_appserver.py')):
69 if (path.endswith('bin') and
70 os.path.exists(os.path.join(path, 'gcloud'))):
71 # Cloud SDK ships with dev_appserver.py in a bin directory. In the
72 # root directory, we can find the Python SDK in
73 # platform/google_appengine provided that it's installed.
74 sdk_path = os.path.join(os.path.dirname(path),
75 'platform',
76 'google_appengine')
77 if not os.path.exists(sdk_path):
78 logging.warning(_PYTHON_EXTENSIONS_WARNING)
79 return sdk_path
80 # App Engine SDK ships withd dev_appserver.py in the root directory.
81 return path
82
83
84def _SetupPaths():
85 """Sets up the sys.path with special directories for endpointscfg.py."""
86 sdk_path = _FindSdkPath()
87 if sdk_path:
88 sys.path.append(sdk_path)
89 try:
90 import dev_appserver # pylint: disable=g-import-not-at-top
91 if hasattr(dev_appserver, 'fix_sys_path'):
92 dev_appserver.fix_sys_path()
93 else:
94 logging.warning(_NO_FIX_SYS_PATH_WARNING)
95 except ImportError:
96 logging.warning(_IMPORT_ERROR_WARNING)
97 else:
98 logging.warning(_NOT_FOUND_WARNING)
99
100 # Add the path above this directory, so we can import the endpoints package
101 # from the user's app code (rather than from another, possibly outdated SDK).
102 # pylint: disable=g-import-not-at-top
103 from google.appengine.ext import vendor
104 vendor.add(os.path.dirname(os.path.dirname(__file__)))
105
106
107_SetupPaths()