{"action":"created","issue":{"url":"https://api.github.com/repos/ejeschke/ginga/issues/169","labels_url":"https://api.github.com/repos/ejeschke/ginga/issues/169/labels{/name}","comments_url":"https://api.github.com/repos/ejeschke/ginga/issues/169/comments","events_url":"https://api.github.com/repos/ejeschke/ginga/issues/169/events","html_url":"https://github.com/ejeschke/ginga/pull/169","id":109556756,"number":169,"title":"Turn ginga.*.plugins into namespace packages","user":{"login":"pllim","id":2090236,"avatar_url":"https://avatars.githubusercontent.com/u/2090236?v=3","gravatar_id":"","url":"https://api.github.com/users/pllim","html_url":"https://github.com/pllim","followers_url":"https://api.github.com/users/pllim/followers","following_url":"https://api.github.com/users/pllim/following{/other_user}","gists_url":"https://api.github.com/users/pllim/gists{/gist_id}","starred_url":"https://api.github.com/users/pllim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pllim/subscriptions","organizations_url":"https://api.github.com/users/pllim/orgs","repos_url":"https://api.github.com/users/pllim/repos","events_url":"https://api.github.com/users/pllim/events{/privacy}","received_events_url":"https://api.github.com/users/pllim/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-10-02T19:29:57Z","updated_at":"2015-10-05T18:49:50Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ejeschke/ginga/pulls/169","html_url":"https://github.com/ejeschke/ginga/pull/169","diff_url":"https://github.com/ejeschke/ginga/pull/169.diff","patch_url":"https://github.com/ejeschke/ginga/pull/169.patch"},"body":"Turn `ginga.*.plugins` into namespace packages, as discussed in #92.\r\n\r\nWith this change, I can add my own custom plugins under the `ginga.qtw.plugins` namespace with this directory structure:\r\n```\r\n+- mygingastuff/\r\n    +- ginga/\r\n    |   +- __init__.py\r\n    |   +- qtw/\r\n    |   |   +- __init__.py\r\n    |   |   +- plugins/\r\n    |   |   |   +- MyGlobalPlugin2.py\r\n    |   |   |   +- MyLocalPlugin2.py\r\n    |   |   |   +- __init__.py\r\n    +- setup.py\r\n```\r\n\r\nThe contents of each `__init__.py` (as pointed out by @embray):\r\n```python\r\ntry:\r\n    # As long as we're using setuptools/distribute, we need to do this the\r\n    # setuptools way or else pkg_resources will throw up unncessary and\r\n    # annoying warnings (even though the namespace mechanism will still\r\n    # otherwise work without it).\r\n    # Get rid of this as soon as setuptools/distribute is dead.\r\n    __import__('pkg_resources').declare_namespace(__name__)\r\nexcept ImportError:\r\n    pass\r\n__path__ = __import__('pkgutil').extend_path(__path__, __name__)\r\n```\r\n\r\nThis is an example `setup.py`:\r\n```python\r\n#! /usr/bin/env python\r\n#\r\ntry:\r\n    from setuptools import setup\r\nexcept ImportError:\r\n    from distutils.core import setup\r\n\r\nsetup(\r\n    version = '0.1.0',\r\n    name = 'mygingastuff',\r\n    namespace_packages = ['ginga'],\r\n    packages = ['ginga', 'ginga.qtw', 'ginga.qtw.plugins'],\r\n    author = 'J. Doe',\r\n    description = 'Ginga Qt plugins',\r\n    long_description = 'Ginga Qt plugins'\r\n)\r\n```\r\n\r\nTo start Ginga with these plugins from command line:\r\n```\r\nginga --loglevel=20 --log=ginga.log --plugins=MyLocalPlugin2 --modules=MyGlobalPlugin2 myimage.fits\r\n```\r\n\r\nAs far as Python is concerned, it is the same namespace although the plugins reside in two separate actual packages:\r\n```python\r\n>>> from ginga.qtw.plugins import Contents\r\n>>> Contents\r\n<module 'ginga.qtw.plugins.Contents' from '.../ginga-2.5.20151001032930-py2.7.egg/ginga/qtw/plugins/Contents.pyc'>\r\n>>> from ginga.qtw.plugins import MyLocalPlugin2\r\n>>> MyLocalPlugin2\r\n<module 'ginga.qtw.plugins.MyLocalPlugin2' from '.../mygingastuff-0.1.0-py2.7.egg/ginga/qtw/plugins/MyLocalPlugin2.pyc'>\r\n```"},"comment":{"url":"https://api.github.com/repos/ejeschke/ginga/issues/comments/145629918","html_url":"https://github.com/ejeschke/ginga/pull/169#issuecomment-145629918","issue_url":"https://api.github.com/repos/ejeschke/ginga/issues/169","id":145629918,"user":{"login":"pllim","id":2090236,"avatar_url":"https://avatars.githubusercontent.com/u/2090236?v=3","gravatar_id":"","url":"https://api.github.com/users/pllim","html_url":"https://github.com/pllim","followers_url":"https://api.github.com/users/pllim/followers","following_url":"https://api.github.com/users/pllim/following{/other_user}","gists_url":"https://api.github.com/users/pllim/gists{/gist_id}","starred_url":"https://api.github.com/users/pllim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pllim/subscriptions","organizations_url":"https://api.github.com/users/pllim/orgs","repos_url":"https://api.github.com/users/pllim/repos","events_url":"https://api.github.com/users/pllim/events{/privacy}","received_events_url":"https://api.github.com/users/pllim/received_events","type":"User","site_admin":false},"created_at":"2015-10-05T18:49:49Z","updated_at":"2015-10-05T18:49:49Z","body":"> does this work under python 3 ?\r\n\r\nYes.\r\n\r\n> does every `__init__.py` have to have this declaration?\r\n\r\nWhen I remove the incantation from submodule init, the following fails, so as far as I am concerned, it needs to be repeated on all levels.\r\n```python\r\n>>> from ginga.qtw.plugins import Contents, MyLocalPlugin2\r\n```"}}