borgcube.web package

borgcube.web.core.hookspec module

borgcube.web.core.metrics module

class borgcube.web.core.metrics.WebData[source]

Bases: borgcube.core.models.Evolvable

class borgcube.web.core.metrics.Metric[source]

Bases: object

name = None
label = None
formatted_value()[source]

borgcube.web.core.middleware module

borgcube.web.core.middleware.transaction_middleware(get_response)[source]

Calls transaction.abort() before and after obtaining a response.

class borgcube.web.core.middleware.ZODBErrorMiddleware(get_response)[source]

Bases: object

process_exception(request, exception)[source]

borgcube.web.core.templatetags.borgcube module

borgcube.web.core.templatetags.borgcube.field_name(obj, field)[source]
borgcube.web.core.templatetags.borgcube.get_url(model_instance)[source]

Return URL for model_instance.

This has some core classes coded in and otherwise works through hookspec.borgcube_web_get_url.

borgcube.web.core.templatetags.borgcube.compression_name(compression_id)[source]
borgcube.web.core.templatetags.borgcube.summarize_archive(archive)[source]
borgcube.web.core.templatetags.borgcube.job_outcome(job)[source]
borgcube.web.core.templatetags.borgcube.format_timedelta(td)[source]

Format a datetime.timedelta instance to a human-friendly format.

borgcube.web.core.templatetags.borgcube.get(obj, attr)[source]

Look value of an object up through a variable (instead of a fixed name as in obj.a)

borgcube.web.core.templatetags.borgcube.json(obj)[source]

Return safe JSON serialization (as in: use in <script>-tags) of obj.

borgcube.web.core.templatetags.borgcube.describe_recurrence(rec: recurrence.base.Recurrence)[source]

Describe a recurrence.Recurrence object in human terms.

Due to the possible complexities of recurrences this only works for simple recurrences, complex ones will return a non-descript description.

borgcube.web.core.publishers package

class borgcube.web.core.publishers.PublisherMenu[source]

Bases: object

Defines the interface for exposing menu entries directly by publishers.

Note that there is no way to specify an URL; the menu entry always points to the default view of the instance.

menu_descend = True

Whether this publisher should be included. When absent, False.

menu_text = ''

The text of the item. Normally a lazy translation object (eg. ugettext_lazy).

class borgcube.web.core.publishers.Publisher(companion)[source]

Bases: object

Core class of the object publishing system.

Since the core of BorgCube is not tied to the web interface, objects do not directly implement object publishing protocols like usually done in eg. Zope or Pyramid.

Instead a second hierarchy of object exists, the publishers, that only contain web- related functionality. Every publisher instance is bound to a companion, the core object that it renders. The companion attribute defines how the instance attribute shall be named.

A publisher can have multiple views, but by default only has it’s default view.

A publisher can either have a “relatively static” number of children, by implementing children and returning a mapping of segments to child publisher instances or factories, or a “rather dynamic” number of children, by implementing __getitem__.

The first case is usually used if the children are static, eg. the RootPublisher has fixed children (ClientsPublisher, SchedulesPublisher, …), while the second case is best applied if the children are sourced from the database, since only one publisher, for the requested child, needs to be constructed.

An example best illustrates this:

class RootPublisher(Publisher):
    companion = 'dr'

    def children(self):
        return {
            'clients': ClientsPublisher(self.dr.clients),
            'schedules': SchedulesPublisher(self.dr.schedules),
            # ...
        }

On the other hand, here is how ClientsPublisher handles it’s children:

class ClientsPublisher(Publisher):
    companion = 'clients'

    def __getitem__(self, hostname):
        client = self.clients[hostname]
        return ClientPublisher(client)

Note that, since ClientsPublisher was provided by RootPublisher the companion of ClientsPublisher is data_root().clients – so __getitem__ here only loads the required client from the database.

Also note how no extra error handling is required: clients is already a mapping itself, so if no client with hostname exists it will raise KeyError.

This might seem a bit confusing and convoluted, however, it allows implicit URL generation and avoids having to define many URL patterns by hand. It also decouples components very efficiently, since URLs are both resolved and generated by the hierarchy, so plugins can just “hook into” the system and don’t need to bother defining URLs that don’t conflict with core URLs.

Additional views

Additional views can be added by adding something_view methods and adding it to the views property:

class MyPublisher(Publisher):
    views = ('edit', )

    def view(self, request):
        ...

    def edit_view(self, request):
        ...

In the URL hierarchy these are addressed through the view query parameter, eg. /clients/foo/?view=edit. The query parameter converts dashes to underscores, eg. ?view=latest_job and ?view=latest-job are identical.

companion = 'companion'

The name of the companion attribute

views = ()

Exposed views (the default view is always exposed), base names, no trailing _view.

name

Name of the publisher for hookspec purposes. Defaults to class.companion.

get_companion()[source]

Returns the companion object.

get(segment)[source]

Return child from segment or raise KeyError.

First tries subscription (__getitem__), then looks up in children. Ensures that child.segment and child.parent are set correctly.

children()[source]

Return a mapping of child names to child publishers.

Make sure to call into children_hook, like so:

def children(self):
    return self.children_hook({
        ...
    })
children_hook(children)[source]

Post-process result of children.

This adds plugin children via borgcube_web_children and ensures that all children know their parent and segment.

redirect_to(view=None, permanent=False)[source]

Return a HTTP redirect response to this publisher and view.

reverse(view=None)[source]

Return the path to this publisher and view.

resolve(path_segments, view=None)[source]

Resolve reversed path_segments to a view or raise Http404.

Note: path_segments is destroyed in the process.

render(request, template=None, context={})[source]

Return a TemplateResponse for request, template and context.

The actual context is constructed by obtaining the return of context and updating that with the passed context.

If template is None, then the base_template is used.

base_template(request)[source]

Return base template name. Default: base.html

context(request)[source]

Return the “base context” for request.

Make sure to always call the base implementation, which provides the following keys:

  • publisher (self)
  • cls.companion (correctly named companion obtained from self.get_companion())
  • base_template
  • secondary_menu (None, overridden in subclasses)
view(request)[source]

The default view of this object.

This implementation raises Http404.

class borgcube.web.core.publishers.ExtensiblePublisher(companion)[source]

Bases: borgcube.web.core.publishers.Publisher, borgcube.web.core.publishers.PublisherMenu

An extensible publisher implements publishers which are extended by ExtendingPublisher s.

This allows to decouple the publishing of child objects from the publisher of an object, by allowing other parts and plugins to hook into the display and present their content wrapped up in your visual framework.

An extensible publisher always has a menu entry that is used for secondary navigation between the ExtensiblePublisher and a number of ExtendingPublishers, which appear at the same level (although the are technically subordinate).

The extending publishers are attached in the regular way through children_hook.

Templates and contexts

An extensible publisher should designate a template with default_template whose title and ctitle blocks are renderable with the standard context. ExtendingPublishers will use this to render their content into the ccontent block (indirectly).

context(request)[source]

Return the “base context” for request.

Make sure to always call the base implementation, which provides the following keys:

  • publisher (self)
  • cls.companion (correctly named companion obtained from self.get_companion())
  • base_template
  • secondary_menu (None, overridden in subclasses)
base_template(request)[source]

Return base template name. Default: base.html

default_template(request)[source]

Return default template name (see class docstring). Default: base_template

class borgcube.web.core.publishers.ExtendingPublisher(companion)[source]

Bases: borgcube.web.core.publishers.Publisher, borgcube.web.core.publishers.PublisherMenu

render(request, template=None, context=None)[source]

Return a TemplateResponse for request, template and context.

The actual context is constructed by obtaining the return of context and updating that with the passed context.

If template is None, then the base_template is used.