How to use bcrypt on Google App Engine (GAE)? [duplicate] - python

This question already has answers here:
How to include third party Python libraries in Google App Engine?
(6 answers)
Closed 8 years ago.
I have found a bcrypt library for python that seems to be very easy to use:
bcrypt 1.0.1
After installing it and testing the hello world example in my local machine all seems fine:
>>> import bcrypt
>>> password = b"super secret password"
>>> # Hash a password for the first time, with a certain number of rounds
>>> hashed = bcrypt.hashpw(password, bcrypt.gensalt(10))
>>> # Check that a unhashed password matches one that has previously been
>>> # hashed
>>> if bcrypt.hashpw(password, hashed) == hashed:
... print("It Matches!")
... else:
... print("It Does not Match :(")
However, in my GAE application, when I use import bcrypt I get an error:
Traceback (most recent call last):
File "/home/pedro/google_appengine/google/appengine/runtime/wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/home/pedro/google_appengine/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/home/pedro/google_appengine/google/appengine/runtime/wsgi.py", line 84, in LoadObject
obj = __import__(path[0])
File "/home/pedro/google_appengine/hw4/blog.py", line 8, in <module>
import bcrypt
ImportError: No module named bcrypt
INFO 2014-05-05 21:17:04,375 module.py:639] default: "GET /blog/signup HTTP/1.1" 500 -
This leads me to believe that I must change the app.yaml file to include this library:
application: calm-grid-571
version: 1
runtime: python27
api_version: 1
threadsafe: False
handlers:
- url: /static
static_dir: static
- url: /.*
script: blog.app
libraries:
- name: jinja2
version: latest
- name: PIL
version: latest
However, when checking the official page for the supported libraries I cannot find anything about bcrypt.
So, how do I use the bcrypt library in GAE? Is it even possible?

You have to include the source of bcrypt (or any other non-embedded library) into your project.
Suggestion is to create a libs folder on the root of your project (same level where app.yaml lives) and place there as many libraries' sources as you need.
For this case, the final result should look like: /libs/bcrypt/
Make sure to include __init__.py blank files on any new folder you want your code to treat this folder as a package. After that, simply import the module: from libs.bcrypt import bcrypt
EDIT: Also note you can just have pure python code on your app engine project. Try py-bcrypt, it is working like a charm for a project hosted on App Engine.

Related

Python & GAE - StringType write() argument type parsing

When running dev_appserver.py ., I get the following error when trying to access http://localhost:8080:
Traceback (most recent call last):
File "/usr/local/Cellar/python#2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 86, in run
self.finish_response()
File "/usr/local/Cellar/python#2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 128, in finish_response
self.write(data)
File "/usr/local/Cellar/python#2/2.7.15_1/Frameworks/Python.framework/Versions 2.7/lib/python2.7/wsgiref/handlers.py", line 204, in write
assert type(data) is StringType,"write() argument must be string"
AssertionError: write() argument must be string
I've searched and it seems to come back to my app.yaml file, per these links:
SO Question for GAE Assertion Error
Russian Question site with
same information
I'm just not sure how to go about debugging it. Below is my app.yaml file and my main.py file. I'm super new to the GAE platform and any help would be appreciated.
app.yaml file:
application: gqtimer
version: 1-56
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /favicon.ico
static_files: static/images/favicon.ico
upload: static/images/favicon.ico
- url: /_ah/login_required
script: main.py
- url: /static
static_dir: static
- url: /player.*
script: main.py
login: required
- url: /stat.*
script: main.py
login: required
- url: .*
script: main.py
libraries:
- name: django
version: "1.11"
main.py file:
#!/usr/bin/env python
#
import config
import os
import sys
# Force sys.path to have our own directory first, so we can import from it.
sys.path.insert(0, config.APP_ROOT_DIR)
sys.path.insert(1, os.path.join(config.APP_ROOT_DIR, 'externals'))
os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.dist import use_library
use_library('django', '1.2')
from handlers import error, timer, do_openid_login
def main():
application = webapp.WSGIApplication([('/', timer.ExportHandler),
('/_ah/login_required', do_openid_login.OpenIdLoginHandler),
('/player/([-\w]+)', timer.PlayerHandler),
('/player/([-\w]+)/archives', timer.ArchivesHandler),
('/stat/([-\w]+)', timer.StatHandler),
('/stat/([-\w]+)/delete', timer.StatDeleteHandler),
# If we make it this far then the page we are looking
# for does not exist
('/.*', error.Error404Handler),
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
Indeed, your app.yaml file might not be properly mapping your application code. You need to:
take the application variable outside of the main() function so that it becomes a global variable in the main.py module (and maybe rename it to app as well - just to stay inline with the official convention and documentation examples)
replace the script: main.py statements from your app.yaml's handlers with main.application (or main.app if renamed as mentioned above) - this is the reference to the above-mentioned global variable. From the script row in the Handlers element table:
A script: directive must be a python import path, for example,
package.module.app that points to a WSGI application. The last component of a script: directive using a Python module path is
the name of a global variable in the module: that variable must be a
WSGI app, and is usually called app by convention.
I'd also recommend explicitly passing the app.yaml as argument to dev_appserver.py instead of the app's directory (. in your case) - occasionally the auto-detection doesn't behave as expected. It's also the only way to run multiple services and/or using a dispatch.yaml file for routing, so it's a good habit.

"Failed to import google/appengine/ext/deferred/handler.py" in Google App Engine Flexible Environment

I use App Engine Flexible Environment (previously called Managed VMs), and recently upgraded to the latest gcloud SDK. It included some new errors:
ERROR: (gcloud.preview.app.deploy) Error Response: [400] Invalid
character
in filename: lib/setuptools/script (dev).tmpl
ERROR: The [application] field is specified in file [.../app.yaml]. This field is not used
by gcloud and must be removed. Project name should instead be
specified either by `gcloud config set project MY_PROJECT` or by
setting the `--project` flag on individual command executions.
ERROR: (gcloud.preview.app.deploy) There is a Dockerfile in the
current directory, and the runtime field in
.../app.yaml is currently set to
[runtime: python27]. To use your Dockerfile to build a custom runtime,
set the runtime field in .../app.yaml
to [runtime: custom]. To continue using the [python27] runtime, please
omit the Dockerfile from this directory.
I fixed these errors and was able to publish again, but started seeing errors like this:
Failed to import google/appengine/ext/deferred/handler.py
Traceback (most recent call last):
File "/home/vmagent/python_vm_runtime/google/appengine/ext/vmruntime/meta_app.py", line 549, in GetUserAppAndServe
app, mod_file = self.GetUserApp(script)
File "/home/vmagent/python_vm_runtime/google/appengine/ext/vmruntime/meta_app.py", line 410, in GetUserApp
app = _AppFrom27StyleScript(script)
File "/home/vmagent/python_vm_runtime/google/appengine/ext/vmruntime/meta_app.py", line 270, in _AppFrom27StyleScript
app, filename, err = wsgi.LoadObject(script)
File "/home/vmagent/python_vm_runtime/google/appengine/runtime/wsgi.py", line 85, in LoadObject
obj = __import__(path[0])
ImportError: Import by filename is not supported.
After a bit of digging, I figured out what is going on. Namely, the code that processes this:
builtins:
- remote_api: on
- appstats: on
- deferred: on
is broken with Managed VMs. The correct fix is to eliminate these and inline the builtin includes instead. You can find the relevant includes inside these subdirectories:
In my case, it was to add this to my handlers: directive:
- url: /_ah/queue/deferred
script: google.appengine.ext.deferred.application
login: admin
- url: /_ah/stats.*
script: google.appengine.ext.appstats.ui.app
- url: /_ah/remote_api(/.*)?
script: google.appengine.ext.remote_api.handler.application
As to why, you can understand more here. In google/appengine/ext/builtins/__init__.py#L92, it attempts to find the relevant include file by using the runtime: field in your app.yaml. This means where it previously looked up deferred/include-python27.yaml, it now attempts to find deferred/include-custom.yaml (due to fixing the errors above) and fails. So now it defaulting to deferred/include.yaml, which lists the include scrip by path-name instead of module-name. This then breaks in a python27-custom-VM setup (since it is expecting/needing module-names)

Why am I still getting the error: "CryptoUnavailableError: No crypto library available" in Python?

I am trying to make an API call through Python to Google's DFA and am using their suggested code. However, it is still not saying the credentials object is defined and throws the error:
Traceback (most recent call last):
File "<input>", line 2, in <module>
File "C:\Python27\lib\site-packages\oauth2client\util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Python27\lib\site-packages\oauth2client\client.py", line 1502, in __init__
_RequireCryptoOrDie()
File "C:\Python27\lib\site-packages\oauth2client\client.py", line 1456, in _RequireCryptoOrDie
raise CryptoUnavailableError('No crypto library available')
CryptoUnavailableError: No crypto library available
I have installed the pyOpenSSL library, and pycrypto library with the VCForPython compiler. I have also managed to edit all 3 app.yaml files in the LiClipse client to append:
libraries:
- name: pycrypto
version: "latest"
onto it.
This is what my code looks like so far with arbitrary credentials:
import json
import sys
import apiclient
from oauth2client import crypt
import ssl
import urllib2
from OpenSSL import crypto
HAS_OPENSSL = False
HAS_CRYPTO = False
try:
from oauth2client import crypt
HAS_CRYPTO = True
if crypt.OpenSSLVerifier is not None:
HAS_OPENSSL = True
except ImportError:
pass
from oauth2client.client import SignedJwtAssertionCredentials
client_email = 'example.apps.googleusercontent.com'
with open("C:\My Project-1234.p12") as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key,
'https://www.googleapis.com/auth/dfareporting')
from httplib2 import Http
I realize there is probably some excess in the beginning. I have not been able to get past this step.
I feel like I have tried everything and am still getting thrown the 'no crypto library' error.
Can anyone help? THANK YOU!
PS - I am using Windows 7 and Python 2.7 and LiClipse.
The above method was to make an API call as a 'service' Google account. I retried as an 'installed application' account with new credentials and a different way to make the API call which did not require any crypto type libraries.

Website not deploying using Google App Engine Launcher

I am creating a website and I wanted to put it online. However how many times I would try to deploy it using the Google App Engine Launcher it would not deploy.
app.yaml file :
application: GameDroidWeb
version: 1
runtime: python
api_version: 1
handlers:
- url: /(.*\.(gif|png|jpg|ico|js|css))
static_files: \1
upload: (.*\.(gif|png|jpg|ico|js|css))
- url: /robots.txt
static_files: robots.txt
upload: robots.txt
- url: .*
script: main.py
main.py :
# Copyright 2012 Digital Inspiration
# http://www.labnol.org/
import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template
class MainHandler(webapp.RequestHandler):
def get (self, q):
if q is None:
q = 'index.html'
path = os.path.join (os.path.dirname (__file__), q)
self.response.headers ['Content-Type'] = 'text/html'
self.response.out.write (template.render (path, {}))
def main ():
application = webapp.WSGIApplication ([('/(.*html)?', MainHandler)], debug=True)
util.run_wsgi_app (application)
if __name__ == '__main__':
main ()
Deployment Console Log :
2014-05-13 22:53:29 Running command: "['C:\\Python33\\pythonw.exe', '-u', 'C:\\Program Files (x86)\\Google\\google_appengine\\appcfg.py', '--no_cookies', u'--email=TheAddictedGamerOfficial#gmail.com', '--passin', 'update', 'C:\\Users\\User\\Desktop\\WEBSITE TEST']"
Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\appcfg.py", line 126, in <module>
run_file(__file__, globals())
File "C:\Program Files (x86)\Google\google_appengine\appcfg.py", line 122, in run_file
execfile(_PATHS.script_file(script_name), globals_)
NameError: global name 'execfile' is not defined
2014-05-13 22:53:29 (Process exited with code 1)
You can close this window now.
Does anyone know how to solve this? I have tried un-installing and reinstalling but that did not work either. Any help will be appreciated.
Thanks in advance,
You are using python 3 , you need Python 2.7.
(The Python SDK is not compatible with Python 3.) from here

mapping values are not allowed here ... in foo.py

I have this GAE python code
In file foo.py
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello Foo')
app = webapp2.WSGIApplication([('/', MainPage)], debug = True)
in file app.yaml
application: foo
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: foo.app
I get this error pointing to the third line in file foo.py ( class MainPage(webapp2.RequestHandler): )
Obs. Begin reading from the end of the message
...
line 172, in _HandleEvents
for event in events:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/yaml_listener.py", line 212, in _GenerateEventParameters
raise yaml_errors.EventListenerYAMLError(e)
google.appengine.api.yaml_errors.EventListenerYAMLError: mapping values are not allowed here
in "foo.py", line 3, column 39
I would appreciate a good help
thanks
Sam
This kind of error occurs if you start the application the wrong way: dev_appserver.py foo.py. You need a directory, e.g., foo with foo/foo.py and foo/app.yaml and then start the program from the parent directory with dev_appserver.py foo/ or in the directory itself with dev_appserver.py .
There is nothing wrong with your code. I copy and pasted both into files and ran them on my Win7 system using App Engine SDK release: "1.7.7" and it served up the page without errors.
You may have issues with the files or your setup.
Have you tried the File->Creating New Application menu option? It will create a new application called engineapp that will display "Hello world!" when browsed on the localhost machine.

Categories