I want to streamline/reduce my code, so I try to put initializations of classes with repeated parameters in their own, extended classes. This is a REST API based on Pyramid & Cornice.
How would I initialize a pyramid.httpexceptions.HTTPUnauthorized when I'm always adding the same headers on initialization? This also applies to other HTTP responses where I initialize them repeatedly without changing their parameters.
Currently I've come up with this to extend the class:
class _401(HTTPUnauthorized):
def basic_jwt_header(self):
self.headers.add('WWW-Authenticate','JWT')
self.headers.add('WWW-Authenticate', 'Basic realm="Please log in"')
return self
def jwt_header(self):
self.headers.add('WWW-Authenticate','JWT')
return self
which I use in a view like this:
#forbidden_view_config()
def authenticate(request):
response = _401()
return _401.basic_jwt_header(response)
But it does not feel and look right. Is there a better, cleaner way?
Create an __init__ method on the class:
class _401(HTTPUnauthorized):
def __init__(self):
# call base class __init__ first, which will set up the
# headers instance variable
super(_401, self).__init__()
# in Python 3, just use this:
# super().__init__()
# now add the headers that you always enter
self.headers.add('WWW-Authenticate','JWT')
self.headers.add('WWW-Authenticate', 'Basic realm="Please log in"')
resp = _401()
print resp.headers
Since you are using two different methods after instantiating your _401 instance, then you might be better off using class-level factory methods, which will do both the instance creation and setting the desired headers:
class _401(HTTPUnauthorized):
#classmethod
def basic_jwt_header(cls):
ret = cls()
ret.headers.add('WWW-Authenticate','JWT')
ret.headers.add('WWW-Authenticate', 'Basic realm="Please log in"')
return ret
#classmethod
def jwt_header(cls):
ret = cls()
ret.headers.add('WWW-Authenticate','JWT')
return ret
resp = _401.basic_jwt_header()
print resp.headers
Now there's no need for creating __init__, or calling super() or whatever. We use cls instead of the explicit _401 class in support of any future subclassing of _401.
Related
I am performing load test using locust and have implemented RPS based load generation using a custom class from LoadTestShape.
This custom class holds methods for different load shapes like _tick_step_increase, _tick_rps_based, etc.:
class CustomLoadShape:
# factory class that holds different shape methods #
def __init__(self, step_interval=5, max_rps=500):
self.step_interval = step_interval
self.max_rps = max_rps
def _tick_step_increase(self):
# use self.interval here #
pass
def _tick_square_wave(self):
# use self.max_rps here #
pass
class MyCustomLoadShape(LoadTestShape, CustomLoadShape):
# this class is present in locustfile #
def __init__(self):
CustomLoadShape.__init__()
setattr(self, "tick", self._tick_rps_based) # this is how i make sure the `tick` method is defined
I am accepting some cli args, say, max-rps and wish to pass them to MyCustomLoadShape (eventually to CustomLoadShape).
I know that in the task functions, we can access cli args as self.environment.parsed_options.max_rps.
Intuitively, I tried to do the same in __init__ but it does not have self.environment and self.runner is None (somehow it appears as an object in the tick method).
Although we can access cli args in the tick method using self.runner.environment.parsed_options.max_rps, I was wondering if there was a way to do this in __init__ so that we could play around with attributes in a more OOP way.
I answered another similar question recently:
How to create and use custom command line parameters in locust
If you can't access the environment inside the LoadShape class, I'd recommend just setting a global variable with another function that runs on init like so:
max_rps = None
step_interval = None
#events.init.add_listener
def set_max_rps(environment, **kw):
global max_rps
max_rps = environment.parsed_options.max_rps
global step_interval = None
step_interval = None
Then you could access it from your other classes:
class CustomLoadShape:
# factory class that holds different shape methods #
def _tick_step_increase(self):
# use interval here #
step_interval
pass
def _tick_square_wave(self):
# use max rps here #
max_rps
pass
I want to use my own class RetrySession that is inherited from requests.Session, but with more robust try/else checking (for non-200 status codes, timeouts, etc.) and extra logging around the get() function.
# retry_session.py
import requests
import logging
logger = logging.getLogger(__name__)
# Oversimplified...
class RetrySession(requests.Session):
def get_(self, url, **kwargs):
logger.info(url)
return self.get(url, **kwargs)
Is there any way to keep the original function name of get() without like temporary copying the function? Right now, I'm doing something like:
from retry_session import *
# Logging defined here
s = RetrySession()
# Would like to do s.get(...) instead of s.get_(...)
r = s.get_("https://httpbin.org/get")
You need to use super() to call the method from the superclass, also there is no new keyword to instanciate object
class RetrySession(requests.Session):
def get(self, url, **kwargs):
print("Requesting", url)
return super().get(url, **kwargs)
if __name__ == '__main__':
s = RetrySession()
r = s.get("https://httpbin.org/get")
In pymodbus library in server.sync, SocketServer.BaseRequestHandler is used, and defines as follow:
class ModbusBaseRequestHandler(socketserver.BaseRequestHandler):
""" Implements the modbus server protocol
This uses the socketserver.BaseRequestHandler to implement
the client handler.
"""
running = False
framer = None
def setup(self):
""" Callback for when a client connects
"""
_logger.debug("Client Connected [%s:%s]" % self.client_address)
self.running = True
self.framer = self.server.framer(self.server.decoder, client=None)
self.server.threads.append(self)
def finish(self):
""" Callback for when a client disconnects
"""
_logger.debug("Client Disconnected [%s:%s]" % self.client_address)
self.server.threads.remove(self)
def execute(self, request):
""" The callback to call with the resulting message
:param request: The decoded request message
"""
try:
context = self.server.context[request.unit_id]
response = request.execute(context)
except NoSuchSlaveException as ex:
_logger.debug("requested slave does not exist: %s" % request.unit_id )
if self.server.ignore_missing_slaves:
return # the client will simply timeout waiting for a response
response = request.doException(merror.GatewayNoResponse)
except Exception as ex:
_logger.debug("Datastore unable to fulfill request: %s; %s", ex, traceback.format_exc() )
response = request.doException(merror.SlaveFailure)
response.transaction_id = request.transaction_id
response.unit_id = request.unit_id
self.send(response)
# ----------------------------------------------------------------------- #
# Base class implementations
# ----------------------------------------------------------------------- #
def handle(self):
""" Callback when we receive any data
"""
raise NotImplementedException("Method not implemented by derived class")
def send(self, message):
""" Send a request (string) to the network
:param message: The unencoded modbus response
"""
raise NotImplementedException("Method not implemented by derived class")
setup() is called when a client is connected to the server, and finish() is called when a client is disconnected. I want to manipulate these methods (setup() and finish()) in another class in another file which use the library (pymodbus) and add some code to setup and finish functions. I do not intend to modify the library, since it may cause strange behavior in specific situation.
---Edited ----
To clarify, I want setup function in ModbusBaseRequestHandler class to work as before and remain untouched, but add sth else to it, but this modification should be done in my code not in the library.
The simplest, and usually best, thing to do is to not manipulate the methods of ModbusBaseRequestHandler, but instead inherit from it and override those methods in your subclass, then just use the subclass wherever you would have used the base class:
class SoupedUpModbusBaseRequestHandler(ModbusBaseRequestHandler):
def setup(self):
# do different stuff
# call super().setup() if you want
# or call socketserver.BaseRequestHandler.setup() to skip over it
# or call neither
Notice that a class statement is just a normal statement, and can go anywhere any other statement can, even in the middle of a method. So, even if you need to dynamically create the subclass because you won't know what you want setup to do until runtime, that's not a problem.
If you actually need to monkeypatch the class, that isn't very hard—although it is easy to screw things up if you aren't careful.
def setup(self):
# do different stuff
ModbusBaseRequestHandler.setup = setup
If you want to be able to call the normal implementation, you have to stash it somewhere:
_setup = ModbusBaseRequestHandler.setup
def setup(self):
# do different stuff
# call _setup whenever you want
ModbusBaseRequestHandler.setup = setup
If you want to make sure you copy over the name, docstring, etc., you can use `wraps:
#functools.wraps(ModbusBaseRequestHandler.setup)
def setup(self):
# do different stuff
ModbusBaseRequestHandler.setup = setup
Again, you can do this anywhere in your code, even in the middle of a method.
If you need to monkeypatch one instance of ModbusBaseRequestHandler while leaving any other instances untouched, you can even do that. You just have to manually bind the method:
def setup(self):
# do different stuff
myModbusBaseRequestHandler.setup = setup.__get__(myModbusBaseRequestHandler)
If you want to call the original method, or wraps it, or do this in the middle of some other method, etc., it's otherwise basically the same as the last version.
It can be done by Interceptor
from functools import wraps
def iterceptor(func):
print('this is executed at function definition time (def my_func)')
#wraps(func)
def wrapper(*args, **kwargs):
print('this is executed before function call')
result = func(*args, **kwargs)
print('this is executed after function call')
return result
return wrapper
#iterceptor
def my_func(n):
print('this is my_func')
print('n =', n)
my_func(4)
more explanation can be found here
I'm trying to override the DaemonRunner in the python standard daemon process library (found here https://pypi.python.org/pypi/python-daemon/)
The DaemonRunner responds to command line arguments for start, stop, and restart, but I want to add a fourth option for status.
The class I want to override looks something like this:
class DaemonRunner(object):
def _start(self):
...etc
action_funcs = {'start': _start}
I've tried to override it like this:
class StatusDaemonRunner(DaemonRunner):
def _status(self):
...
DaemonRunner.action_funcs['status'] = _status
This works to some extent, but the problem is that every instance of DaemonRunner now have the new behaviour. Is it possible to override it without modifying every instance of DaemonRunner?
I would override action_functs to make it a non-static member of class StatusDaemonRunner(DaemonRunner).
In terms of code I would do:
class StatusDaemonRunner(runner.DaemonRunner):
def __init__(self, app):
self.action_funcs = runner.DaemonRunner.action_funcs.copy()
self.action_funcs['status'] = StatusDaemonRunner._status
super(StatusDaemonRunner, self).__init__(app)
def _status(self):
pass # do your stuff
Indeed, if we look at the getter in the implementation of DaemonRunner (here) we can see that it acess the attribute using self
def _get_action_func(self):
""" Return the function for the specified action.
Raises ``DaemonRunnerInvalidActionError`` if the action is
unknown.
"""
try:
func = self.action_funcs[self.action]
except KeyError:
raise DaemonRunnerInvalidActionError(
u"Unknown action: %(action)r" % vars(self))
return func
Hence the previous code should do the trick.
I've a class Client which has many methods:
class Client:
def compute(self, arg):
#code
#more methods
All the methods of this class runs synchronously. I want to run them asynchronously. There are too many ways to accomplish this. But I'm thinking along these lines:
AsyncClient = make_async(Client) #make all methods of Client async, etc!
client = AsyncClient() #create an instance of AsyncClient
client.async_compute(arg) #compute asynchronously
client.compute(arg) #synchronous method should still exist!
Alright, that looks too ambitious, and I feel it can be done.
So far I've written this:
def make_async(cls):
class async_cls(cls): #derive from the given class
def __getattr__(self, attr):
for i in dir(cls):
if ("async_" + i) == attr:
#THE PROBLEM IS HERE
#how to get the method with name <i>?
return cls.__getattr__(i) # DOES NOT WORK
return async_cls
As you see the comment in the code above, the problem is to get the method given its name as string. How to do that? Once I get the method, I would wrap it in async_caller method, etc — the rest of the work I hope I can do myself.
The function __getattr__ just works with class instance, not class. Use getattr(cls, method_name) instead, it will solve the problem.
getattr(cls, method_name)