Skip to content

WebCore Conventions

Alice Zoë Bevan–McGregor edited this page Oct 22, 2016 · 3 revisions

Table of Contents

  1. General Python Guidelines
  2. Extensions
    1. Philosophical Guidelines
    2. Naming Conventions
    3. Extension Metadata
    4. Callback Best Practices

General Python Guidelines

  1. Use, but optimize away debug level logging.
    Debug-level logging statements are encouraged, however, these should be wrapped in if __debug__: conditions to ensure that the logging statement itself is removed from production code. (When Python is run with the -O flag or in an environment with PYTHONOPTIMIZE set.)

  2. Provide optimizations.
    The if __debug__: condition should additionally be utilized to mark costly (but optional) validation tests and other diagnostic statements, especially if there are loops involved. A few of the extension callbacks are executed within loops, and will be noted below.

  3. Provide logging metadata.
    Logging statements are encouraged to contain extras dictionary keyword argument. Be careful to avoid accidentally overwriting a standard attribute of logging.Log objects. Individual guidelines below may mention specific keys that should be included at different points of execution. The values should be encodable as JSON, or, optionally (with an appropriate logger configured), MongoDB Extended JSON, or some other format as supported. For maximum portability, stick to basic Python built-in types.

Extensions

Philosophical Guidelines

  1. Does it need to be a WebCore Extension?
    There are many hooks provided through other mechanisms, such as object dispatch for request endpoint discovery, the serialization extension to adapt outgoing data transformers like JSON encoders, etc.

  2. Are you adapting one of a class of tools?
    For example, instead of having a SQLiteExtension and a MongoDBExtension, there is the database extension providing its own extension interface. If your own efforts involve integrating one specific tool in a class of tools, please consider instead creating an extension exposing an interface that can be provided by several, even if you only initially write an interface for one.

Naming Conventions

  1. All extension classes should end with Extension.

  2. Be expressive, but keep it short. For example, LocaleExtension is preferable to LocalizationExtension. One word is usually sufficient–synonyms are your friend.

  3. Short abbreviations–two or fewer characters–should be avoided. For example, DatabaseExtension is preferable to DBExtension.

Extension Metadata

Several metadata attributes are provided to allow execution order to be controlled through dependency graphing, as well as to advertise features the extension implements to the application, and provide introspective documentation. You can see these documented in the extension example doc-strings.

  1. Mean what you say.
    Do not define a metadata attribute if you wish to omit it, i.e. do not assign None, empty lists or tuples, etc.

  2. Sets are awesome.
    Most list-like attributes (such as uses, or provides) should be defined as sets, typically as set literals.

  3. Metadata is configurable.
    The only time it is permitted to modify an extension's metadata is within its constructor. For example, it is perfectly permissible to customize your extension's uses or needs (even provides) in response to specific configuration.

Callback Best Practices

  1. __call__ – Wrapping WSGI middleware.

    1. Avoid WSGI middleware where possible.
      There are many fine-grained hooks provided that replicate the "do work before", "capture result", and "do work after" pattern offered by middleware. There are two occasions to utilize middleware: to adapt an awesome existing package that just must be middleware, or when you must capture bubbled exceptions including their stack trace. There are better ways to "just detect an error" when using extension callbacks.