Creating a Library

In Moya, a library, is a bundle of files for handling a particular component of your website. All functionality for handing URLs is contained within a library, whether unique to your project or something you would like to distribute. This chapter covers how to create a new library.

Starting a Library

You can use the moya start library command to create a library within your project. This will create a fully functioning library which you can use as a starting point.

Here's how you might create a new library called "Sushi Finder":

$ moya start library --title "Sushi Finder" -a

Alternatively, you can create the directory and files manually. This chapter will describe the structure and contents of a library.

Library Contents

By convention a library directory should be named after the long name of the library, so the directory name won't conflict with a library from another organization. An example long name would be acme.shop. As long as no other organization uses the name acme, there is no risk of creating a library name used by someone else.

Immediately inside the project directory should be the following files:

__init__.py
Required if you plan to distribute your library as a Python module.
lib.ini
Required for all libraries, this INI file contains information about the library and the files / directories it contains.

A library will contain a number of directories that Moya will read from, depending on the features enabled in lib.ini. The next section describes the contents of lib.ini.

Library Settings

Like the main project, a library is initialized form an INI file which defines a few settings and tells Moya what files to load. This settings file should be called lib.ini. This INI file may define the following sections:

[author] Section

The author section contains information about the library and author, which is used when distributing the library. Here's an example of an author section:

[author]
name = Mr T Author
email = author@example.org
organization = Example Inc
url = http://example.org

name = <author's name>

The name of the author or – if you prefer – the organization.

email = <email address>

A contact email the library author. You can leave this blank if you wish.

organization = <organization name>

The author's organization, i.e. the company you work for or some other group you belong to. You can leave this blank if you wish.

url = <homepage URL>

This should be a URL with information regarding the author; which could be an homepage, blog, company website etc. You may leave this blank if you wish.

[lib] Section

This section contains information Moya needs to read the library's code. All libraries must contain a [lib] section. The following is en example of a lib section:

[lib]
location = ./logic
title = Sushi Finder
url = http://www.example.org
namespace = http://moyaproject.com/sushifinder
longname = moyaproject.sushifinder
version = 0.1.0-dev

location = <path>

This should be a relative path to a directory in the library which contains Moya code. This should be ./logic according to convention, but could be another directory. When Moya imports the library it will read all the xml files in this directory, and sub-directories.

Note that the names of the xml files are irrelevant as far as Moya is concerned, but should probably reflect what they contain. The moya start library command will create a few example files, but the names are only a suggestion.

title = <project title>

This is the human readable title of the project. For example, "Sushi Finder".

url = <library homepage>

This setting should be the URL for the library, i.e. documentation. Leave blank if the library has no URL.

namespace = <xml namespace>

This should be an XML namespace which will be used for any tags defined in the library. If your library doesn't define any tags, you may leave this blank.

name = <library's long name>

This should be the library long name (a name used to identify the library in code). A library long name consists of lower-case characters with no spaces, separated by periods (.). The first token should identify the organization, other tokens should identify the library. Library long names should be globally unique, so try and pick a long name that isn't likely to clash with a library from another author.

version = <library version>

Libraries should be tagged with a version number in Semantic Versioning format. Essentially this consists of MAJOR.MINOR.PATCH. Start at 0.1.0 for a first pre-release version, then increment PATCH when you make backwards-compatible fixes, increment MINOR when you add new functionality, and increment MAJOR when there is a new version.

A MAJOR value of 0 is for initial development. When you are ready to distribute your library, reset the version to 1.0.0. You can also add -dev to indicate a version in development. It is a good idea to bump your version number immediately after publishing the library and add -dev. Drop the -dev suffix when you publish the next version.

[py] Section

Moya can be extended with Python code that defines new tags and adds functionality.

location = <path>

This setting should be a relative path to a directory containing Python (.py) files. By convention, this should be ./py.

[settings] Section

This section defines the initial settings for the library. These can be overridden in the project settings once installed. There are no particular requirements for the setting, you may define as many as you need to configure an application with the library. As a guideline though, it is recommended to chose sensible defaults so that a library may be installed with little or no configuration.

[templates] Section

This section initializes templates used in the library. This section isn't required if the library doesn't have any templates.

location = <path to templates>

This setting should be a relative path to template files. By convention, this setting should be ./templates.

priority = <integer priority>

This setting defines the template directory priority which is used to resolve conflicting template paths. Moya will select the template with the highest priority. The priority defaults to 0 if this setting isn't present.

The template priority may be overridden when the library is imported (see <import>).

Generally this setting should be left as the default, as most libraries contain templates for their own use that will not conflict with other libraries. Set it to 10 if the library was designed to replace template in another library.

[media] Section

Moya libraries may bundle media files (images, CSS, Javascript etc.) with the code, which will be served statically. To add media to your library add a named section, called media: and give it a name to be used as an identifier. Most libraries will only have one media directory, and the convention is to name it simply 'media', so the section will be [media:media].

The media section takes one setting, location, which should be a relative path to the directory containing the media. By convention, this will be ./media. For example:

[media:media]
location = ./media

When the library is installed, Moya adds media directories to a virtual filesytem called media, under a sub-directory called <application name>-<media name>.

Let's work through an example to illustrate this. Assume we have a library called moya.sushifinder, with a media section as follows:

[media:media]
location = ./media

And the library contains the following files (some directories omitted for brevity):

moyaproject.sushifinder/
|-- lib.ini
|-- logic
|   |-- views.xml
|   `-- widgets.xml
`-- media
    |-- css
    |   `-- sushi.css
    `-- images
        `-- logo.png

When we install this library with the application name of sushi, Moya adds a directory to the media filesystem called sushi-media. If we were to list the contents of the media filesystem, with moya fs media --tree, we would see something like the following (along with media from other libraries):

|-- sushi-media
|   |-- css
|   |   `-- sushi.css
|   `-- images
|       `-- logo.png

You can serve this media filesystem with the moya.static library. To use it, add the following to your <server>:

<import py="moya.libs.static" />

Then install it with something like the following:

<install name="media" lib="moya.static" mount="/static/" />

Finally, add the following section to your project settings:

[settings:media]
fs = media
dirlist = yes

Your project should now be serving media from all applications. If you visit the /static/ url, you should see a directory listing of the media files you are serving.

See Overriding Media for ways of customizing media for a project.

[data] Section

This section defines additional data files (json, text etc) that may be read from your project code. Moya combines any directories defined in this section, in to a single filesystem called "data". You can see what data files are exposed by Moya with the following command line:

$ moya fs data --tree

You can read a data file with the <read-data> tag, which supports a variety of standard formats.

Data follows the same convention as templates; the data files should be within a directory named after the library. This allows a library to over-ride the data files from another library, and is another way of customizing behavior.

location = <path to data>

This setting should be a relative path to a directory containing data files by convention this should be ./data

priority = <integer priority>

The priority is used to resolve which path should be used when there are conflicting paths within data directories. The library with the highest priority is used. This setting may be blank, to use a default priority of 0.

[documentation] Section

This section defines documentation for the library. Moya can extract tag documentation automatically for your library, and you can add supplementary documentation in a dialog of bbcode.

location = <path to documentation>

This value should be a relative path to the documentation. By convention, documentation is stored in ./docs.

[tests] Section

This section defines tests for your library. Tests consists of Moya code that checks the code in your library is working as expected. Well written tests ensure that you can catch bugs early, before they make it in to production.

location = <path to tests>

This setting should be a relative path to the directory containing tests, by convention this is ./tests.

projects = <path to projects directory>

This setting should be a relative path to a directory containing projects. Your tests can load these projects on the fly and test that they are generating the expected responses.

import = <list of imports>

This setting should be a list of libraries to import when testing (i.e. dependencies of the library). An entry in this list can be a path, or a Python module if a line is prefixes with py:.

[translations] Section

Moya supports internationalization of text in to any language. If you intend to supply text translations for your library, then add this section.

location = <path to translations>

This should be a relative path to the directory containing message catalogs. By convention, this should be ./translations.

default_language = <language code>

This setting defines the language used in the library. Moya needs this information when extracting text. Typically this will be 'en' for English, but could be any language code.

languages = <comma separated list of language codes>

This should be a comma separated list of language codes, for each of the languages the library contains translations for. This language doesn't have to include the default language, which is implied. For example, a value of fr, es would indicate the library supports French and Spanish in addition to the default language.

Overriding Media

Moya's media system allows you to either replace individual files in the media directories, or completely swap out a media directory for another – depending on the level of customization you would like.

To override individual files, first add the following section to your project settings:

[media]
location = ./static

This combines the /static directory in your project with the files in media, so that any files in this directory take priority over the files stored in library directries. For example, lets say we want to completely replace the image logo.png in the Sushi Finder library with our own logo. To do this, we can add the custom logo.png to the project's static directory. So ./static will look something like this:

`-- static
    `-- sushi-media
        `-- images
            `-- logo.png

Now when the browser requests /static/sushi-sushimedia/images/logo.png it will receive the version stored in the project directory, rather than the version in the library.

The second way to customize media is to replace a media directory entirely. This can be done by creating a filesystem called <app name>_<media name>. In the Sushi Finder application, it would be called sushi_media. The contents of this filesystem will be used in preference to the media contained in the library.

The following section, when added to project settings, creates a media directory that completely replaces the media from then Sushi Finder library:

[fs:sushi_media]
location = ./replace_sushimedia

Now, when you request any file under /static/sushi-sushimedia/ it will look for it in the ./replace_sushimedia directory in the project.

Note that if you use this method you will probably have to replace or copy all the media files the library uses. As a starting point you can copy a library's media with the following:

$ moya fs sushi_media --copy ./replace_sushimedia

This copies all the media files from the sushi library to the replace_sushimedia directory. You can now modify any files you wish to customize.