Mature TiddlyWeb plugins need to be packaged so they can be indexed by pypi and installed via pip. At base this is relatively straightforward, put some stuff in a directory, make a setup.py
, register the package, package up a source distribution, tell PyPI about it.
This is okay if you have a good name for your package, but what about packages, like plugins for TiddlyWeb, which have names which are only meaningful in their use context? You can't just use the name of the module, otherwise you end up with namespace collisions, trouble finding stuff, and associated beasts of chaos.
Thankfully distutils
, setuptools
, pip
, etc conspire to support a notion called namespace_packages
which can solve this issue. Unfortunately using the feature is not exceptionally well documented. I (@cdent) found getting started a bit frustrating, until I sort of cracked the nut. Here's some info for reference.
First some prerequisites:
- You need setuptools
- You need a username and password on PyPi.
- Some understanding of how to make a Python package distribution. Here's one tutorial: Use setup.py to Deploy Your Python App with Style.
- Some understanding of Python packages.
That tutorial includes a section about using namespace_packages
under the heading "Multiple Distributions, One (Virtual) Package". That "Virtual" is key: if you wish to use namespace packages there must be no real distribution which occupies the namespace. In the example of tiddlywebplugins
, you can have tiddlywebplugins.static
and tiddlywebplugins.utils
distributions which are members of the tiddlywebplugins
namespace, but you must not have a tiddlywebplugins
distribution. If you do, the packages which are supposed to occupy the virtual namespace will not be found. The upshot of this is that if you already have a package out there using a name that you want to use as a namespace, you will need to rename the existing package (this is why the old tiddlywebplugins package is now tiddlywebplugins.utils.
Packaging a Plugin
So say you have a TiddlyWeb plugin called foobar.py
sitting in a directory somewhere. You've determined that it is a happy little plugin and the world would benefit if it could be installed easily. You've heard of the tiddlywebplugins namespace and you'd like to join the party. Here's what you do.
- In that directory make a
tiddlywebplugins
directory. -
Edit
tiddlywebplugins/__init__.py
to include just this line:__import__("pkg_resources").declare_namespace(__name__
-
Move
foobar.py
into thetiddlywebplugins
directory. - Create a
setup.py
(in the original directory) that includes at least:
from setuptools import setup, find_packages
setup(
version = '0.1',
namespace_packages = ['tiddlywebplugins'],
name = 'tiddlywebplugins.foobar',
description = 'A TiddlyWeb plugin for foobaring the fritz.',
install_requires = ['setuptools', 'tiddlyweb'],
)
- Do not import from the tiddlywebplugins package in setup.py. This will make installs struggle or fail later.
- Learn enough about distribution to register the package and upload it. The links above point to enough documentation to figure that part out. If you can't be bothered to read that documentation then you shouldn't be distributing packages. We wouldn't want you aol-ing all over PyPi.
- When you want to use your foobar plugin in a TiddlyWeb instance or application refer to it as
tiddlywebplugins.foobar
.
A github repository called pluginmaker has been created which captures all the necessaries for creating a plugin in the tiddlywebplugins
namespace.