TL;TR: For illustration-purposes the lines of this document beginning with 'TL;TR:' are followed by commandline refering to Plone-helper-scripts of the egg 'adi.devgen'. If you execute the command given after 'TL;TR:', it will create all the files explained of the following chapter. There are many alternative helper-script-tools, however in case you want to use this tool, you can install it quickly like this of the commandline:
pip install adi.devgen
TL;TR: devgen addBase mynamespace.myaddon
Just like Plone consists of more than 200 Python-eggs, a Plone-Add-On is also a Python-egg and an egg is a namespaced Python-module. Any egg will be available to the Python-interpreter of ZOPE. To make an egg installable in a Plone-site, it also needs a so called 'profile'. The following will explain these terms.
A Python module is a directory which contains at least one file which must be
named __init__.py
. The name is a flag for the Python-interpreter to
recognize this directory as a module, meaning its path can be imported of other
Python-scripts, e.g. assuming we have a directory called 'myaddon', which
contains a file called 'myfile' and that file contains a defintion called
'myDefinition', you can import the definition of another Python-file like this:
from myaddon.myfile import myDefinition
A Python-egg is a namespaced Python-module, a namespace can be any name, but it should better not be taken already, in case you want to share your add-on with the world.
The reason for namespacing is foremost to exclude the possibility that two or more modules could have the same name (in this example called 'myaddon'), as it would result in conflicts when a Python-script tries to import the path, being not unique anymore.
Here is an overview of the directory-structure and files involved, before we continue to explain their purposes in detail furtheron:
mynamespace.myaddon
setup.py
mynamespace
__init__.py
myaddon
__init__.py
myfile.py
To namespace an add-on firstly create a directory named 'mynamespace.myaddon'.
This directory must contain the 'setup.py'-file, it makes the egg registrable to the Python-interpreter of the ZOPE-instance, this is further explained in the next chapter[TODO].
Then, in that directory, create another directory named after your namespace:
'mynamespace' Now, we make this directory an importable module-path, by adding
the keyword-named file __init__.py
in it. It also must contain the following
lines, which make the namespace-magic happen, explained in the last paragraph:
[TODO: namespace-magic-lines]
Phew almost done, lastly in this new directory we put the module of the previous chapter: The directory 'myaddon', containing the 'init.py' and 'myfile.py' with the 'myDefinition'.
Now we have an registrable egg for the ZOPE-instance and could reference its methods of any other registered egg, using this path-notation:
from mynamespace.myaddon.myfile import myDefinition
You might see the magic, the first two directories are omitted, it is not:
from mynamespace.myaddon.mynamespace.myaddon.myfile import myDefinition
[TODO:
A 'profile' will make the add-on show up in the add-ons-controlpanel of a site, so an admin can (de-)activate it there for the site.
Additionally, as a Plone-site is always a child of ZOPE-instance and a ZOPE-instance can contain several sites, we might not want to have unintendendly components of our add-on installed in other Plone-sites, therefore we bind them to a 'profile'.
TL;TR: devgen addProfile mynamespace.myaddon
This leads us to the really interesting parts, the ZOPE-Component-Architecture, controlled by the files ending with '.zcml', which stands for 'ZOPE-Component- Markup-Language'. With it you can register a profile, bind views to interfaces and much more. In fact, it deserves an own major chapter and a subchapter for each of the directories called "profile", "skins", "browser" and "content".