I have been creating a web app that uses webapp2 framework and hosted with Google App Engine. So in order to run the webapp on LOCALHOST, I use the following command.
dev_appserver.py app.yaml
The python script that I am trying to run is in the same project folder as well, when the script is executed, I get the following error.
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\remote_api\remote_api_stub.py", line 256, in _MakeRealSyncCall
raise pickle.loads(response_pb.exception())
RuntimeError: NotImplementedError()
I have no clue, why it is showing this error. I tried looking at python documentation.
exception NotImplementedError:
This exception is derived from RuntimeError. In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.
https://docs.python.org/3/library/exceptions.html#NotImplementedError
As being new to programming, unfortunately it makes no sense to me.
I might be getting this error because of:
1.The application is running on different server and I am trying to run a script that is on my PC. But the demo I downloaded also has some python scripts that are been executed by clicking a button on html page and those work fine.
The script I am trying to execute, uses selenium web driver, it might be conflicting with the webapp2 framework.
I am not sure, why is that happening. Any suggestions please. Thanks!
UPDATE
full traceback
Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\devappserver2\api_server.py", line 375, in _handle_POST
api_response = _execute_request(request).Encode()
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\devappserver2\api_server.py", line 231, in _execute_request
make_request()
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\devappserver2\api_server.py", line 226, in make_request
request_id)
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\api\apiproxy_stub.py", line 151, in MakeSyncCall
method(request, response)
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\api\remote_socket\_remote_socket_stub.py", line 234, in _Dynamic_Listen
raise NotImplementedError()
NotImplementedError
Views.py
from handlers.api_handler import APIHandler
from handlers.ndb_handler import InitUser
import webapp2
import os
from google.appengine.ext.webapp import template
class Google_Login(webapp2.RequestHandler):
def post(self):
template_values = {
'back_msg': 'View Campaigns'
}
try:
app_user = InitUser()
handler = APIHandler(app_user.client_id,
app_user.client_secret,
app_user.refresh_token,
app_user.adwords_manager_cid,
app_user.developer_token)
handler.google_log()
self.redirect('/showCampaigns?clientCustomerId=%s''{{ccid}}')
except Exception as e:
template_values['error'] = str(e)
# Use template to write output to the page.
path = os.path.join(os.path.dirname(__file__),
'../templates/base_template.html')
self.response.out.write(template.render(path, template_values))
Api_handler.py (where the selenium webdriver is being used)
def google_log(self):
browser=webdriver.Firefox(executable_path=r'C:\Users\JASPREET\geckodriver.exe')
browser.maximize_window()
browser.get("https://accounts.google.com/ServiceLogin/identifier?continue=https%3A%2F%2Fadwords.google.com%2Fum%2Fidentity%3Fhl%3Den%26sourceid%3Dawo%26subid%3Dca-en-ha-g-aw-c-dr_df_1-b_ex!o2~-1340701349-261603328952-kwd-1329939046%26utm_campaign%3Dca-ww-di-g-aw-a-awhp_1!o2&hl=en&service=adwords&skipvpage=true<mpl=signin&flowName=GlifWebSignIn&flowEntry=AddSession")
username=browser.find_element_by_css_selector('#identifierId')
username.send_keys('#EMAIL')
next=browser.find_element_by_css_selector('#identifierNext').click()
time.sleep(1)
password= browser.find_element_by_xpath("//input[#name='password']")
password.send_keys('#PASSWORD')
login=browser.find_element_by_xpath('//*[#id="passwordNext"]')
login.click()
time.sleep(3)
browser.get('path to scripts')
time.sleep(7)
run=browser.find_element_by_xpath('/html/body/div[2]/root/div/div[1]/div[3]/awsm-child-content/div[2]/div/bulk-root/base-root/div[2]/div[1]/view-loader/script-editor-view/script-editor/div/buttonbar/pending-panel/div/div/material-button[2]').click()
time.sleep(2)
run_two=browser.find_element_by_xpath('/html/body/div[4]/div[2]/material-dialog/focus-trap/div[2]/div/footer/div/material-button[2]').click()
HTML FILE where I am calling the python script to execute "FB" is the name of view that links to API handler and calls the script.
<div class="">
<form action="/fb?clientCustomerId = {{ccid}}" method="post">
<input type="submit" name="" value="RUN">
</form>
</div>
UPDATE 2
APP.YAML
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /stylesheets
static_dir: stylesheets
- url: /js
static_dir: js
- url: /.*
script: demo.main.app
login: required
secure: always
libraries:
- name: ssl
version: latest
MAIN.PY
"""App Engine application module.
Configures the web application that will display the AdWords UI.
"""
from demo import DEBUG
from views import AddAdGroup
from views import AddCampaign
from views import InitView
from views import ShowAccounts
from views import ShowAdGroups
from views import ShowBudget
from views import ShowCampaigns
from views import ShowCredentials
from views import UpdateBudget
from views import UpdateCredentials
from views import ShowPage
from views import ShowKeywords
from views import NonServing
from views import Google_Login
import webapp2
app = webapp2.WSGIApplication([('/', InitView),
('/showCredentials', ShowCredentials),
('/updateCredentials', UpdateCredentials),
('/showAccounts', ShowAccounts),
('/showCampaigns', ShowCampaigns),
('/addCampaign', AddCampaign),
('/showAdGroups', ShowAdGroups),
('/addAdGroup', AddAdGroup),
('/showBudget', ShowBudget),
('/updateBudget', UpdateBudget),
('/nonservingpause', NonServing),
('/keywords', ShowKeywords),
('/fb', Google_Login),
],
debug=DEBUG)
Related
I am currently trying to build an api using connexion. However, I am having some issues using relative local module imports through the connexion module, which modifies the underlying flask app. Here is a simplified overview of my file structure:
hall_of_fame_api
controller
____init____.py
routes.py
model
____init____.py
routes.py
____init____.py
config.py
create_db.py
swagger.yml
I am getting an error when I try to run 'python config.py' in my terminal. Here is config.py:
import os
import connexion
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
basedir = os.path.abspath(os.path.dirname(__file__))
# Create the Connexion application instance
connex_app = connexion.App(__name__, specification_dir=basedir)
# Get the underlying Flask app instance
app = connex_app.app
connex_app.add_api('swagger.yml')
# Configure the SQLAlchemy part of the app instance
app.config['SQLALCHEMY_ECHO'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://doadmin:password#nba-player-db-do-user-7027314-0.db.ondigitalocean.com:25060/nba_test_1?sslmode=require'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Create the SQLAlchemy db instance
db = SQLAlchemy(app)
# Initialize Marshmallow
ma = Marshmallow(app)
And here is the error it gives:
Failed to add operation for GET /api/players
Failed to add operation for GET /api/players
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 209, in add_paths
self.add_operation(path, method)
File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 173, in add_operation
pass_context_arg_name=self.pass_context_arg_name
File "/usr/local/lib/python3.7/site-packages/connexion/operations/__init__.py", line 8, in make_operation
return spec.operation_cls.from_spec(spec, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/connexion/operations/swagger2.py", line 137, in from_spec
**kwargs
File "/usr/local/lib/python3.7/site-packages/connexion/operations/swagger2.py", line 96, in __init__
pass_context_arg_name=pass_context_arg_name
File "/usr/local/lib/python3.7/site-packages/connexion/operations/abstract.py", line 96, in __init__
self._resolution = resolver.resolve(self)
File "/usr/local/lib/python3.7/site-packages/connexion/resolver.py", line 40, in resolve
return Resolution(self.resolve_function_from_operation_id(operation_id), operation_id)
File "/usr/local/lib/python3.7/site-packages/connexion/resolver.py", line 66, in resolve_function_from_operation_id
raise ResolverError(str(e), sys.exc_info())
connexion.exceptions.ResolverError: <ResolverError: module 'controller.routes' has no attribute 'read_all'>
This error comes specifically from line 12 where connexion is trying to add the swagger.yml file, here is that for reference as well:
swagger: "2.0"
info:
description: This is the swagger file that goes with our server code
version: "1.0.0"
title: Swagger REST Article
consumes:
- "application/json"
produces:
- "application/json"
basePath: "/api"
# Paths supported by the server application
paths:
/players:
get:
operationId: "controller.routes.read_all"
tags:
- "People"
summary: "The people data structure supported by the server application"
description: "Read the list of people"
responses:
200:
description: "Successful read people list operation"
schema:
type: "array"
items:
properties:
fname:
type: "string"
lname:
type: "string"
timestamp:
type: "string"
Now here is where I am confused, because my routes.py file does have a function defined as read_all(), here is that file:
from model.models import Regseason, RegSchema, Playoffs, PlayoffSchema
def read_all():
return Regseason.query.all()
I have been racking my brain over this bug for almost 24 hours, any guidance would be greatly appreciated. Thanks in advance!
Please add a extra field x-openapi-router-controller below operationid. It is used by Connexion to map which module to send requests to. It is combined together with OperationId to go to correct module and function.
I'm working to modify a cookiecutter Flask app. I'm working locally on WIN7 and attempting to deploy to heroku. I'm currently trying to add a datepicker to a page. I've found https://eonasdan.github.io/bootstrap-datetimepicker/. The structure of myflaskapp:
I've set up bower to install the front end dependencies under the static root by using a .bowerrc file in the document root containing:
{ "directory" : "myflaskapp/static/bower_components" }
This cookiecutter uses flask-assets to manage the project assets. Following https://adambard.com/blog/fresh-flask-setup/ I've modified myflaskapp/assets.py file :
from flask_assets import Bundle, Environment
import os
css = Bundle(
"libs/bootstrap/dist/css/spacelab/bootstrap.css",
"bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.css",
"css/style.css",
"css/home.css",
# "css/style.css",
filters="cssmin",
output="public/css/common.css"
)
js = Bundle(
"libs/jQuery/dist/jquery.js",
"libs/bootstrap/dist/js/bootstrap.js",
"bower_components/moment/moment.js",
"bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js",
"js/plugins.js",
filters='jsmin',
output="public/js/common.js"
)
assets = Environment()
assets.register("js_all", js)
assets.register("css_all", css)
myflaskapp/app.py initializes the assets:
from flask import Flask, render_template
from myflaskapp.assets import assets
"""
:param config_object: The configuration object to use.
"""
app = Flask(__name__)
app.config.from_object(config_object)
register_extensions(app)
register_blueprints(app)
register_errorhandlers(app)
return app
def register_extensions(app):
assets.init_app(app)
def register_blueprints(app):
app.register_blueprint(public.blueprint)
app.register_blueprint(user.blueprint)
In the myflaskapp/settings.py , during testing, I have set:
ASSETS_DEBUG = True # Don't bundle/minify static assets
Locally, there are no errors in the console. On heroku , I get an Internal server error. Logs:
←[33m2016-03-19T18:02:12.464159+00:00 app[web.1]:←[0m for org, cnt in self.resolve_contents(ctx):
←[33m2016-03-19T18:02:12.464161+00:00 app[web.1]:←[0m raise BundleError(e)
←[33m2016-03-19T18:02:12.464162+00:00 app[web.1]:←[0m BundleError: 'bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.css' not found in load path:
['/app/myflaskapp/static']
←[33m2016-03-19T18:02:12.464150+00:00 app[web.1]:←[0m rv = template.render(context)
←[33m2016-03-19T18:02:12.464151+00:00 app[web.1]:←[0m File "/app/.heroku/python/lib/python2.7/site-packages/jinja2/environment.py", line 969, in render
←[33m2016-03-19T18:02:12.464152+00:00 app[web.1]:←[0m File "/app/.heroku/python/lib/python2.7/site-packages/jinja2/environment.py", line 742, in handle_exception
←[33m2016-03-19T18:02:12.464154+00:00 app[web.1]:←[0m {% extends "layout.html" %}
←[33m2016-03-19T18:02:12.464157+00:00 app[web.1]:←[0m urls = bundle.urls()
←[33m2016-03-19T18:02:12.464153+00:00 app[web.1]:←[0m reraise(exc_type, exc_value, tb)
As you can see in the top screenshot it is there. How can I fix this?
Note: I've been looking at https://github.com/mitsuhiko/flask/issues/348, which may have a bearing on this.
Try checking your .gitignore, build is often ignored which would exclude your static files here: bower_components/eonasdan-bootstrap-datetimepicker/build/*
I am reading 'Head First Python'. I am on Chapter 10 where Google App Engine is introduced. The initial hello world of using Python and Google App Engine was successful but subsequent programs have all failed.
I have the following app.yaml file:
application: three
version: 1
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /.*
script: page368b.py
libraries:
- name: django
version: "1.3"
With the following Python code (page368b.py):
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template
#this line throws the error when accessing the web-page
from google.appengine.ext.db import djangoforms
import birthDB
class BirthDetailsForm(djangoforms.ModelForm):
class Meta:
model = birthDB.BirthDetails
class SimpleInput(webapp.RequestHandler):
def get(self):
html = template.render('templates/header.html', {'title': 'Provide your birth details'})
html = html + template.render('templates/form_start.html', {})
html = html + str(BirthDetailsForm(auto_id=False))
html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Details'})
html = html + template.render('templates/footer.html', {'links': ''})
self.response.out.write(html)
def main():
app = webapp.WSGIApplication([('/.*', SimpleInput)], debug=True)
wsgiref.handlers.CGIHandler().run(app)
if __name__ == '__main__':
main()
Here is another Python module imported into the one above called birthDB.py:
from google.appengine.ext import db
class BirthDetails(db.Model):
name = db.StringProperty()
date_of_birth = db.DateProperty()
time_of_birth = db.TimeProperty()
There is a templates folder that the above Python module calls. They have HTML code in them with some Django code. Here is an example using the footer.html.
<p>
{{ links }}
</p>
</body>
</html>
The other HTML files are similar. I can start the Google App Engine with no problems using this command from BASH: python google_appengine/dev_appserver.py ~/Desktop/three The directory three contains the templates folder, the app.yaml file, the Python modules shown above.
My problem is when I access the web-page at http://localhost:8080 nothing is there and the BASH shell where the command is run to start this shows all the calls in the Python program that caused the problem and then finally says: ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
I have read in a few different places a few different things to try so I thought I would go ahead and make a new post and hope that some expert Python programmers would chime in and lend their assistance to a lost hobbit such as myself.
Also, the book says to install Python2.5 to use this code but Google App Engine now supports Python2.7 that was not available as of the time of the books writing. Also, I just checked and Python2.5 is not even an option to use with Google App Engine. Python2.5 deprecated
This is probably too complex to solve on here. I am surprised all of these different technologies are used in a Head First Python book. It is asking a lot of a Python noob. ^_^
Regards,
user_loser
UPDATE - I installed Django on my Ubuntu Operating System
When I change the line in the python module 368b.py from google.appengine.ext.db import djangoforms to from django import forms I receive the following error on the console when accessing the web-page on localhost:
loser#loser-basic-box:~/Desktop$ google_appengine/dev_appserver.py three
INFO 2014-09-06 21:08:36,669 api_server.py:171] Starting API server at: http://localhost:56044
INFO 2014-09-06 21:08:36,677 dispatcher.py:183] Starting module "default" running at: http://localhost:8080
INFO 2014-09-06 21:08:36,678 admin_server.py:117] Starting admin server at: http://localhost:8000
ERROR 2014-09-06 21:08:48,942 cgi.py:121] Traceback (most recent call last):
File "/home/loser/Desktop/three/page368b.py", line 13, in <module>
class BirthDetailsForm(forms.ModelForm):
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/models.py", line 205, in __new__
opts.exclude, opts.widgets, formfield_callback)
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/models.py", line 145, in fields_for_model
opts = model._meta
AttributeError: type object 'BirthDetails' has no attribute '_meta'
INFO 2014-09-06 21:08:48,953 module.py:652] default: "GET / HTTP/1.1" 500 -
ERROR 2014-09-06 21:08:49,031 cgi.py:121] Traceback (most recent call last):
File "/home/loser/Desktop/three/page368b.py", line 13, in <module>
class BirthDetailsForm(forms.ModelForm):
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/models.py", line 205, in __new__
opts.exclude, opts.widgets, formfield_callback)
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/models.py", line 145, in fields_for_model
opts = model._meta
AttributeError: type object 'BirthDetails' has no attribute '_meta'
Update Errors from running the program as is without making any changes:
loser#loser-basic-box:~/Desktop$ google_appengine/dev_appserver.py three/
INFO 2014-09-06 21:35:19,347 api_server.py:171] Starting API server at: http://localhost:60503
INFO 2014-09-06 21:35:19,356 dispatcher.py:183] Starting module "default" running at: http://localhost:8080
INFO 2014-09-06 21:35:19,358 admin_server.py:117] Starting admin server at: http://localhost:8000
ERROR 2014-09-06 21:35:25,011 cgi.py:121] Traceback (most recent call last):
File "/home/loser/Desktop/three/page368b.py", line 13, in <module>
class BirthDetailsForm(djangoforms.ModelForm):
File "/home/loser/Desktop/google_appengine/google/appengine/ext/db/djangoforms.py", line 772, in __new__
form_field = prop.get_form_field()
File "/home/loser/Desktop/google_appengine/google/appengine/ext/db/djangoforms.py", line 370, in get_form_field
return super(DateProperty, self).get_form_field(**defaults)
File "/home/loser/Desktop/google_appengine/google/appengine/ext/db/djangoforms.py", line 353, in get_form_field
return super(DateTimeProperty, self).get_form_field(**defaults)
File "/home/loser/Desktop/google_appengine/google/appengine/ext/db/djangoforms.py", line 200, in get_form_field
return form_class(**defaults)
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/fields.py", line 340, in __init__
super(DateField, self).__init__(*args, **kwargs)
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/fields.py", line 99, in __init__
widget = widget()
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/forms/widgets.py", line 382, in __init__
self.format = formats.get_format('DATE_INPUT_FORMATS')[0]
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/utils/formats.py", line 67, in get_format
if use_l10n or (use_l10n is None and settings.USE_L10N):
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/utils/functional.py", line 276, in __getattr__
self._setup()
File "/home/loser/Desktop/google_appengine/lib/django-1.3/django/conf/__init__.py", line 40, in _setup
raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
I assume you're working with the example code that accompanies the book, available from this website: http://examples.oreilly.com/0636920003434/
If you download and expand the chapter 10 archive (chapter10.zip), you'll see several example files, and also several .zip archives. The page368b.py file corresponds with the webapp-chapter10-simpleform.zip archive. Open that archive to create a webapp-chapter10-simpleform directory. This directory contains an app.yaml file, the simpleform.py file (identical to page368b.py), birthDB.py (an ext.db model class), and static and template file directories.
Unfortunately, as you may have already noticed, the example doesn't work out of the box with the latest SDK. (I'm using version 1.9.10 of the SDK, which was just released.) It reports "ImportError: No module named django.core.exceptions" when you attempt to load the page. Strictly speaking, this example is not a Django application, but is merely trying to use a library that depends on Django being present.
The Python 2.5 runtime environment, which is selected by the app.yaml file included with this example, is meant to include Django 0.96 by default. However, this behavior has changed in the SDK since Head First Python was written. The smallest fix to get this example to work is to add these lines to simpleform.py prior to the import of djangoforms:
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from google.appengine.dist import use_library
use_library('django', '0.96')
Then create a file named settings.py in your application root directory (the webapp-chapter10-simpleform directory). This file can be empty in this case. (As other commenters have noted, there is a better way to generate this file when using the Django framework, but in this case we just need the import to succeed.)
To upgrade this example to use the Python 2.7 runtime environment, modify app.yaml as follows:
application: simpleform
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /static
static_dir: static
- url: /*.
script: simpleform.app
The changes:
runtime: is now python27
threadsafe: true is added
The reference to simpleform.py is now a Python object path to the global variable app.
Then modify simpleform.py so that everything following the definition of the SimpleInput class is replaced with:
app = webapp.WSGIApplication([('/.*', SimpleInput)], debug=True)
Instead of running the simpleform.py script, the Python 2.7 runtime environment imports it as a module, then looks for a WSGI application object in a global variable. The lines we removed executed the app, and that's now done for us by the runtime environment.
From here, you can use a libraries: clause as you have done to select a newer version of Django, if you wish. A quick test in a dev server shows that the modified example works with Django 1.5, which is the latest supported version.
I am trying to create a demo webserver that returns a TwiML Say block with custom text inside it based on parameters provided with the URL (Yes, POSTing would be better, but I'm not quite sure how to do that). It would work a lot like https://www.twilio.com/labs/twimlets/message except I want to write my own code so I can add more customizations.
I have started by building off of the Weather by Phone demo because it contains customized text inside of xml.
I have created my own google appengine called gracklevoice, and I got the weatherbyphone example working. Now, I'm having trouble when I try to simplify it. My code looks like this:
import os
import wsgiref.handlers
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
BASE_URL = "http://gracklevoice.appspot.com/"
def xml_response(handler, page, templatevalues=None):
"""
Renders an XML response using a provided template page and values
"""
path = os.path.join(os.path.dirname(__file__), page)
handler.response.headers["Content-Type"] = "text/xml"
handler.response.out.write(template.render(path, templatevalues))
class GracklePage(webapp.RequestHandler):
def get(self):
self.post()
def post(self):
xml_response(self, 'notification.xml')
def main():
application = webapp.WSGIApplication([ \
('/', GracklePage)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == "__main__":
main()
There is the yaml file too:
application: gracklevoice
version: 1
runtime: python27
api_version: 1
threadsafe: no
handlers:
- url: /.*
script: gracklevoice.py
And notification.xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="alice" language="en-US">
This is a message from Grackle.
</Say>
</Response>
This seems it should be really simple, but when my client app sets the call url to http://gracklevoice.appspot.com/ I get an error instead of the voice message: "We are sorry. an application error has occurred. Goodbye." What am I missing?
Looking in the appEngine logs (which are limited in length, welp), I see:
2013-11-18 14:45:09.781
Traceback (most recent call last):
E 2013-11-18 14:45:09.781
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/wsgiref/handlers.py", line 86, in run
E 2013-11-18 14:45:09.781
self.finish_response()
E 2013-11-18 14:45:09.781
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/wsgiref/handlers.py", line 128, in finish_response
E 2013-11-18 14:45:09.781
self.write(data)
E 2013-11-18 14:45:09.781
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/wsgiref/handlers.py", line 204, in write
E 2013-11-18 14:45:09.781
assert type(data) is StringType,"write() argument must be string"
E 2013-11-18 14:45:09.781
AssertionError: write() argument must be string
Twilio Developer Evangelist here. Cast the output of template.render(path, templatevalues) with the unicode() function. Your new line of code will end up as
handler.response.out.write(unicode(template.render(path, templatevalues)))
The output of the template.render function is a StringType, instead of a str type, which is what the write function needs. Casting with the unicode function converts the output to the input format you require.
There is additional information in this question about issues with StringType and unicode.
I created a simple python project that serves up a couple of pages. I'm using the 'webapp' framework and django. What I'm trying to do is use one template file, and load 'content files' that contain the actual page text.
When I try to read the content files using os.open, I get the following error:
pageContent = os.open(pageUrl, 'r').read()
OSError: [Errno 1] Operation not permitted: 'content_includes/home.inc' error
If I let the django templating system to read the same file for me, everything works fine!
So the question is What am I doing wrong that django isn't??? The same 'pageUrl' is used.
The code below will give me the error, while if I comment out the first pageContent assignment, everything works fine.
Code:
pageName = "home";
pageUrl = os.path.join(os.path.normpath('content_includes'), pageName + '.inc')
pageContent = os.open(pageUrl, 'r').read()
pageContent=template.render(pageUrl, template_values, debug=True);
template_values = { 'page': pageContent,
'test': "testing my app"
}
Error:
Traceback (most recent call last):
File "/opt/apis/google_appengine/google/appengine/ext/webapp/__init__.py", line 511, in __call__
handler.get(*groups)
File "/home/odessit/Development/Python/Alpha/main.py", line 19, in get
pageContent = os.open(pageUrl, 'r').read()
File "/opt/apis/google_appengine/google/appengine/tools/dev_appserver.py", line 805, in FakeOpen
raise OSError(errno.EPERM, "Operation not permitted", filename)
OSError: [Errno 1] Operation not permitted: 'content_includes/home.inc'
app.yaml:
handlers:
- url: /javascript
static_dir: javascript
- url: /images
static_dir: images
- url: /portfolio
static_dir: portfolio
- url: /.*
script: main.py
os.path.normpath() on "content_includes" is a no-op - normpath just removes double slashes and other denormalizations. What you probably want is to build a path relative to the script, in which case you should do something like os.path.join(os.path.dirname(__file__), 'content_includes', pageName + '.inc').
If you dig in the dev_appserver.py source code and related files you see that the server does some incarnate checking to ensure that you open only files from below your applications root (in fact the rules seem even more complex).
For file access troubled I instrumented that "path permission checking" code from the development server to find that I was using absolute paths. We propbably should do a patch to appengine to provide better error reporting on that: IIRC the Appserver does not display the offending path but a mangled version of this which makes debugging difficult.