Skip to content

Add handling of decorators when parsing arguments - #246

Closed
tyewang wants to merge 1 commit into
pyinvoke:mainfrom
tyewang:make_tasks_play_nicely_with_decorators
Closed

tyewang wants to merge 1 commit into
pyinvoke:mainfrom
tyewang:make_tasks_play_nicely_with_decorators

Conversation

@tyewang

@tyewang tyewang commented May 15, 2015

Copy link
Copy Markdown

I discovered that I couldn't pass in arguments to my tasks if my arguments were decorated.

For example:

def another_decorator(func):             
    def decorator(*args, **kwargs): 
        return func(*args, **kwargs)      
    return decorator

@task
@another_decorator
def my_task(my_argument):
    ...

In this example, running invoke my_task --my_argument 1234 would not work properly. Invoke's argument parsing only parsed the normal arguments of the decorated function, which it has none (it has varargs "args" and keyword arguments "kwargs").

This PR fixes this case.

@tyewang
tyewang force-pushed the make_tasks_play_nicely_with_decorators branch from 8dda82c to 36006e7 Compare May 15, 2015 23:14
Comment thread tests/tasks.py

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'm not sure how to run tests in this project. I eventually got frustrated and changed all the tests to unittest.TestCase and ran them using nose. How do you usually run tests?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tests run with spec, and we have a local helper for it as well, see http://www.pyinvoke.org/development.html#running-management-tasks

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I was able to get tests to run fine with invoke test, but I wasn't able to run individual tests or individual test files. Everytime I tried to use nosetest or spec on tests/tasks.py, it wouldn't detect any tests. So, how do you run individual tests?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That setup lets you load individual test files with -m (so e.g. inv test -m runners to run tests/runners.py). spec lacks support for individual tests, which is annoying and something I'll probably try to get working soon.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Cool, good to know. Thanks!

--- Original Message ---

From: "Jeff Forcier" notifications@github.com
Sent: May 22, 2015 5:23 PM
To: "pyinvoke/invoke" invoke@noreply.github.com
Cc: "Tye Wang" tyewang@outlook.com
Subject: Re: [invoke] Add handling of decorators when parsing arguments (#246)

@@ -293,3 +292,40 @@ def mytask(longer_arg):
eq_(arg.names, ('longer-arg', 'l'))
eq_(arg.attr_name, 'longer_arg')
eq_(arg.name, 'longer_arg')
+

  •    def decorated_function_names_are_preserved(self):
    

That setup lets you load individual test files with -m (so e.g. inv test -m runners to run tests/runners.py). spec lacks support for individual tests, which is annoying and something I'll probably try to get working soon.


Reply to this email directly or view it on GitHub:
https://github.com/pyinvoke/invoke/pull/246/files#r30931654

@tyewang
tyewang force-pushed the make_tasks_play_nicely_with_decorators branch from 36006e7 to 593d7d9 Compare June 26, 2015 14:58
Comment thread invoke/tasks.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • E127 continuation line over-indented for visual indent

@tyewang

tyewang commented Sep 9, 2015

Copy link
Copy Markdown
Author

Hi @bitprophet, this PR has been waiting for a while as well. Is there anything I need to do for this one to get merged?

@tyewang

tyewang commented Feb 21, 2016

Copy link
Copy Markdown
Author

@bitprophet any update?

@guyskk

guyskk commented Aug 1, 2018

Copy link
Copy Markdown

I need this PR for run async task, here is my case:

from curio import run

def async_task(f):
    @task
    @wraps(f)
    def wrapped(ctx, *args, **kwargs):
        return run(f(ctx, *args, *kwargs))
    return wrapped

I just read the code, some thoughts:

In python 3.3+, inspect.signature is a better method to get signature, it can also resolve signature
of callables which decorated by functool.wraps, see __wrapped__ attribute in functools document.
But in python 2, only inspect.getargspec is available.

The get_undecorated_func implement seems not very reliable, and here https://github.com/mapleoin/undecorated is a better implement.

If OK, I'm glad to contribute.

@guyskk

guyskk commented Aug 2, 2018

Copy link
Copy Markdown

Handle callable-but-not-function objects(Not cause by this PR) has problems, for example:

class Demo:
    def __call__(self, ctx, abc):
        print(self, ctx, abc)

demo = task(name='demo')(Demo())

When I invoke it:

$ inv demo --abc=1
'demo' did not receive all required positional arguments!

Comment in source code says:

# Handle callable-but-not-function objects
# TODO: __call__ exhibits the 'self' arg; do we manually nix 1st result
# in argspec, or is there a way to get the "really callable" spec?

What it means? we can simply ignore the first argument if the callable is not a function.

@bitprophet

Copy link
Copy Markdown
Member

2.0.0 will be out soon & is now using inspect.signature!

@bitprophet bitprophet closed this Jan 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants