Here's the code: https://github.com/zaiste/invoke-example-bug
I followed this tutorial: http://invoke.readthedocs.org/en/latest/concepts/library.html#reusing-as-a-binary
python setup.py installtesterit returns:
Traceback (most recent call last):
File "/usr/local/bin/tester", line 9, in <module>
load_entry_point('tester==0.1.0', 'console_scripts', 'tester')()
File "/usr/local/lib/python2.7/site-packages/invoke/program.py", line 246, in run
self._parse(argv)
File "/usr/local/lib/python2.7/site-packages/invoke/program.py", line 301, in _parse
self.parse_tasks()
File "/usr/local/lib/python2.7/site-packages/invoke/program.py", line 458, in parse_tasks
self.parser = Parser(contexts=self.collection.to_contexts())
AttributeError: 'module' object has no attribute 'to_contexts'
Thanks, will try to replicate on my end but sounds plausible :) may simply need a Collection() wrapped around the module object (so, namespace=Collection(tasks)), though that seems like something odd for me to have overlooked.
I've tried namespace=Collection(tasks) and Collection.from_module(tasks), but it still doesn't work. Now, I'm getting AttributeError: list. I'm not sure how to debug this...
Yep, I'm having the same problem.
The Collection.from_module() worked https://github.com/pyinvoke/invoke/pull/285
But the subcommands can't be executed :(
Having the same problem with 0.12.2
Hi,
I am also seeing this issue; after poking around with the source, I figured it is caused by not including the task_args into the initial context when the namespace is not None.
In other words, I can get the example to work when this diff applied:
diff --git a/invoke/program.py b/invoke/program.py
index 078f9fc..ac799a6 100644
--- a/invoke/program.py
+++ b/invoke/program.py
@@ -429,8 +429,7 @@ class Program(object):
whether a bundled namespace was specified in `.__init__`.
"""
args = self.core_args()
- if self.namespace is None:
- args += self.task_args()
+ args += self.task_args()
return ParserContext(args=args)
def print_version(self):
... and setting up the Program like this:
program = Program(namespace=Collection.from_module(tasks), version= '0.1.0')
However, I don't see why the task_args are omitted with a namespace, so I suspect something else will possibly break with my patch. Maybe it helps tracking down the issue, though :)
Based on the comment by @kiesel, this seems to work for me:
def pyinvoke_issue_283():
from invoke.parser import ParserContext
def initial_context(self):
args = self.core_args()
args += self.task_args()
return ParserContext(args=args)
return property(initial_context)
Program.initial_context = pyinvoke_issue_283()
FTR, this is really two issues:
Program(namespace=xxx) is supposed to take a Collection object, and the doc example doesn't properly reflect that. Rubbing Collection.from_module on it fixes the issue.AttributeError symptom, but with a different attribute/message. Easy to overlook as @zaiste probably did.I have merged #288 and fixed the doc re: this issue, and my real world code that uses namespace=xxx is now working.
For anyone getting this error using flit you can just wrap you entry point with a method.
program = Program(...)
def main():
program.run()
[tool.flit.scripts]
program = "program:main"
Most helpful comment
Hi,
I am also seeing this issue; after poking around with the source, I figured it is caused by not including the
task_argsinto the initial context when the namespace is not None.In other words, I can get the example to work when this diff applied:
... and setting up the Program like this:
However, I don't see why the task_args are omitted with a namespace, so I suspect something else will possibly break with my patch. Maybe it helps tracking down the issue, though :)