Example from « Using Invoke as a library » gives « AttributeError » #283

zaiste opened this Issue Nov 2, 2015 · 8 comments


None yet

7 participants

zaiste commented Nov 2, 2015

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

  1. Install the package with python setup.py install
  2. Execute tester

it 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
  File "/usr/local/lib/python2.7/site-packages/invoke/program.py", line 301, in _parse
  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'
@bitprophet bitprophet added this to the 0.12 milestone Nov 3, 2015

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.

zaiste commented Nov 8, 2015

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...

matheo commented Nov 14, 2015

Yep, I'm having the same problem.
The Collection.from_module() worked #285

But the subcommands can't be executed :(

@bitprophet bitprophet modified the milestone: 0.13, 0.12 Dec 22, 2015


the same for me with Invoke 0.12.0. Code is here

best, Luca


Having the same problem with 0.12.2

kiesel commented Feb 12, 2016


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()
@bitprophet bitprophet modified the milestone: 0.13, 0.14 Jun 11, 2016
bitprophet commented Nov 30, 2016 edited

FTR, this is really two issues:

  • Initially, as I noted in the past, the problem was a documentation one: currently 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.
  • However, you'll then hit issue #288, which is also an 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.

@bitprophet bitprophet modified the milestone: 0.16 Feb 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment