Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create feedback decorator #66

Merged
merged 6 commits into from
Sep 5, 2017
Merged

Create feedback decorator #66

merged 6 commits into from
Sep 5, 2017

Conversation

ArchdukeTim
Copy link
Contributor

The first iteration of a feedback decorator.

I think paired with an auto-send property that you can use with variables and not methods, networktables will be much smoother

@@ -540,6 +560,11 @@ def _inject(self, n, inject_type, cname, component):
# for f in d.keys():
# d[f] = f(component)

def update_feedback(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't anything calling this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I don't know how magicrobot works 😉

@@ -17,6 +17,21 @@

__all__ = ['MagicRobot']

def feedback(key=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No docstring? What is this supposed to do? Maybe add an example in the docstring too?

# If no key is passed, get key from method name.
# -1 instead of 1 in case 'get_' is not present,
# in which case the key will be the method name
nt_key = func.__name__.split('get_')[-1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break if get_ is a non-prefix substring of the function name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so? It should still return whatever comes after 'get_', no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>>> 'forget_me'.split('get_')[-1]
'me'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that scenario, I imagine you want forget_me to be the method, but what about if the method name was... reverse_get_speed. Would the expected key be speed? or reverse_get_speed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another problem is what if they use camelCase and not lowercase_underscore?

def _update_feedback(self):
for (component, cname, name) in self._feedbacks:
# Put ntvalue at /robot/components/component/key
self.__nt.putValue('/components/{0}/{1}'.format(cname, getattr(component, name).__key__), getattr(component, name)())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe avoid calling getattr with the same arguments multiple times. getattr(...)() looks particularly ugly.

setattr(func, '__feedback__', True)
# Store key within the function to avoid using class dictionary
setattr(func, '__key__', nt_key)
return func
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that this should check the function to see if (a) it's a function and (b) do the function arguments match what is required (eg, only a single argument named 'self').

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it need to be named self?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't need to be but there typically aren't reasons for it not to be, so we should enforce it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Luckily state_machine has some code I can steal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still hasn't been added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm I thought I did...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol I did just didn't push

for (component, cname, name) in self._feedbacks:
func = getattr(component, name)
# Put ntvalue at /robot/components/component/key
self.__nt.putValue('/components/{0}/{1}'.format(cname, func.__key__), func())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If func throws, then the entire robot will be dead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'd be embarrassing

Not sure how this would get triggered though, since the name only
gets added to the feedbacks if it is there with the feedback decorator,
but, better safe than sorry
I've decided that (as the docstring states), if the method doesn't
start with `get_` then the key in NetworkTables will be the full name
of the method
nt_key = func.__name__.split('get_')[-1]
name = func.__name__
if name.startswith('get_'):
nt_key = name.split('get_')[1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also still fail if get_ is a non-prefix substring of name.

Copy link
Contributor Author

@ArchdukeTim ArchdukeTim Aug 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it won't. That's what the startswith checks for
Oh you mean if it starts with get and has get again...hmmm...and ideas on how to deal with?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nt_key = name[4:]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3smart5me

@virtuald virtuald merged commit 688ff3a into robotpy:master Sep 5, 2017
@ArchdukeTim ArchdukeTim deleted the feedback branch September 5, 2017 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants