CherryPy Tool: How to register custom tool correctly? - cherrypy

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):

Related

Calling parent class function before executing every child class function in Python

Here is an idea of the code
File 1
class MyParentClass(unittest.TestCase):
def setUpClass(self):
# SuperClass is already defined in the file
obj = SuperClass()
self.exp_fn = obj.create_exp_fn()
# This doesn't work
def setUp(self):
# sets up app to open the screen on which tests run (~100 lines)
File 2
from File1 import MyParentClass
class MyChildClass(MyParentClass):
def test_func_1(self):
# Start execution of its test
self.exp_fn.run_an_attribute()
def test_func_2(self):
# Start execution of its test
self.exp_fn.run_another_attribute()
I have several functions in MyChildClass and several files containing classes like MyChildClass which inherits unittest.TestCase
I want setUp to be called before executing any function of classes like MyChildClass but I don't want to individually decorate each function of MyChildClass or use the same 100 line setUp() function of unittest in all the files of MyChildClass. It should be present in MyParentClass as shown above
To run the tests I need to setUp the app such as open a specific screen, login and open another set of windows before a test can start. Or else the test won't find the element its looking for coz the app wouldn't be on the desired screen.
And the tests start from outside the app always
Is there a way to achieve the same functionality of setUp() following the above conditions. I went through the source code of run() in unittest where they use a contextmanager to implement setUp() but didn't quite get it
Would be highly obliged if anyone can suggest a solution... Thanks!!

Trigger middleware within the call method using Python and uWSGI

I was confused at one point when I was developing an application to run on wsgi - more specifically on uwsgi.
After building my example application:
class MyCustomApp():
def __call__(self, environ, start_response):
start_response('200 OK', [('Content-Type','application/json')])
return "a".encode('utf-8')
application = MyCustomApp()
Everything works perfectly as expected.
I use a class instead of a method, I need to use it for other reasons.
Now let's get to the problem. I am using middleware called beaker and if I replace my application with:
application = SessionMiddleware(MyCustomApp(),options)
Everything is normal, but I don't want to modify my call, despite for the sake of study and understanding.
I would like to do the following:
class MyCustomApp():
def __call__(self, environ, start_response):
start_response('200 OK', [('Content-Type','application/json')])
...
here i want to implement SessionMiddleware without modify
application = MyCustomApp()
...
return "a".encode('utf-8')
application = MyCustomApp()
But nothing I try, my middleware replaces my environment with its defaults. I wish they could guide me to understand and try to implement keeping the logic above.

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

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

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.

Resources