Filesystem organisation
In the Zope 3 world, the Products pseudo-namespace is frowned upon. In Zope 2, every extension module lives in the Products/ folder. This raises some obvious namespace clash concerns, but also separates Zope modules further from plain-Python modules. In Zope 3, you can install a module anywhere in your PYTHONPATH. For example, in Plone 3.0, there will be a module called plone.portlets, normally installed in lib/python/plone/portlets.
For modules that need to act like Zope products (i.e. they need an initialize() method, they install content types, they register a GenericSetup profile or CMF skins or use an Extensions/Install.py method, say), this works in Zope 2.10 and later. It can also be made to work in earlier version of Zope using a product (ironically) called pythonproducts.
For the purposes of borg, we stick with the traditional Products/ installation. It's nice to have imports like from borg import ..., but fundamentally, b-org is very closely tied to Zope (2) and Plone, so the re-use argument goes away, and that nice import syntax is not really worth the extra dependency and configuration.
One thing you may notice, though, is that the borg product is named in lowercase, in keeping with Zope 3 and Python naming conventions. Looking inside it, you will see the following key files and directories:
- __init__.py
- Initialises the Zope 2 product machinery, registers content types, the skin layer and the GenericSetup extension profile that is used to install b-org.
- config.py
- Holds various constants
- configure.zcml
- Starts the Zope 3 snowball going. This references other packages with their own configure.zcml files.
- content/
- Contains the Archetypes content types for Department, Employee and Project. Also contains some utilities, like EmployeeLocator, an adapter to find employees, two utilities used to provide vocabularies AddableTypesProvider and ValidRolesProvider, and the the schema extension mechanism in schema.py.
- events/
- Contains event subscribers which modify ownership of an Employee object so that the employee user owns it (and can thus edit their own profiles, for example), as well as to set up the local workflow when a Project is created.
- interfaces/
- Contains all the interfaces that b-org defines, in various sub-modules like interfaces/employee.py for the Employee-related interfaces. All of these are imported into interfaces/__init__.py, so that you can write from Products.borg.interfaces import ....
- membership/
- Contains various adapters for plugging into membrane which enable b-orgs user-and-group functionality.
- pas/
- Contains a custom PAS plug-in which is used to manage the local roles for Project members
- permissions.py
- Contains custom add-content permissions, so that the ability to add Department, Employee and Project content objects can be controlled by different permissions.
- profiles/
- Contains the GenericSetup extension profile that sets up b-org. This is registered in the borg/__init__.py.
- setuphandlers.py
- Defines a custom GenericSetup "import step" which configures aspects of b-org that cannot be expressed in the existing GenericSetup XML formats.
- skins/
- Contains the borg skin layer, which is registered in borg/__init__.py. This contains only the b-org icons. These could potentially have been defined in a browser package using Zope 3 resources, but are included in a traditional skin layer to make them easier to customise using conventional methods. See the section on Zope 3 views for more details.
- tests/
- Contains unit and integration tests.
- zmi/
- Defines a ZMI page for adding the PAS plug-in, for completeness' sake.
You will notice that there are many directories, and many of these directories contain the same set of files - employee.py, department.py and project.py. This is a side-effect of the finer-grained components and increased separation of concerns that stem from Zope 3 design concepts. For products that act less as framework, the degree of separation may be lower, and thus the product may appear smaller. However, as you browse b-org's source code, it should become obvious why things are placed where they are, and how code is grouped together by logical functionality rather than a tight coupling to Archetypes content types.