How to wrap a base class method in python - python

Working with python3, I have following classes
class RESTApi:
def __init__(self):
self.connection = # Create connection
def hello_world(self):
print("Hello World !!")
... # More methods
class BaseVM:
def __init__(self):
self.restapi = RESTApi()
def _refresh_restapi_connection(self):
self.restapi = # Reconnect
class MyClass(BaseVM):
def __init__(self, *args):
BaseVM.__init__(self, *args)
def create_user(self, usr, pwd):
self.restapi.create_user(usr, pwd)
MyClass is where I interact with the existing classes and I can change the code in MyClass but not in the other classes.
The issue I am having is that the REST connection is being cleaned out, when left idle. So I need to implement a call to refresh the REST connection(_refresh_restapi_connection), whenever 'self.restapi.XYZ' fails.
And I want this to be automatically done in try...except. The methods like 'create_user' etc. need not know that there was a reconnect.
Since I can't change the other classes, I am trying to create a wrapper over self.restapi calls
Something of the type:
class RestRetry:
'''
Wrapper over RESTApi class instance with retries
'''
def __init__(self, vm):
self._restapi = vm.restapi
def __getattr__(self, attrb):
return self.rest_retry(attrb)
def rest_retry(self, attrb):
def _retry():
try:
# class REST API with retries
result = getattr(self._restapi, attrb)
except:
self._refresh_restapi_connection()
return getattr(self._restapi, attrb)
else:
return result
return _retry
And then MyClass will have
def __init__(self, *args):
BaseVM.__init__(self, *args)
self.restapi = RestRetry()
It doesn't work though
Maybe I am missing something very basic, or maybe trying to solve this the wrong way.

This is what I eventually ended up writing. Had to change the attribute name in MyClass which I didn't want to but could not get it working without that
class RestRetry:
'''
Wrapper over RESTApi class instance with retries
'''
def __init__(self, vm):
self._vm= vm
def __getattr__(self, attrb):
return self.rest_retry(attrb)
def rest_retry(self, attrb):
def _retry(*args, **kwargs):
try:
# class REST API with retries though
result = getattr(self._vm.restapi, attrb)(*args, **kwargs)
except:
self._vm._refresh_restapi_connection()
return getattr(self._vm.restapi, attrb)(*args, **kwargs)
else:
return result
return _retry
And then in MyClass
def __init__(self):
BaseVM.__init__(self)
self._restapi = self.RestRetry(self)
def any_method(self):
self._restapi.hello_world()

Related

How can I auto-complete python code if i use dynamic type

Here is an example below:
class Service:
def __init__(self):
self.data = dict()
def get(self, clazz):
# clazz is a class Type, and always return an instance of clazz
return self.data[clazz]
def register(self, clazz, *args, **kwargs):
self.data[clazz] = clazz(*args, **kwargs)
class A:
def method_of_a(self):
pass
class B:
pass
service = Service()
service.register(A)
service.register(B)
now I complete the code of service, and continue coding like
x = service.get(A)
x.method_of_a()
the code works, but there is a problem, when i was coding, the IDE(pycharm in this case) will not show the function of x when you input
x.
even i modify my code like this, it does'nt work
def get(self, clazz):
result: clazz = self.data[clazz]
return result
I want to know if there any way to implement Service, that IDE can recognise the type of the return value?
Use typing.TypeVar and typing.Type to type-hint your .get() function to say "if called with the type of T, this returns an instance of T":
from typing import TypeVar, Type
T = TypeVar('T')
class Service:
def __init__(self):
self.data = dict()
def get(self, clazz: Type[T]) -> T:
return self.data[clazz]
def register(self, clazz, *args, **kwargs):
self.data[clazz] = clazz(*args, **kwargs)
class A:
def method_of_a(self):
pass
s = Service()
s.register(A)
x = s.get(A)
x.method_of_a()
reveal_type(x)
When run with mypy, the reveal_type() call prints out
so73566368.py:24: note: Revealed type is "so73566368.A"

How to remove a method from an object instance conditioned by __init__ parameters?

I would like to write a class that removes access to or throws an error in case a particular method is accessed and this behavior should be conditioned by a variable set upon class instantiation.
So in code I would like something like this:
class NewClass:
def __init__(self, has_non_available_method):
self.has_non_available_method = has_non_available_method
def some_method(self):
if self.has_non_available_method:
raise SomeError()
This is fine however, if I want to have a couple of methods like this then I have to copy-paste these 2 lines into every method. Which "doesn't seem very sophisticated" and I would like to find out if a "better"/DRY approach exists.
I considered using decorators but decorators execute upon class execution so they do not seem to be suitable for this task as the attribute has_non_available_method (in this example) will not be set at that point.
A decorator is perfect for this.
def checkavail(func):
def wrapper(self, *args, **kwargs):
if self.has_non_available_method:
raise SomeError()
func(self, *args, **kwargs)
return wrapper
class NewClass:
def __init__(self, has_non_available_method):
self.has_non_available_method = has_non_available_method
#checkavail
def some_method(self):
# do stuff
You can use decorator to make this behavior more dynamic.
def check_permission(method):
def call(self, *args, **kwargs):
if getattr(self, 'has_{}_permission'.format(method.__name__), False):
method(self, *args, **kwargs)
else:
raise Exception('{} needs permission'.format(method.__name__))
return call
class PermissionRequiredMethodClass(object):
def __init__(self, has_secret_method_permission: bool = False):
self.has_secret_method_permission = has_secret_method_permission
super().__init__()
def open_method(self):
print('in open method')
#check_permission
def secret_method(self):
# secret stuff
print('in secret')
use decorator
I add decorate_all_functions, so you don't need copy-paste the decorate itself to every class method.
code:
def decorate_all_functions(function_decorator):
def decorator(self):
for name, obj in vars(self).items():
if callable(obj):
try:
obj = obj.__func__
except AttributeError:
pass
setattr(self, name, function_decorator(obj))
return self
return decorator
from functools import wraps
def check_permission(func):
#wraps(func)
def wrapper(self, *args, **kwargs):
if func.__name__ in self.has_non_available_method:
raise Exception("Some Error")
func(self,*args, **kwargs)
return wrapper
#decorate_all_functions(check_permission)
class NewClass:
has_non_available_method = []
def __init__(self, has_non_available_method):
self.has_non_available_method = has_non_available_method
def some_method(self):
print("do something")
def another_method(self):
print("do another thing")
x = NewClass(["another_method"])
x.some_method()
try:
x.another_method()
except Exception as e:
print(e)
result:
do something
Some Error
use del
You can try delattr or del to remove class method dynamically.
code:
class NewClass:
def some_method(self):
print("do something")
def another_method(self):
print("do another thing")
x = NewClass()
x.some_method()
x.another_method()
delattr(type(x),"some_method")
# del NewClass.some_method
# both work
try:
x.some_method()
except Exception as e:
print(e)
x.another_method()
result:
do something
do another thing
'NewClass' object has no attribute 'some_method'
do another thing
But it will remove the class method, not the instance.
y = NewClass()
y.some_method()#raise AttributeError

Can't grasp : making a simple singleton in python (for a mongodb manager)

I have read the various main examples of singletons but I have trouble making what I want. My main inspiration here is this example :
class OnlyOne:
class __OnlyOne:
def __init__(self, arg):
self.val = arg
def __str__(self):
return repr(self) + self.val
instance = None
def __init__(self, arg):
if not OnlyOne.instance:
OnlyOne.instance = OnlyOne.__OnlyOne(arg)
else:
OnlyOne.instance.val = arg
def __getattr__(self, name):
return getattr(self.instance, name)
But I don't need anything like getattr, here is my code so far:
class MongoManager:
class __MongoManager:
def __init__(self):
# Initialise client
self.client = pymongo.MongoClient('localhost', 27017)
__instance = None
def __init__(self):
if not MongoManager.__instance:
MongoManager.__instance = MongoManager.__MongoManager()
All I want is to get the variable client when I type MongoManager.client, but I get the error AttributeError: 'MongoManager' object has no attribute 'client'.
I guess I could try with getattr and check something like if arg == "client" but it feels dirty, I'm sure there's a proper way to do that.
Try this:
class MongoManager:
__instance = None
#staticmethod
def getInstance():
if MongoManager.__instance == None:
MongoManager()
return MongoManager.__instance
def __init__(self):
if MongoManager.__instance != None:
raise Exception("This class is a singleton!")
else:
MongoManager.__instance = pymongo.MongoClient('localhost', 27017)
You can get instance of this class by calling MongoManager.getInstance().
What we are doing here? We have a class variable __instance and when object of the class is created, we are initializing it. Now, when we call getInstance() this instance which is stored in __instance will get passed instead of creating new instance.
I managed to do exactly what I wanted. I didn't completely understand how __getattr__ worked so a bit more reading was necessary.
class MongoManager:
class __MongoManager:
def __init__(self):
# Initialise mongo client
self.client = pymongo.MongoClient('localhost', 27017)
__instance = None
def __init__(self):
if not MongoManager.__instance:
MongoManager.__instance = MongoManager.__MongoManager()
def __getattr__(self, item):
return getattr(self.__instance, item)
Now whenever I call MongoManager().client, I get the desired client.

Using decorators to implement Observer Pattern in Python3

This question is not in general about the observer pattern. It is focused on the use of decorators in that pattern. The question is based on the answer of a similar question.
#!/usr/bin/env python3
class Observable:
"""
The object that need to be observed. Alternative names are 'Subject'.
In the most cases it is a data object.
"""
def __init__(self):
self._observers = []
def register_observer(self, callback):
self._observers.append(callback)
return callback
def _broadcast_observers(self, *args, **kwargs):
for callback in self._observers:
callback(*args, **kwargs)
class TheData(Observable):
"""
Example of a data class just for demonstration.
"""
def __init__(self, data):
Observable.__init__(self)
self._data = data
#property
def data(self):
return self._data
#data.setter
def data(self, data):
self._data = data
self._broadcast_observers()
class TheGUIElement:
"""
Example of a gui class (Widget) just for demonstration.
e. g. it could be a text field in GUI.
"""
def __init__(self, data):
self._data = data
#data.register_observer(self._data_updated)
self._redraw()
def _redraw(self):
print('in _redraw(): ' + data.data)
#Observable.register_observer
def _data_updated(self, **kwargs):
"""
This is the callback that is called by the Observable if the
data changed.
"""
print('in _data_updated() - kwargs: {}'.format(kwargs))
self._redraw()
if __name__ == '__main__':
data = TheData('DATA')
gui = TheGUIElement(data)
data.data = 'SECOND DATA'
This code doesn't work because of this error.
Traceback (most recent call last):
File "./o.py", line 42, in <module>
class TheGUIElement:
File "./o.py", line 55, in TheGUIElement
#Observable.register_observer
TypeError: register_observer() missing 1 required positional argument: 'callback'
It is unclear to me how to use a decorator for to register the observers (e.g. TheGUIElement).
To register the callback, you need to have an actual object. In your code, how is #Observable.register_observer supposed to find which instance is should register on?
Please drop that Observable thing that's a javaism, cumbersome in python.
Look at this.
#!/usr/bin/env python
class SomeData(object):
def __init__(self, value):
self.callbacks = []
self.foo = value
def register(self, callback):
self.callbacks.append(callback)
return callback
def notify(self, *args, **kwargs):
for callback in self.callbacks:
callback(self, *args, **kwargs)
class SomeGUI(object):
def redraw(self, obj, key, newvalue):
print('redrawing %s with value %s' % (self, newvalue))
if __name__ == '__main__':
my_data = SomeData(42)
# Register some function using decorator syntax
#my_data.register
def print_it(obj, key, value):
print('Key %s changed to %s' % (key, value))
# Register the SomeGUI element
my_gui = SomeGUI()
my_data.register(my_gui.redraw)
# Try changing it. Note my_data is dumb for now, notify manually.
my_data.foo = 10
my_data.notify("foo", 10)
I intentionally removed automatic notifications to illustrate registration by itself.
Let's add it back. But there is no point using that Observable class. Let's make it lighter, simply defining an event class.
#!/usr/bin/env python3
class Event(object):
def __init__(self):
self.callbacks = []
def notify(self, *args, **kwargs):
for callback in self.callbacks:
callback(*args, **kwargs)
def register(self, callback):
self.callbacks.append(callback)
return callback
class SomeData(object):
def __init__(self, foo):
self.changed = Event()
self._foo = foo
#property
def foo(self):
return self._foo
#foo.setter
def foo(self, value):
self._foo = value
self.changed.notify(self, 'foo', value)
class SomeGUI(object):
def redraw(self, obj, key, newvalue):
print('redrawing %s with value %s' % (self, newvalue))
if __name__ == '__main__':
my_data = SomeData(42)
# Register some function using decorator syntax
#my_data.changed.register
def print_it(obj, key, value):
print('Key %s changed to %s' % (key, value))
# Register the SomeGUI element
my_gui = SomeGUI()
my_data.changed.register(my_gui.redraw)
# Try changing it.
my_data.foo = 10
As you probably noted now, the decorator syntax is useful in those circumstances:
You have a single registry. Either a singleton or the class itself class are first-order objects, and most are singletons.
You dynamically define the function and register it as you go.
Now, those manual getters/setters you have are cumbersome as well, if you have many why not factor them out?
#!/usr/bin/env python3
class Event(object):
def __init__(self):
self.callbacks = []
def notify(self, *args, **kwargs):
for callback in self.callbacks:
callback(*args, **kwargs)
def register(self, callback):
self.callbacks.append(callback)
return callback
#classmethod
def watched_property(cls, event_name, key):
actual_key = '_%s' % key
def getter(obj):
return getattr(obj, actual_key)
def setter(obj, value):
event = getattr(obj, event_name)
setattr(obj, actual_key, value)
event.notify(obj, key, value)
return property(fget=getter, fset=setter)
class SomeData(object):
foo = Event.watched_property('changed', 'foo')
def __init__(self, foo):
self.changed = Event()
self.foo = foo
class SomeGUI(object):
def redraw(self, obj, key, newvalue):
print('redrawing %s with value %s' % (self, newvalue))
if __name__ == '__main__':
my_data = SomeData(42)
# Register some function using decorator syntax
#my_data.changed.register
def print_it(obj, key, value):
print('Key %s changed to %s' % (key, value))
# Register the SomeGUI element
my_gui = SomeGUI()
my_data.changed.register(my_gui.redraw)
# Try changing it.
my_data.foo = 10
For reference, all three programs output the exact same thing:
$ python3 test.py
Key foo changed to 10
redrawing <__main__.SomeGUI object at 0x7f9a90d55fd0> with value 10
Even though the thread is kinda old (probably the problem is already solved), I would like to share a solution of mine to the "Decorated Observer Pattern" problem:
https://pypi.org/project/notifyr/
I created a package that implements decorators which add the observer-observed methods/attributes to python classes. I managed to use the package in a Django project too, but with a few adaptations (the .observers attribute is not persisted in the database, so I had to load the list of observers into it every time I expected to notify them).
Here is an implementation example:
Original Code:
class Dog(object):
def __init__(self, name):
self.name = name
def bark(self):
print('Woof')
def sleep(self):
print(self.name, 'is now asleep: ZZzzzzZzzZ...')
class Person(object):
def __init__(self, name):
self.name = name
def educate_dog(self, dog):
print(self.name + ':','Sleep,', dog.name)
dog.sleep()
Suppose we want a person to educate a dog every time the animal barks:
from notifyr.agents import observed, observer
from notifyr.functions import target
#observed
class Dog(object):
def __init__(self, name):
self.name = name
#target
def bark(self):
print('Woof')
def sleep(self):
print(self.name, 'is now asleep: ZZzzzzZzzZ...')
#observer('educate_dog')
class Person(object):
def __init__(self, name):
self.name = name
def educate_dog(self, dog):
print(self.name + ':','Sleep,', dog.name)
dog.sleep()
Given the decorated classes, it is possible to achieve the following result:
d = Dog('Tobby')
p = Person('Victor')
d.attach(p) # Victor is now observing Tobby
d.bark()
# Woof
# Victor: Sleep, Tobby
# Tobby is now asleep: ZZzzzzZzzZ...
The package is still very primitive, but it presents a working solution to this type of situation.
I was recently looking for something similar and here's what I came up with. It works by intercepting the __setattr__ method -- a useful stunt I plan on keeping in my pocket for later.
def watchableClass(cls):
"""
Class Decorator!
* If the class has a "dirty" member variable, then it will be
automatically set whenever any class value changes
* If the class has an "onChanged()" method, it will be called
automatically whenever any class value changes
* All this only takes place if the value is different from what it was
that is, if myObject.x is already 10 and you set myObject.x=10
nothing happens
* DOES NOT work with getter/setter functions. But then, you are
already in a function, so do what you want!
EXAMPLE:
#watchableClass
class MyClass:
def __init__(self):
self.dirty=False
def onChanged(self):
print('class has changed')
"""
if hasattr(cls,'__setattr__'):
cls.__setattr_unwatched__=cls.__setattr__
cls.__setattr__=_setObjValueWatchedCascade
else:
cls.__setattr__=_setObjValueWatched
return cls
def _setObjValueWatched(ob,k,v):
"""
called when an object value is set
"""
different=not k in ob.__dict__ or ob.__dict__[k]!=v
if different:
ob.__dict__[k]=v
if k not in ('dirty'):
if hasattr(ob,'dirty'):
ob.dirty=True
if hasattr(ob,'onChanged'):
ob.onChanged()
def _setObjValueWatchedCascade(ob,k,v):
"""
called when an object value is set
IF the class had its own __setattr__ member defined!
"""
different=not k in ob.__dict__ or ob.__dict__[k]!=v
ob.__setattr_unwatched__(k,v)
if different:
if k not in ('dirty'):
if hasattr(ob,'dirty'):
ob.dirty=True
if hasattr(ob,'onChanged'):
ob.onChanged()

Python. Put bottle.py routes in class and use self. [duplicate]

I've done some coding with Bottle. It's really simple and fits my needs. However, I got stick when I tried to wrap the application into a class :
import bottle
app = bottle
class App():
def __init__(self,param):
self.param = param
# Doesn't work
#app.route("/1")
def index1(self):
return("I'm 1 | self.param = %s" % self.param)
# Doesn't work
#app.route("/2")
def index2(self):
return("I'm 2")
# Works fine
#app.route("/3")
def index3():
return("I'm 3")
Is it possible to use methods instead of functions in Bottle?
Your code does not work because you are trying to route to non-bound methods. Non-bound methods do not have a reference to self, how could they, if instance of App has not been created?
If you want to route to class methods, you first have to initialize your class and then bottle.route() to methods on that object like so:
import bottle
class App(object):
def __init__(self,param):
self.param = param
def index1(self):
return("I'm 1 | self.param = %s" % self.param)
myapp = App(param='some param')
bottle.route("/1")(myapp.index1)
If you want to stick routes definitions near the handlers, you can do something like this:
def routeapp(obj):
for kw in dir(app):
attr = getattr(app, kw)
if hasattr(attr, 'route'):
bottle.route(attr.route)(attr)
class App(object):
def __init__(self, config):
self.config = config
def index(self):
pass
index.route = '/index/'
app = App({'config':1})
routeapp(app)
Don't do the bottle.route() part in App.__init__(), because you won't be able to create two instances of App class.
If you like the syntax of decorators more than setting attribute index.route=, you can write a simple decorator:
def methodroute(route):
def decorator(f):
f.route = route
return f
return decorator
class App(object):
#methodroute('/index/')
def index(self):
pass
You have to extend the Bottle class. It's instances are WSGI web applications.
from bottle import Bottle
class MyApp(Bottle):
def __init__(self, name):
super(MyApp, self).__init__()
self.name = name
self.route('/', callback=self.index)
def index(self):
return "Hello, my name is " + self.name
app = MyApp('OOBottle')
app.run(host='localhost', port=8080)
What most examples out there are doing, including the answers previously provided to this question, are all reusing the "default app", not creating their own, and not using the convenience of object orientation and inheritance.
Below works nicely for me :)
Quite object orientated and easy to follow.
from bottle import Bottle, template
class Server:
def __init__(self, host, port):
self._host = host
self._port = port
self._app = Bottle()
self._route()
def _route(self):
self._app.route('/', method="GET", callback=self._index)
self._app.route('/hello/<name>', callback=self._hello)
def start(self):
self._app.run(host=self._host, port=self._port)
def _index(self):
return 'Welcome'
def _hello(self, name="Guest"):
return template('Hello {{name}}, how are you?', name=name)
server = Server(host='localhost', port=8090)
server.start()
I took #Skirmantas answer and modified it a bit to allow for keyword arguments in the decorator, like method, skip, etc:
def routemethod(route, **kwargs):
def decorator(f):
f.route = route
for arg in kwargs:
setattr(f, arg, kwargs[arg])
return f
return decorator
def routeapp(obj):
for kw in dir(obj):
attr = getattr(obj, kw)
if hasattr(attr, "route"):
if hasattr(attr, "method"):
method = getattr(attr, "method")
else:
method = "GET"
if hasattr(attr, "callback"):
callback = getattr(attr, "callback")
else:
callback = None
if hasattr(attr, "name"):
name = getattr(attr, "name")
else:
name = None
if hasattr(attr, "apply"):
aply = getattr(attr, "apply")
else:
aply = None
if hasattr(attr, "skip"):
skip = getattr(attr, "skip")
else:
skip = None
bottle.route(attr.route, method, callback, name, aply, skip)(attr)
try this, worked for me, documentation is also pretty decent to get started with ...
https://github.com/techchunks/bottleCBV
I know this question is quite old, but it is useful.
I am currently refactoring a Bottle application code into class. I am thinking about using something like:
import bottle
class App:
def __init__(self, port=80):
self.app = bottle.Bottle()
self.port = port
def setup_routes(self):
#self.app.route("/foo")
def foo():
return("foo")
#self.app.route("/bar")
def bar():
return("bar")
def start(self):
self.app.run(port=self.port)
a = App()
a.setup_routes()
a.start()
Does it work for your applications too? Feel free to comment, I am interested about this.
Notes from the creator of Bottle: https://github.com/bottlepy/bottle/issues/1224#issuecomment-619344849

Categories