Pass arguments to command groups, python fire - python

How can I pass the arguments val and code to the group get
Code so far
import fire
class Get:
def __init__(self, val="no", code=""):
self.val = val
self.code = code
def get(self):
return f"called get {self.val} {self.code}"
def get_many(self):
return f"called get many {self.val}"
class Pipeline:
def __init__(self,):
self.get = Get()
def main():
fire.Fire(Pipeline)
The error I Got
$> my_p get --code="test" --val="yes" get
ERROR: Could not consume arg: --code=test
Usage: my_p get get <command>

according to https://github.com/google/python-fire/blob/master/docs/guide.md#version-4-firefireclass
you need to change :
self.get = Get
Besides, I recommend to not use the same name in "get" function in class Get. It is confusing.

import fire
class Get(object):
def __init__(self, attr):
self.attr = attr
def get(self):
return f"called get {self.attr.val} {self.attr.code}"
def get_many(self):
return f"called get many {self.attr.val}"
class Pipeline(object):
def __init__(self, **kwargs):
for key, val in kwargs.items():
self.__dict__[key] = kwargs.get(key, val)
self.get = Get(self)
if __name__ == "__main__":
fire.Fire(Pipeline)
output
python my_p.py get --code="test" --val="yes" get
called get yes test

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"

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

Pythonic way to access Flask request arguements

In my Flask app I am setting a number of local variables that have come in via an API call, using the
from flask import request
.
.
submission_id = request.args.get('submission_id')
grader = request.args.get('grader')
grading_factor = float(request.args.get('grading_factor'))
answer_key = request.args.get('answer_key')
submission_key = request.args.get('submission_key')
What is a less repetitive or otherwise more Pythonic way of setting these 5 variables?
As I suggested in the comments, you could come up with a decorator that would map the request arguments to the corresponding function parameters, such as:
def map_args(func):
#functools.wraps(func)
def wrapper(**kwargs):
all_args = dict(request.args, **kwargs)
return func(**all_args)
return wrapper
Then:
#app.route('/mypath')
#map_args
def handler(submission_id, grader, grading_factor, ...):
"""the remaining logic"""
That's similar to what Flask does with the view_args, except that it does not do any type conversions, which this margin is too narrow to contain.
from flask import Flask, request
app = Flask(__name__)
class DotDict(object):
def __init__(self, inner):
self._inner = inner
def __getattr__(self, item):
return self._inner.get(item)
def get(self, item, default=None):
return self._inner.get(item, default)
class LazyAttribute(object):
def __init__(self, obj, attr):
self.obj = obj
self.attr = attr
def __getattribute__(self, item):
return getattr(getattr(object.__getattribute__(self, 'obj'),
object.__getattribute__(self, 'attr')),
item)
rargs = DotDict(LazyAttribute(request, 'args'))
#app.route("/")
def hello():
print rargs.a, rargs.c, rargs.get('d', 3)
return "Hello World!"
if __name__ == "__main__":
app.run(debug=True)
Accessing http://localhost:5000/?a=1 prints 1 None 3 in the terminal.
The LazyAttribute class is because calling just DotDict(request.args) outside of a request context throws an error. The alternative is to make a function:
def rargs():
return DotDict(request.args)
but I wanted to make usage as smooth as possible.
Firstly, I don't think there's anything wrong with the way you're doing it. But, there are a couple of different approaches you could take; the first being to the call to get the argument from request:
from flask import request
# ...
def getRequestArg(name, *args):
return request.args.get(name, *args)
submission_id = getRequestArg('submission_id')
grader = getRequestArg('grader')
grading_factor = float(getRequestArg('grading_factor'))
answer_key = getRequestArg('answer_key')
submission_key = getRequestArg('submission_key')
If you don't need each of these to be separate local variables, you could store them all in a dict:
from flask import request
# ...
args = {}
arg_names = ('submission_id', 'grader', 'grading_factor', 'answer_key', 'submission_key')
for arg in arg_names:
args[arg] = request.args.get(arg)

Using __setattr__ + __slots__ in a python3 class

I am trying to be all fancy with sub element attribute access in a custom class hierarchy.
My fanciness works in that I can successfully use descriptors to do this.
I want to be even more fancy and make the class RefHolder (shown below in the testcase) use slots to save space.
When I try to use slots though, I get RuntimeError: maximum recursion depth exceeded
Note that I have already tried looking at existing solutions for this, the most closely matching I could find being this one:
https://stackoverflow.com/a/19566973/1671693
I have tried this in the testcase below but I am still get the runtimeerror.
Note that in the testcase, if the commented lines are used instead of the ones directly beneath them and __slots__ is removed from RefHolder,
The testcase passes.
Any suggestions?
Additionally, I am creating an object for every attribute access which seems expensive, are there any suggestions on a more efficient way of achieving the same behavior? Thanks!
import unittest
class RefHolder():
__slots__ = ['__obj', 'get_value']
def __init__(self, obj, get_value=False):
self.__dict__['__obj'] = obj
self.__dict__['get_value']=get_value
def get_sub(self, name):
#attr = self.__dict__['__obj'].find_by_name(name)
attr = self.__dict__['__obj'].__get__(self, RefHolder).find_by_name(name)
if attr is None:
raise AttributeError("Can't find field {}".format(name))
return attr
def __getattr__(self, name):
attr = self.get_sub(name)
#if self.__dict__['get_value']:
if self.__dict__['get_value'].__get__(self, RefHolder):
return attr.Value
else:
return attr
def __setattr__(self, name, value):
attr = self.get_sub(name)
#if self.__dict__['get_value']:
if self.__dict__['get_value'].__get__(self, RefHolder):
attr.Value = value
else:
raise AttributeError("{} is read only in this context".format(name))
class ContainerAccess():
__slots__ = ['get_value']
def __init__(self, get_value=False):
self.get_value = get_value
def __get__(self, obj, objtype=None):
if obj is None:
return self
return RefHolder(obj, self.get_value)
def __set__(self, obj, value):
raise AttributeError("Read Only attribute".format(value))
class PropVal():
def __init__(self, val):
self.Value = val
#property
def Value(self):
return self._value
#Value.setter
def Value(self, value):
self._value = value
class T():
get = ContainerAccess()
getv = ContainerAccess(get_value=True)
def __init__(self):
self.store = {}
self._value = 0
def find_by_name(self, name):
return self.store.get(name)
class T2(T):
pass
class TestDesc(unittest.TestCase):
def test_it(self):
t = T()
t2 = T2()
t.store['my_val'] = PropVal(5)
t.store['my_val2'] = PropVal(6)
t2.store['my_val'] = PropVal(1)
self.assertEqual(t.get.my_val.Value, 5)
self.assertEqual(t.get.my_val2.Value, 6)
self.assertEqual(t2.get.my_val.Value, 1)
t.get.my_val.Value = 6
self.assertEqual(t.get.my_val.Value, 6)
with self.assertRaises(AttributeError):
t.get.blah.Value = 6
#self.assertEqual(t.get.my_other_val.Value, None)
self.assertEqual(t.getv.my_val, 6)
t.getv.my_val = 7
self.assertEqual(t.getv.my_val, 7)
with self.assertRaises(AttributeError):
t.get.my_val = 7

Derived class doesn't recognise arguments of method from parent

I'm trying to make a set of functions to operate easily through some data.
The problem I'm facing is: it seems to recognize and use methods from the parent class, except one: show(), giving me errors about unexpected arguments.
Here's a sample of the classes:
from treelib import Tree, Node
class Join(Tree):
def __init__(self, id, desc, childs=(), *args, **kwargs):
Tree.__init__(self, *args, **kwargs)
self.id = id
self.desc = desc
self.value = None
self.parent = None
self.childs = None
self.create_node(tag=desc, identifier=id)
for i in childs:
self.paste(self.id, i)
def getSons(self):
sons = self.children(self.id)
return sons
def getID(self):
return self.id
def getDesc(self):
return self.desc
def show(self):
self.show(key=lambda x: x.tag, reverse=True, line_type='ascii-em')
class Get(Tree):
def __init__(self, id, desc, primitive, *args, **kwargs):
Tree.__init__(self, *args, **kwargs)
self.id = id
self.desc = desc
self.parent = None
self.primitive = primitive
self.create_node(tag=desc, identifier=id, data=primitive)
def getID(self):
return self.id
def getDesc(self):
return self.desc
def show(self):
self.show(key=lambda x: x.tag, reverse=True, line_type='ascii-em')
class Primitive():
def __init__(self, value):
self.value = value
def getValue(self):
return self.value
def show(self):
pass
#print '\t -> ' + str(self.value)
If, for example, I do this on another .py
prim = Primitive(0)
get1 = Get("get1", "Some random thing", prim)
get1.show()
it tells me that key is an unexpected argument. I even checked the library's .py file, the argument is there:
def show(self, nid=None, level=ROOT, idhidden=True, filter=None,
key=None, reverse=False, line_type='ascii-ex'):
The create_node() method works just fine! That's what's weird. Any suggestions?
I'm using treelib in Python 2.7
Your method show() calls itself:
def show(self):
self.show(key=lambda x: x.tag, reverse=True, line_type='ascii-em')
Removed it in Get and change it in Join to:
def show(self):
super(Join, self).show(key=lambda x: x.tag, reverse=True, line_type='ascii-em')

Categories