I've been using geasessions for a while, been working great. It's simple and fast.
But today I started a new project (GAE v1.3.7) and can't get it to work, get_current_session() just returns None
I've split the code in to a new project that's just using gaesessions:
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template
from gaesessions import get_current_session
import logging
class MainHandler(webapp.RequestHandler):
def get(self):
session = get_current_session()
logging.info(session)
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, { }))
And in the log it just says None.
The strange part is that the other solutions it still works. (I'm guessing it's due to that the db.Model for Session is already present). Tested both the version I use there and downloaded the latest version (1.04)
I've looked at the source code for gaesessions and it kinda make sense that it returns None:
_current_session = None
def get_current_session():
"""Returns the session associated with the current request."""
return _current_session
And I can't find anywhere where the Session class is invoked, but then again it could be my laking python skills.
Does anyone use gaesession and know what's happening?
I think you have missed something in the installation process.
Anyway, if you scroll down the source code you will notice also this part of code that actually valorize the _current_session variable.
def __call__(self, environ, start_response):
# initialize a session for the current user
global _current_session
_current_session = Session(lifetime=self.lifetime, no_datastore=self.no_datastore, cookie_only_threshold=self.cookie_only_thresh, cookie_key=self.cookie_key)
Related
I'm trying to run Flask from an imported module (creating a wrapper using decorators).
Basically I have:
app.py:
import mywrapper
#mywrapper.entrypoint
def test():
print("HEYO!")
mywrapper.py
from flask import Flask
ENTRYPOINT = None
app = Flask(__name__)
#app.route("/")
def listen():
"""Start the model API service"""
ENTRYPOINT()
def entrypoint(f):
global ENTRYPOINT
ENTRYPOINT = f
return f
FLASK_APP=app
Running python -m flask, however, results in:
flask.cli.NoAppException: Failed to find Flask application or factory in module "app". Use "FLASK_APP=app:name to specify one.
Is there any trick to getting Flask to run like this? Or is it just not possible? The purpose of this is to abstract Flask away in this situation.
In my head flask should try to import mywrapper.py, which imports app.py which should generate the app and route, yet this doesn't seem to be what occurs.
Any help would be appreciated.
So I've since learnt that Flask searches only in the chosen module's namespace for a variable containing a Flask object.
There may be a smart way to avoid this limitation, but I instead decided that it was more sensible to instead just wrap the Flask class itself. If people want direct Flask functionality, I don't really care in this situation, so the only real limitation I have from this is some function names are off limits.
Basically:
wrapper.py:
class Wrapper(Flask):
def __init__(self, name):
super().__init__(name)
self.entrypoint_func = None
#self.route("/")
def listen():
return self.entrypoint_func()
def entrypoint(self, f):
assert self.entrypoint_func is None, "Entrypoint can only be set once"
self.entrypoint_func = f
return f
and app.py:
from mywrapper import Wrapper
app = Wrapper(__name__)
#app.entrypoint
def test():
print("HEYO!")
return "SUCCESS"
This is still abstracted enough that I am happy with the results.
I am trying to load a module according to some settings. I have found a working solution but I need a confirmation from an advanced python developer that this solution is the best performance wise as the API endpoint which will use it will be under heavy load.
The idea is to change the working of an endpoint based on parameters from the user and other systems configuration. I am loading the correct handler class based on these settings. The goal is to be able to easily create new handlers without having to modify the code calling the handlers.
This is a working example :
./run.py :
from flask import Flask, abort
import importlib
import handlers
app = Flask(__name__)
#app.route('/')
def api_endpoint():
try:
endpoint = "simple" # Custom logic to choose the right handler
handlerClass = getattr(importlib.import_module('.'+str(endpoint), 'handlers'), 'Handler')
handler = handlerClass()
except Exception as e:
print(e)
abort(404)
print(handlerClass, handler, handler.value, handler.name())
# Handler processing. Not yet implemented
return "Hello World"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=True)
One "simple" handler example. A handler is a module which needs to define an Handler class :
./handlers/simple.py :
import os
class Handler:
def __init__(self):
self.value = os.urandom(5)
def name(self):
return "simple"
If I understand correctly, the import is done on each query to the endpoint. It means IO in the filesystem with lookup for the modules, ...
Is it the correct/"pythonic" way to implement this strategy ?
Question moved to codereview. Thanks all for your help : https://codereview.stackexchange.com/questions/96533/extension-pattern-in-a-flask-controller-using-importlib
I am closing this thread.
I want to make a docstring for my router module in gae. I also know it must be the first thing in the module (after the file encoding type).
The thing is, if you run this module alone you get nothing but an import error (No module named webapp2). What I wanted is to print the docstring when running just the file but this import error just don't let me. Is there any way to do this?
I tried:
if __name__ == "__main__":
print help(self)
And other combinations, but no success.
[EDIT]
No specific code. Could be appengine's example:
# coding: utf-8
""" docstring """
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello, webapp World!')
app = webapp2.WSGIApplication([('/', MainPage)],
debug=True)
The ImportError happens when you run it as a standalone because it won't include any of the 'magic' that is included when run as an app. For instance, if you look at dev_appserver.py (just the basic one you use to run a dev server), you'll see this function:
def fix_sys_path(extra_extra_paths=()):
"""Fix the sys.path to include our extra paths."""
extra_paths = EXTRA_PATHS[:]
extra_paths.extend(extra_extra_paths)
sys.path = extra_paths + sys.path
Here you can see that sys.path is being modified to include some 'extra' paths, and if we take a look at one of them, you'll see webapp2 (as well as additional libraries provided in the SDK):
EXTRA_PATHS = [
# ...other similar setups...
os.path.join(DIR_PATH, 'lib', 'webapp2'),
# ...other similar setups...
]
You can see GAE is performing some additional steps behind the scenes to let you say import webapp2 without issue. Therefore when you try to run it on its own, you will get that error because your system is just checking the standard paths for webapp2 (which you likely don't have installed).
And that doesn't really answer your question at all :) As for that, I'm sure there are definitely more elegant/appropriate ways of handling this, but one thing you could try is wrapping your import(s) in a try/except block and on ImportError, checking if you're running the module directly. If so, call the module docstring and exit. Note this is just an example - you would want to make this more refined if you were to actually use it:
"""Module information."""
import sys
try:
import webapp2
except ImportError:
if __name__ == '__main__':
print __doc__
else:
print 'Webapp2 not found'
sys.exit(1)
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello, webapp World!')
app = webapp2.WSGIApplication([('/', MainPage)],
debug=True)
This will print Module information if you run it directly.
Just like in the title. I have a model that I can test manually. I enter url in a browser and receive a result form one of the views. Thing is unittest should be doing that.
I think there should be some way to create a request, send it to the application and in return receive the context.
You can create functional tests using the WebTest package, which allows you to wrap your WSGI application in a TestApp that supports .get(), .post(), etc.
See http://docs.pylonsproject.org/projects/pyramid/1.0/narr/testing.html#creating-functional-tests for specifics in Pyramid, pasted here for posterity:
import unittest
class FunctionalTests(unittest.TestCase):
def setUp(self):
from myapp import main
app = main({})
from webtest import TestApp
self.testapp = TestApp(app)
def test_root(self):
res = self.testapp.get('/', status=200)
self.failUnless('Pyramid' in res.body)
Pyramid doesn't really expose a method for testing a real request and receiving information about the internals. You possible execute the traverser yourself using:
from pyramid.traversal import traverse
app = get_app(...)
root = get_root(app)
out = traverse(root, '/my/test/path')
context = out['context']
However, the test is a bit contrived. It'd be more relevant to use a functional test that checks if the returned page is what you expect.
i am using python 2.6.5 to develop an app for google app engine - i am not too familiar with python, but i'm learning.
i am trying to put a url into a string so variable = "string http://domain.name"
then i print the string out. the problem is, if the colon (after http) is in the string, i don't get any output and i don't know why.
i've tried escaping the string with:
"""http://domain.name"""
r"http://domain.name"
"http\://domain.name"
"http\://domain.name"
"http\\://domain.name"
"http:://domain.name"
none of them seem to work and i'm not sure what else to try
The context is like so
variables.py is:
...
HOST_URL = "http://domain.name"
...
example logout.py
import variables
import sys
...
class Logout(webapp.RequestHandler):
""" RequestHandler for when a user wishes to logout from the system."""
def post(self):
self.get()
def get(self):
print(variables.HOST_URL)
print('hi')
self.redirect(variables.HOST_URL)
sys.exit()
or
in file functions.py
import variables
import sys
...
def sendhome(requesthandler)
print 'go to '+variables.HOST_URL
requesthandler.redirect(variables.HOST_URL)
sys.exit()
called from a context like:
from functions import sendhome
...
class Logout(webapp.RequestHandler):
""" RequestHandler for when a user wishes to logout from the system."""
def post(self):
self.get()
def get(self):
sendhome(self)
any help would be appreciated
thanks
If I'm not terrible mistaken, GAE uses WSGI, you do not simply print things, you are supposed to return a proper HTTP response object (it is not PHP).
I guess that if you access the page using firefox+firebug and look at the network->header you will see that the browser is taking http: as an HTTP header with value "//domain.name".
Edited: By the way, should not you be using "self.response.out.write" instead of "print"?
The problem was the sys.exit() after the call to print or redirect