Intent
I am creating a CRUD app for App Engine where the user authenticates via OAuth and the server stores their access and refresh tokens in Datastore. I am doing local testing with dev_appserver and getting stuck between a rock and hard place:
The python37 runtime cannot import thethe python27 runtime cannot import thendbmodule for Datastore andgoogle.authmodule.
Problem Statement
Python37
In the python37 runtime, my requirements.txt file is detected and all dependencies are installed properly. However, it appears that this runtime does not currently have native support for the ndb module in order to make calls the Datastore API.
from google.appengine.ext import ndb
ModuleNotFoundError: No module named 'google.appengine'
One way to solve my problem would be to manually install the ndb package, however I don't believe that it open-source at this point in time.
I will most likely move forward by using google-api-python-client to interact with Datastore. However, I am still interested in solving the problem outlined below in order to better my understanding of the way python modules work in App Engine.
Python27
In the python27 runtime, requirements.txt is ignored. My workaround has been to include the latest releases of all of the dependencies' source code. I do this by populating a directory called dependencies with the source and then add symbolic links to root modules. (This has also been a nice exercise in learning how importing python modules works)
Project Structure
Directory
.
├── api.py
├── app
│ ├── build
│ ├── config
│ ├── dist
│ ├── index.html
│ ├── node_modules
│ ├── package.json
│ ├── package-lock.json
│ ├── src
│ └── static
├── app.yaml
├── dependencies
│ ├── click-7.0
│ ├── flask-1.0.2
│ ├── google-auth-library-python-1.6.3
│ ├── google-auth-library-python-oauthlib-0.3.0
│ ├── itsdangerous-1.1.0
│ ├── jinja-2.10.1
│ └── markupsafe-1.1.1
├── libs
│ ├── click -> ../dependencies/click-7.0/click/
│ ├── flask -> ../dependencies/flask-1.0.2/flask/
│ ├── google -> ../dependencies/google-auth-library-python-1.6.3/google/
│ ├── google_auth_oauthlib -> ../dependencies/google-auth-library-python-oauthlib-0.3.0/google_auth_oauthlib/
│ ├── __init__.py
│ ├── itsdangerous -> ../dependencies/itsdangerous-1.1.0/src/itsdangerous/
│ ├── jinja2 -> ../dependencies/jinja-2.10.1/jinja2/
│ └── markupsafe -> ../dependencies/markupsafe-1.1.1/src/markupsafe/
├── requirements.txt
└── spa.py
Python Code
In my server files, spa.py and api.py, I include libs in the python path as follows:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'libs'))
This works for import statements such as
import google_auth_oauthlib.flow # works
and
from flask import Flask, request, session, redirect # works
but it fails for
import google.auth # does not work
with the exception
Traceback (most recent call last):
File "<HOME>/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "<HOME>/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 299, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "<HOME>/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 85, in LoadObject
obj = __import__(path[0])
File "<HOME>/vue-scheduler/api.py", line 6, in <module>
import google.auth
File "<HOME>/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/python/runtime/sandbox.py", line 1149, in load_module
raise ImportError('No module named %s' % fullname)
ImportError: No module named google.auth
I believe I've set everything up correctly for python to import the auth submodule. The __init__.py files are present and that should let python recurse through the nested module directories. However it isn't able to find auth.