Return the exposed callable page handler that is used for a route - cherrypy

Using the simple application:
import cherrypy
class Root(object):
#cherrypy.expose
def index(self):
return "Hello World!"
if __name__ == '__main__':
cherrypy.quickstart(Root(), '/')
Is there a way I can hook into the dispatching process and get the name of which handler is to be called? In this instance, when I go to /, I want to be able to print index or whatever the name of the exposed method for that route is. It seems like a before_handler or before_finalize hook would be what I want, but not clear how to use them.

Using a before_handler hook, I was able to retrieve it through request.handler.callable

Related

CherryPy Tool: How to register custom tool correctly?

I want to create a simple tool but fail to register it correctly. As soon as I add it to any method I get the error:
AttributeError: 'Toolbox' object has no attribute 'authenticate'
I tried
cherrypy.tools.authenticate = cherrypy.Tool('before_handler', authenticate)
and
#cherrypy.tools.register('before_handler')
def authenticate():
The issue I likely have is placing the function in the wrong place. I have a main file launching the server and all apps:
#config stuff
if __name__ == '__main__':
cherrypy.engine.unsubscribe('graceful', cherrypy.log.reopen_files)
logging.config.dictConfig(LOG_CONF)
cherrypy.tree.mount(app1(), '/app1')
cherrypy.tree.mount(app2(), '/app2')
cherrypy.quickstart(app3)
This file is launched by a systemd unit.
If I put the authenticate function in the config area, it doesn't work. If i put it in one of the apps directly and only use it in that app, it doesn't work. Always the same error.
So where do I have to place it to make this work?
Another case of me falling into the python definition order matters trap.
Doesn't work:
class MyApp(object):
#....
#cherrypy.tools.register('on_start_resource')
def authenticate():
#....
Works:
#cherrypy.tools.register('on_start_resource')
def authenticate():
#....
class MyApp(object):

APscheduler and Pyramid python

I'm trying to use the wonder apscheduler in a pyarmid api. The idea is to have a background job run regularly, while we still query the api for the result from time to time. Basically I use the job in a class as:
def my_class(object):
def __init__(self):
self.current_result = 0
scheduler = BackGroundScheduler()
scheduler.start()
scheduler.add_job(my_job,"interval", id="foo", seconds=5)
def my_job():
print("i'm updating result")
self.current_result += 1
And outside of this class (a service for me), the api has a POST endpoint that returns my_class instance's current result:
class MyApi(object):
def __init__(self):
self.my_class = MyClass()
#view_config(request_method='POST')
def my_post(self):
return self.my_class.current_result
When everything runs, I see the prints and incrementation of value inside the service. But current_result stays as 0 when gathered from the post.
From what I know of the threading, I guess that the update I do is not on the same object my_class but must be on a copy passed to the thread.
One solution I see would be to update the variable in a shared intermediate (write on disk, or in a databse). But I wondered if that would be possible to do in memory.
I manage to do exactly this when I do this in a regular script, or with one script and a very simple FLASK api (no class for the API there) but I can't manage to have this logic function inside the pyramid api.
It must be linked to some internal of Pyramid spawning my api endpoint on a different thread but I can't get right on the problem.
Thanks !
=== EDIT ===
I have tried several things to solve the issue. First, the instance of MyClass used is intitialized in another script, follow a container pattern. That container is by default contained in all MyApi instances of pyramid, and supposed to contain all global variables linked to my project.
I also define a global instance of MyClass just to be sure, and print its current result value to compare
global_my_class = MyClass()
class MyApi(object):
def __init__(self):
pass
#view_config(request_method='POST')
def my_post(self):
print(global_my_class.current_result)
return self.container.my_class.current_result
I check using debug that MyClass is only spawned twice during the api execution (one for the global variable, one inside the container. However.
So what I see in logging are two values of current_result getting incremented, but at each calls of my_post I only get 0s.
An instance of view class only lives for the duration of the request - request comes in, a view class is created, produces the result and is disposed. As such, each instance of your view gets a new copy of MyClass() which is separate from the previous requests.
As a very simple solution you may try defining a global instance which will be shared process-wide:
my_class = MyClass()
class MyApi(object):
#view_config(request_method='POST')
def my_post(self):
return my_class.current_result

Django viewflow: not receiving flow_finished signal

I'm trying to catch the flow_finished signal from django viewflow like this
flow_finished.connect(function)
but it's not working. The function isn't called even if the flow finishes.
Any help please, I'm pretty lost.
In my app's init.py I added this
from django.apps import AppConfig
default_app_config = 'test.TestConfig'
class TestConfig(AppConfig):
name = 'test'
verbose_name = 'Test'
def ready(self):
import viewflow.signals
First, you need to ensure that you properly configured you app config, and the ready method really been called. Check your installed apps that you properly included your TestConfig, or if you use shortcuts, check you test/__init__.py default_app_config value
from viewflow.signals import flow_finished
def receiver(sender, **kwargs):
print('hi')
class TestConfig(AppConfig):
name = 'test'
def ready(self):
flow_finished.connect(receiver)
But generally, using signals to weave your codebase is a bad taste. To call an action before flow.End you can explicitly add flow.Handler. That's the recommended solution.

python tornado how to get id of a edge

I have a web application that runs on flask web framework. Flask couldn't answer application requirements anymore. So we have decided to migrate tornado.
I need to handle below two request.
/entry GET Method
/entry/id GET Method
When first request called it must return authenticated entry.
When second request called it must return the entry whose entry_id
is id
Is there a different nice solution to handle above request except my solution. The solution i have found it creates cyclomatic complexity.
def get(self):
id = self.request.path.split('/')[-1]
if id is None:
#return authenticated user
else:
#return the user whose entry_id is id
Note: I am looking a solution like this:
#rest_user.route('/user', methods=['GET'])
#some code
#rest_user.route('/user/<user_id>', methods=['GET'])
#some code
The analogous arrangement in Tornado uses two handler classes (perhaps with a common base class for shared methods):
class AuthedUserHandler(RequestHandler):
def get(self):
...
class UserHandler(RequestHandler):
def get(self, user_id):
...
app = Application([
('/user', AuthedUserHandler),
('/user/(.*)', UserHandler),
])

Forcing single threaded request handling with web.py

I'm using web.py framework. For debugging purposes, I'd like to force all requests to be handled by a single thread, or simulate such behaviour with a mutex. How can I do that?
Let me suggest something like this, but it will lock only current application stack over your controller method.
import web
from threading import Lock
urls = ("/", "Index")
class Index:
def GET(self):
# This will be locked
return "hello world"
def mutex_processor():
mutex = Lock()
def processor_func(handle):
mutex.acquire()
try:
return handle()
finally:
mutex.release()
return processor_func
app = web.application(urls, globals())
app.add_processor(mutex_processor())
if __name__ == "__main__":
app.run()
UPD: if you need to lock the whole application stack then you probably have to wrap app.wsgifunc with your own WSGI middleware. To get an idea check my answer to this question.
To get things decently into a single thread debugging mode, the web.py app can be run with a single threaded WSGI server.
Such server is "almost" offered by web.py itself as web.httpserver.runbasic() which uses Python's builtin BaseHTTPServer.HTTPServer - but also SocketServer.ThreadingMixIn .
This ThreadingMixIn however can be blocked by something like this:
# single threaded execution of web.py app
app = web.application(urls, globals())
# suppress ThreadingMixIn in web.httpserver.runbasic()
import SocketServer
class NoThreadingMixIn:
pass
assert SocketServer.ThreadingMixIn
SocketServer.ThreadingMixIn = NoThreadingMixIn
web.httpserver.runbasic(app.wsgifunc())
Or you could replicate the rather short web.httpserver.runbasic() code.

Resources