===================== Application framework ===================== Launchpad is built around Zope components. Zope has meant substantially different things over the years (`Wikipedia's Zope article `_ has a good overview, and `The World of Zope `_ is also a useful introduction to some terminology), so this document tries to be a little more specific. In modern terms, Launchpad uses the Zope Toolkit, but not the full Zope application server. Component architecture ---------------------- Launchpad uses the Zope Component Architecture (`zope.interface `_ and `zope.component `_) extensively and pervasively. ``zope.interface`` defines most of Launchpad's internal interfaces, and is also built upon by `lazr.restful `_ to define its `external web service API `_. ``zope.component`` provides facilities for registering and looking up components, making it easier to decouple implementations from interfaces and reducing the need for circular imports. The `zope.schema `_ package from the Zope Toolkit allows specifying more detailed types for attributes of interfaces, and `zope.security `_ allows enforcing interfaces using security policies. The latter is particularly important to Launchpad; it is the foundation of our ability to operate a complex multi-tenanted service in which users' privileges often overlap in ways that cannot be accurately enforced purely at API boundaries, and must instead be enforced object-by-object. Most objects passed across interface boundaries within Launchpad are wrapped in Zope security proxies so that the security policy in ``lp.services.webapp.authorization`` is consulted on all attribute accesses. URL traversal and publishing ---------------------------- Launchpad uses `zope.traversing `_ to "traverse" URLs (i.e. work segment-by-segment along them until reaching a model object with an associated view), and `zope.publisher `_ to define the details of how objects are "published" (i.e. the process of turning an HTTP request into an appropriate response, including various hooks that are run before and after calling the object itself). Many of the details here are handled by custom code in ``lp.services.webapp``, especially ``lp.services.webapp.publication`` which provides many application-specific hooks, and ``lp.services.webapp.publishing`` which defines much of Launchpad's traversal framework. The URL structure is defined in various ``configure.zcml`` files: ``lp:url`` tags are used to build up the canonical URL for an object, and ``lp:navigation`` tags register classes called as part of traversal to resolve the next step from each intermediate object in the URL (starting at ``lp.app.browser.launchpad.LaunchpadRootNavigation``). Page templating --------------- Launchpad uses `Page Templates `_ as its HTML templating mechanism. While systems like `Jinja `_ are more popular elsewhere, the Page Templates language has the benefit that source files are themselves valid XML rather than being a combination of two syntaxes, and it is not generally possible to write well-formed input that produces ill-formed output. Page Templates were originally invented by Zope, and we still happen to use `Zope's original implementation of them `_, although Zope nowadays uses `Chameleon `_ instead. Views and forms --------------- Launchpad's view layer (used for the web UI) is custom code, starting at ``lp.services.webapp.publisher.LaunchpadView``. However, many views are built around "forms", defined by building up a data schema using ``zope.interface`` and ``zope.schema`` and then using `zope.formlib `_ to generate HTML forms and to parse data from HTTP ``POST`` requests. ``zope.formlib`` also provides "widgets" whose job it is to define the precise rendering and parsing of particular form elements, and Launchpad defines a number of custom widgets for cases where ``zope.formlib``'s widgets are insufficient. Events ------ It's often useful for parts of Launchpad to be able to subscribe to events generated by other parts of Launchpad. For example, a number of subscribers watch for objects such as comments being created in order to be able to assign "karma" to their creators. This is coordinated using `zope.event `_, as well as ``subscriber`` tags in various ``configure.zcml`` files. `lazr.lifecycle `_ enhances this with common events for object creation, modification, and deletion. WSGI server ----------- Launchpad's application server runs within `Gunicorn `_, wrapped using `Talisker `_ to add several useful operational facilities.