is it possible to route errors to class-wrapped Bottle methods? - python

I wrap Bottle in a class and would like to bottle.route() error handlers. Is this possible? I currently use decorators on unbound functions as described in the docs (the comments reflect how I would like to change the code)
import bottle
class WebServer(object):
def __init__(self):
self.message = "hello world"
bottle.route("/", 'GET', self.root)
# bottle.route(error 404 to self.error404)
bottle.run(host='0.0.0.0', debug=True)
def root(self):
print("hello from root")
#bottle.error(404)
def error404(error):
# I would like to print self.message here after the routing above
print("error 404")
return
if __name__ == "__main__":
WebServer()
Note: I read the warning in another SO thread about not doing the routing in __init__ but I will be using only one instance of the class.

You should be able to define your error handler within Webserver.__init__:
import bottle
class WebServer(object):
def __init__(self):
self.message = "hello world"
bottle.route("/", 'GET', self.root)
# just define your error function here,
# while you still have a reference to "self"
#bottle.error(404)
def error404(error):
# do what you want with "self"
print(self.message)
return self.message
bottle.run(host='0.0.0.0', debug=True)
def root(self):
print("hello from root")
if __name__ == "__main__":
WebServer()

Related

function in another file wont get mocked

I have this class in a file called local.py:
def get_credentials(creds):
data = creds
return data
class ClassA:
def __init__(self):
body = "not a json"
self.credentials = get_credentials(body)
def run(self):
print(self.credentials)
def main():
inst = ClassA()
inst.run()
if __name__ == "__main__":
main()
all it does is return the credentials passed to it.
I want to mock the get_credentials function for which I have another file test_local.py:
from local import ClassA
import unittest
from unittest.mock import patch
def mock_get_credentials(creds):
return "123"
class NameTestCase(unittest.TestCase):
patch('local.get_credessntials', new=mock_get_credentials("test"))
def test_whatever(self):
print("true")
inst = ClassA()
inst.run()
self.assertEqual(1, 1)
if __name__ == '__main__':
unittest.main()
The output I keep getting is this:
true
not a json
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
The fact that it spits out "not a json" to me shows that it is not taking in the mocked value. I don't understand why it's doing this as I feel I have follow the documentation. Would appreciate some help with this as to why its not getting mocked.
There are a few typos in your code: you forgot the # for the patch decorator, the patched name is wrong, and you pass the function result instead of the function to new. Here is the relevant part of the fixed test:
class NameTestCase(unittest.TestCase):
#patch('local.get_credentials', new=mock_get_credentials)
def test_whatever(self):
inst = ClassA()
inst.run()
self.assertEqual(1, 1)

Python pseudo callback function

I have my main.py
import application
def foo(args):
print("Invoked!")
def main():
app = application.Application()
# here i want to connect app.receivedMessage to foo
and my application.py
class Application:
def __init__(self):
pass
def receivedMessage(self, args):
# somehow call foo(args)
Basically how can I call foo and pass the args when receivedMessage is called. I have other pieces to the Application class that listen to a usb message and invoke 'receivedMessage'
Thanks
You could pass the foo function to your Application object:
class Application:
def __init__(self, foo):
self.foo = foo
def receivedMessage(self, args):
self.foo(args)
Passing the function as an argument works fine too.
#!python3
class Application:
def __init__(self):
pass
def receivedMessage(self,args,**kwargs):
if kwargs and kwargs['foo']:
foo=kwargs['foo']
foo(args)
def foo(args):
print('Invoked')
if __name__=='__main__':
app = Application()
app.receivedMessage("haha", foo=foo) # works
app.receivedMessage("haha") # doesn't raise error

Suppress warning Eclipse when developing with Pydev

I want to suppress Eclipse warnings when defining decorators.
For example:
def tool_wrapper(func):
def inner(self):
cmd="test"
cmd+=func(self)
return inner
#tool_wrapper
def list_peer(self):
return "testing "
I get warning on a decorator definition:
"Method 'tool_wrapper' should have self as first parameter
I define the decorator inside a class, so this is the only way it's working properly.
Thanks
Just define your decorator outside the class and pass the instance as an argument, it will work just as fine.
def tool_wrapper(func):
def inner(inst): # inst : instance of the object
cmd="test"
cmd+=func(inst)
return cmd
return inner
class Test():
def __init__(self):
pass
#tool_wrapper
def list_peer(self):
return "testing "
if __name__ == '__main__':
t = Test()
print t.list_peer()
This script prints testtesting

Python classes: How should a built it

I am trying to create a class called ListenerVilma that has two methods: "Clock_" and "Diagnostics_". Nevertheless both methods will call inner functions. The following code shows my attempt to achieve the mentioned behavior, but when I call ListenerVilma.Clock_() the get the following error:
TypeError: unbound method Clock_() must be called with ListenerVilma instance as first argument (got nothing instead)
How should a create my class ListenerVilma???
Thanks.
#!/usr/bin/env python
import rospy
from rosgraph_msgs.msg import Clock
from diagnostic_msgs.msg import DiagnosticArray
class ListenerVilma:
"""Class that listens all topics of the file vilmafeagri"""
def Clock_(self):
"""Method that listens the topic /clock if the file vilmafeagri"""
def __init__(self):
self.listener()
def callback(self, clock):
print clock
def listener(self):
rospy.Subscriber('clock', Clock, self.callback)
def Diagnostics_(self):
"""Method that listen the topic /diagnostics from rosbag file vilmafeagri"""
def __init__(self):
self.listener()
def callback(self, diagnostics):
print diagnostics
def listener(self):
rospy.Subscriber('diagnostics', DiagnosticArray, self.callback)
if __name__ == '__main__':
rospy.init_node('listener', anonymous=True)
ListenerVilma.Clock_()
rospy.spin()
the error is in line 41 in ListenerVilma.Clock_() here your directly using the method of your class so no implicit argument is pass and a instance of ListenerVilma is expected. The solution is ListenerVilma().Clock_() this first create a instance of your class and from say instance call its Clock_ method.
Outside that, your class construction is very weird, the __init__ is used to initialize a class and a basic class construction is like this
class Foo:
"""example class"""
def __init__(self,*argv,**karg):
"""initialize this class"""
#do something with argv and/or karg according to the needs
#for example this
print "init argv", argv
print "init karg", karg
self.ultimate=42
def do_stuff(self):
"""this method do something"""
print "I am doing some stuff"
print "after 7.5 million years of calculations The Answer to the Ultimate Question of Life, the Universe, and Everything is: ", self.ultimate
def do_some_other_stuff(self,*argv,**karv):
"""this method do something else"""
print "method argv", argv
print "method karg", karg
# basic usage
test = Foo(1,2,3,key_test=23)
test.do_stuff()
test.do_some_other_stuff(7,8,9,something=32)
test.ultimate = 420
test.do_stuff()
I am not quite sure what you intentions are, but you build Clock_ and Diagnostics_ as a class, but they are not, and as right now they do nothing, if you want they to be class on their own do
class Clock_:
def __init__(self):
self.listener()
def callback(self, clock):
print clock
def listener(self):
rospy.Subscriber('clock', Clock, self.callback)
and the same with Diagnostics_, and I don't see a reason to the listener method so I would put what it does in the __init__, but maybe the rospy need it? I don't know, but for the looks of it then it should be used as
rospy.init_node('listener', anonymous=True)
Clock_()
Diagnostics_()
rospy.spin()
The Clock_ method doesn't belong to the class; it's an 'instance' method.
There are two options
In the main function: create an instance of ListenerVilma: listener = ListenerVilma(), or
In the ListenerVilma class: annotate the methods with #classmethod and make the class inherit from object: class ListenerVilma(object):. But remember, the first argument in your methods will be a reference to the class and not a reference to an instance.
The following code performs better the behavior that I wanted. :)
class ListenerVilma:
def CLOCK(self):
def clock_sub():
rospy.Subscriber('clock', Clock, clock_callback)
def clock_callback(clock):
print clock
clock_sub()
def DIAGNOSTICS(self):
def diagnostics_sub():
rospy.Subscriber('diagnostics', DiagnosticArray, diagnostics_callback)
def diagnostics_callback(diagnostics):
print diagnostics
diagnostics_sub()
if __name__ == '__main__':
rospy.init_node('listener', anonymous=True)
myVilma = ListenerVilma()
myVilma.CLOCK()
myVilma.DIAGNOSTICS()
rospy.spin()

Importing a class to another class in python

I am trying to learn python i tried to import a class in another class but it is not working
Application.py:
class Application:
def example(self):
return "i am from Application class"
Main.py
class Main:
def main():
application = Application()
application.example()
if __name__ == "__main__":
Main.main()
This gives me :
File "Main.py", line 11, in <module>
Main.main()
TypeError: unbound method main() must be called with Main instance as first argument (got nothing instead)
The error has nothing to do with importing (Although you don't seem to import Application anywhere). The problem is that you use the main method like a static method without declaring it to be static.
To solve this, You either need to declare your main method as static or create an instance of the Main class.
As a static method (add the #staticmethod decorator):
class Main():
#staticmethod
def main():
...
With an Instance:
class Main():
def main(self):
....
if __name__ == "__main__":
myMain = Main() #create an instance
myMain.main() #call the function on the instance
Also, to import your Application class from Application.py, you would just write this:
from Application import Application
You should instantiate your Main class first.
if __name__ == '__main__':
myMain = Main()
myMain.main()
But this will give you another error:
TypeError: main() takes no arguments (1 given)
There are two ways to fix this. Either make Main.main take one argument:
class Main:
def main(self):
application = Application()
application.example()
or make Main.main a static method. In which case you don't have to instantiate your Main class:
class Main:
#staticmethod
def main():
application = Application()
application.example()
if __name__ == "__main__":
Main.main()

Categories

Resources