Forcing single threaded request handling with web.py - multithreading

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.

Related

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.

Asyncio testing a function which uses loop.call_soon_threadsafe

I have the following function:
def send_command(self, cmd):
self.loop.call_soon_threadsafe(
functools.partial(
self._transport.write, str(cmd).encode() + b"\n"
)
)
The system under test (sut) is a class inheriting from asyncio.Protocol which sends some commands to a piece of hardware on a socket. I have to use threads since this is part of a GUI under wxPython. Finally, if I call self._transport.write the code works fine on Linux but crashes on Windows™.
When running the test:
#pytest.mark.asyncio
async def test_send_command(self):
self.sut._transport = Mock()
self.sut.send_command("ook eek")
assert self.sut._transport.write.called is True
I get an assert error. The self.sut._transport.write is never called. If I call self._transport.write directly in the function, the code crashes on Windows™ but the test passes just fine.
What am I missing here?
Anyone?…
Surely, this is not such an edge case…
A work around…
After reading and experimenting with even loops, using this:
import asyncio
import selectors
selector = selectors.SelectSelector()
loop = asyncio.SelectorEventLoop(selector)
asyncio.set_event_loop(loop)
by passes the problem. Of course, it means using a sub-efficient loop on Windows. ☹ PHA!
Anyone with a better solution is welcome to some fake internet points.

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

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

Method calling in Python

I'm somewhat of a n00b to Python and I'm working on a tiny project. This is my code in src/sock.py
import socket
import config
class Server(socket.socket):
def __init__(self):
socket.socket.__init__(self, socket.AF_INET, socket.SOCK_STREAM)
def start(self):
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.bind((config.bind_host, config.bind_port))
self.listen(5)
while True:
pass
and my code in start.py
import src
Socket = src.sock
Socket.Server()
Socket.Server.start
but the Server doesn't seem to be starting. :(
Any help would be much appreciated
Your code:
Socket.Server()
will create a server instance. But since you don't assign that created instance to a variable, you can't use it or reach it (and it will be garbage collected very quickly).
Socket.Server.start
accesses the start method on the Server class (not the created instance, but the class). But again, you don't do anything with it. You don't call it, you don't assign it to anything. So it is in effect a noop.
You need to assign the created server instance to a variable, and then call the start method on that instance. Like so:
server = Socket.Server()
server.start()

Resources