{"issue":{"created_at":"2011-11-16T22:10:48Z","state":"open","updated_at":"2011-11-23T21:03:37Z","user":{"gravatar_id":"2828f28fb012308a7786eee83b8293c5","id":1299,"url":"https://api.github.com/users/mitchellh","login":"mitchellh","avatar_url":"https://secure.gravatar.com/avatar/2828f28fb012308a7786eee83b8293c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png"},"comments":1,"body":"Hello,\r\n\r\nWorking with the \"new\" (for me!) 1.3 version and loving it so far. But I'm finding some oddities based on what I would expect to be behavior, in this case with the new `execute` function. I have a module named `deploy` (so living in `deploy.py`) which I import tasks from. Here is a hypothetical `fabfile`:\r\n\r\n```python\r\nimport deploy\r\n```\r\n\r\nHere is a hypothetical `deploy.py`:\r\n\r\n```python\r\nfrom fabric.api import execute, task\r\n\r\n@task(default=True)\r\ndef deploy():\r\n    execute(\"foo\")\r\n\r\n@task\r\ndef foo():\r\n    print(\"Foo called!\")\r\n```\r\n\r\nThe above actually doesn't work because `execute` expects a valid task name. But note that that pushes knowledge into the deploy module of knowing how the deploy module is imported into a Fabfile. So, sure, I can do this to make it work:\r\n\r\n```python\r\nexecute(\"deploy.foo\")\r\n```\r\n\r\nSo that works. But what if I then change the fabfile to this:\r\n\r\n```python\r\nimport deploy as old_deploy\r\n```\r\n\r\nNow the old deploy actually breaks! \r\n\r\nI think this knowledge of how a module is imported doesn't belong in the module. In fact, I think before checking for a valid task name, I think that the `execute` semantics should check the currently available tasks and try to execute that. Then you can do whatever you want wit the knowledge you're 100% sure you have in your module, and it will always work.\r\n\r\nBest,\r\nMitchell","assignee":{"gravatar_id":"f1acc6318028fdba9874c77bc622a2fb","id":6088,"url":"https://api.github.com/users/bitprophet","login":"bitprophet","avatar_url":"https://secure.gravatar.com/avatar/f1acc6318028fdba9874c77bc622a2fb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png"},"id":2262532,"number":479,"labels":[{"name":"1.x","color":"DDDDDD","url":"https://api.github.com/repos/fabric/fabric/labels/1.x"},{"name":"Bug","color":"a04040","url":"https://api.github.com/repos/fabric/fabric/labels/Bug"},{"name":"Core","color":"ededed","url":"https://api.github.com/repos/fabric/fabric/labels/Core"},{"name":"Wart","color":"e10c02","url":"https://api.github.com/repos/fabric/fabric/labels/Wart"}],"pull_request":{"patch_url":null,"html_url":null,"diff_url":null},"title":"Execute should be able to reference locally available tasks","closed_at":null,"html_url":"https://github.com/fabric/fabric/issues/479","milestone":{"created_at":"2011-11-16T22:16:45Z","state":"open","due_on":null,"closed_issues":11,"creator":{"gravatar_id":"f1acc6318028fdba9874c77bc622a2fb","id":6088,"url":"https://api.github.com/users/bitprophet","login":"bitprophet","avatar_url":"https://secure.gravatar.com/avatar/f1acc6318028fdba9874c77bc622a2fb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png"},"number":17,"title":"1.3.3 et al","description":"","open_issues":1,"url":"https://api.github.com/repos/fabric/fabric/milestones/17"},"url":"https://api.github.com/repos/fabric/fabric/issues/479"},"action":"created","comment":{"created_at":"2011-11-23T21:03:37Z","updated_at":"2011-11-23T21:03:37Z","user":{"gravatar_id":"f1acc6318028fdba9874c77bc622a2fb","id":6088,"url":"https://api.github.com/users/bitprophet","login":"bitprophet","avatar_url":"https://secure.gravatar.com/avatar/f1acc6318028fdba9874c77bc622a2fb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png"},"body":"Yes, the problem here is that `execute(\"string arg\")`, in the context of `fab` and thus a fabfile, considers a global data structure compiled from loading the fabfile module (and then any sub-modules inside it as per the namespacing docs.)\r\n\r\nIt's *probably* possible to update the namespacing/crawling mechanism (or maybe even just the name lookup of `execute`) to make \"relative\" task references work.\r\n\r\nHowever, part of me wants to say that in this case you should just be using the `foo` object itself, i.e. `execute(foo)`. This should work even if `foo` is defined \"after\" `deploy`, based on memory and a quick test.\r\n\r\nPut another way, `execute(\"task\")` is basically for use in the global context, while `execute(task)` is more low-level/flexible/API-friendly and is what should be used in more specific contexts.\r\n\r\n----\r\n\r\nI'm +0 on taking the high road here and trying to make relative task names work; it could be a moderate amt of effort/complexity-add for (IMO) little gain, though it certainly would be clean and prevent the surprise you ran into.\r\n\r\nThe alternate/lazy solution would be to update the `execute` docs to make it clear that relative task names do not work and one should use object reference instead.\r\n\r\n----\r\n\r\nI'll take a quick look in case relative naming is easier than I think; otherwise, patches welcome if you have the time.","id":2854806,"url":"https://api.github.com/repos/fabric/fabric/issues/comments/2854806"}}