API

Package abilian

Module abilian.app

Base Flask application class, used by tests or to be extended in real applications.

class Application(name=None, config=None, *args, **kwargs)[source]

Base application class. Extend it in your own app.

add_static_url(url_path, directory, endpoint=None)[source]

Adds a new url rule for static files.

Parameters:
  • endpoint – flask endpoint name for this url rule.
  • url – subpath from application static url path. No heading or trailing slash.
  • directory – directory to serve content from.

Example:

app.add_static_url('myplugin',
                   '/path/to/myplugin/resources',
                   endpoint='myplugin_static')

With default setup it will serve content from directory /path/to/myplugin/resources from url http://.../static/myplugin

check_instance_folder(create=False)[source]

Verifies instance folder exists, is a directory, and has necessary permissions.

:param:create: if True, creates directory hierarchy

Raises:OSError with relevant errno
create_db()[source]
create_jinja_environment()[source]
handle_exception(e)[source]
handle_http_error(code, error)[source]

Helper that renders error{code}.html.

Convenient way to use it:

from functools import partial
handler = partial(app.handle_http_error, code)
app.errorhandler(code)(handler)
handle_user_exception(e)[source]
init_breadcrumbs()[source]

Inserts the first element in breadcrumbs.

This happens during request_started event, which is triggered before any url_value_preprocessor and before_request handlers.

init_debug_toolbar()[source]
init_extensions()[source]

Initializes flask extensions, helpers and services.

init_sentry()[source]

Installs Sentry handler if config defines ‘SENTRY_DSN’.

install_default_handler(http_error_code)[source]

Installs a default error handler for http_error_code.

The default error handler renders a template named error404.html for http_error_code 404.

log_exception(exc_info)[source]

Log exception only if sentry is not installed (this avoids getting error twice in sentry).

make_config(instance_relative=False)[source]
maybe_register_setup_wizard()[source]
register_asset(type_, *assets)[source]

Registers webassets bundle to be served on all pages.

Parameters:
  • type“css”, “js-top” or “js”“.
  • *asset – a path to file, a webassets.Bundle instance or a callable that returns a webassets.Bundle instance.
Raises KeyError:
 

if type_ is not supported.

register_jinja_loaders(*loaders)[source]

Registers one or many jinja2.Loader instances for templates lookup.

During application initialization plugins can register a loader so that their templates are available to jinja2 renderer.

Order of registration matters: last registered is first looked up (after standard Flask lookup in app template folder). This allows a plugin to override templates provided by others, or by base application. The application can override any template from any plugins from its template folder (See Flask.Application.template_folder).

Raise:ValueError if a template has already been rendered
register_plugins()[source]

Loads plugins listed in config variable ‘PLUGINS’.

setup_logging()[source]
APP_PLUGINS = ('abilian.web.search',)

Custom apps may want to always load some plugins: list them here.

CONFIG_ENVVAR = 'ABILIAN_CONFIG'

Environment variable used to locate a config file to load last (after instance config file). Use this if you want to override some settings on a configured instance.

configured

True if application as a config file and can be considered configured for site.

db[source]
default_config = ImmutableDict({'JSON_AS_ASCII': True, 'USE_X_SENDFILE': False, 'SESSION_COOKIE_PATH': None, 'SEND_FILE_MAX_AGE_DEFAULT': 43200, 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_NAME': 'session', 'LOGGER_NAME': None, 'DEBUG': False, 'ADMIN_PANELS': ('abilian.web.admin.panels.dashboard.DashboardPanel', 'abilian.web.admin.panels.audit.AuditPanel', 'abilian.web.admin.panels.login_sessions.LoginSessionsPanel', 'abilian.web.admin.panels.settings.SettingsPanel', 'abilian.web.admin.panels.sysinfo.SysinfoPanel'), 'SECRET_KEY': None, 'LOGO_URL': Endpoint('abilian_static', *(), **{'filename': 'img/logo-abilian-32x32.png'}), 'CSRF_ENABLED': True, 'SENTRY_USER_ATTRS': ('email', 'first_name', 'last_name'), 'MAX_CONTENT_LENGTH': None, 'APPLICATION_ROOT': None, 'SERVER_NAME': None, 'PREFERRED_URL_SCHEME': 'http', 'JSONIFY_PRETTYPRINT_REGULAR': True, 'TESTING': False, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'PROPAGATE_EXCEPTIONS': None, 'TRAP_BAD_REQUEST_ERRORS': False, 'JSON_SORT_KEYS': True, 'TEMPLATE_DEBUG': False, 'SESSION_COOKIE_HTTPONLY': True, 'PLUGINS': (), 'BABEL_ACCEPT_LANGUAGES': ('en', 'fr'), 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SESSION_COOKIE_SECURE': False, 'TRAP_HTTP_EXCEPTIONS': False})
default_view = None

instance of web.views.registry.Registry.

jinja_loader[source]

Searches templates in custom app templates dir (default flask behaviour), fallback on abilian templates.

jinja_options[source]
class ServiceManager[source]

Mixin that provides lifecycle (register/start/stop) support for services.

start_services()[source]
stop_services()[source]
create_app(config=None)[source]

Module abilian.i18n

I18n.

To mark strings for transalation:

from abilian.i18n import _
_(u'message to translate')

Use _ for gettext, _l for lazy_gettext, _n for ngettext.

Babel extension support multiple translation paths. This allows to add more catalogs to search for translations, in LIFO order. This feature can be used to override some translations in a custom application, be providing a catalog with messages to override:

current_app.extensions['babel'].add_translations('abilian.core')

See add_translations.

To extract messages to build the message catalog template (.pot), use the following “-k” parameters:

$ pybabel extract -F babel.cfg -k "_n:1,2" -k "_l" -o "msg.pot" "src"
_ = <function gettext at 0x7fe3182cd398>

Translates a string with the current locale and passes in the given keyword arguments as mapping to a string formatting string.

gettext(u'Hello World!')
gettext(u'Hello %(name)s!', name='World')
_l = <function lazy_gettext at 0x7fe3182cd578>

Like gettext() but the string returned is lazy which means it will be translated when it is used as an actual string.

Example:

hello = lazy_gettext(u'Hello World')

@app.route('/')
def index():
    return unicode(hello)
_n = <function ngettext at 0x7fe3182cd410>

Translates a string with the current locale and passes in the given keyword arguments as mapping to a string formatting string. The num parameter is used to dispatch between singular and various plural forms of the message. It is available in the format string as %(num)d or %(num)s. The source language should be English or a similar language which only has one plural form.

ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples))
class Babel(*args, **kwargs)[source]

Bases: flask_babel.Babel

Allow to load translations from other modules

add_translations(module_name)[source]

Adds translations from external module. For example:

babel.add_translations('abilian.core')

Will add translations files from abilian.core module.

babel = <abilian.i18n.Babel object at 0x7fe3183c2d10>

importable instance of Babel

gettext(string, **variables)

Translates a string with the current locale and passes in the given keyword arguments as mapping to a string formatting string.

gettext(u'Hello World!')
gettext(u'Hello %(name)s!', name='World')
lazy_gettext(string, **variables)

Like gettext() but the string returned is lazy which means it will be translated when it is used as an actual string.

Example:

hello = lazy_gettext(u'Hello World')

@app.route('/')
def index():
    return unicode(hello)
ngettext(singular, plural, num, **variables)

Translates a string with the current locale and passes in the given keyword arguments as mapping to a string formatting string. The num parameter is used to dispatch between singular and various plural forms of the message. It is available in the format string as %(num)d or %(num)s. The source language should be English or a similar language which only has one plural form.

ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples))
babel = <abilian.i18n.Babel object at 0x7fe3183c2d10>

importable instance of Babel

Package abilian.plugin

Starting work on a plugin system. This will probably be refactored heavily in the future.

Package abilian.core

Module abilian.core.commands

Abilian script commands to be used in a project. See Flask-Script documentation for full documentation.

Here is how a manage.py can include these commands:

from flask.ext.script import Manager
from abilian.commands import setup_abilian_commands

my_manager = Manager(app)
setup_abilian_commands(my_manager)

You can also include abilian commands as sub commands:

from abilian.commands import manager as abilian_manager
my_manager.add_command('abilian', abilian_manager)

Extensions can add their own commands to manager:

from flask.ext.script import Manager
from abilian.commands import manager

@manager.command
def hello():
    print u"hello"

# or install subcommands
sub_manager = Manager(usage='Little extension')
abilian_manager.add_command('special_commands', sub_manager)
setup_abilian_commands(manager)[source]

Register abilian commands on manager.

Parameters:managerflask.ext.script.Manager instance to add commands onto

Usage exemple:

from flask.ext.script import Manager
from abilian.commands import setup_abilian_commands

my_manager = Manager(app)
setup_abilian_commands(my_manager)

Module abilian.core.entities

Base class for entities, objects that are managed by the Abilian framwework (unlike SQLAlchemy models which are considered lower-level).

exception ValidationError[source]
class Entity(*args, **kwargs)[source]

Base class for Abilian entities.

From Sqlalchemy POV Entities use Joined-Table inheritance, thus entities subclasses cannot use inheritance themselves (as of 2013 Sqlalchemy does not support multi-level inheritance)

The name is a string that is shown to the user; it could be a title for document, a folder name, etc.

The slug attribute may be used in URLs to reference the entity, but uniqueness is not enforced, even within same entity type. For example if an entity class represent folders, one could want uniqueness only within same parent folder.

If slug is empty at first creation, its is derived from the name. When name changes the slug is not updated. If name is also empty, the slug will be the friendly entity_type with concatenated with entity’s id.

display_value(field_name, value=<object object at 0x7fe319d1d9b0>)

Return display value for fields having ‘choices’ mapping (stored value -> human readable value). For other fields it will simply return field value.

display_value should be used instead of directly getting field value.

If value is provided it is “tranlated” to a human-readable value. This is useful for obtaining a human readable label from a raw value

SLUG_SEPARATOR = u'-'
auto_slug[source]

This property is used to auto-generate a slug from the name attribute. It can be customized by subclasses.

created_at
creator
creator_id
deleted_at
entity_class[source]
entity_type = None
id
name
object_type[source]
owner
owner_id
slug
updated_at
all_entity_classes[source]

Returns the list of all concrete persistent classes that are subclasses of Entity.

Module abilian.core.extensions

Create all standard extensions.

get_extension(name)[source]

Get the named extension from the current app, returning None if not found.

Module abilian.core.signals

All signals used by Abilian Core.

Signals are the main tools used for decoupling applications components by sending notifications. In short, signals allow certain senders to notify subscribers that something happened.

Cf. http://flask.pocoo.org/docs/signals/ for detailed documentation.

The main signal is currently activity.

activity = <blinker.base.NamedSignal object at 0x7fe317d057d0; 'activity'>

This signal is used by the activity streams service and its clients.

components_registered = <blinker.base.NamedSignal object at 0x7fe317d05790; 'app:components:registered'>

Triggered at application initialization when all extensions and plugins have been loaded

entity_created = <blinker.base.NamedSignal object at 0x7fe317d05810; 'entity:created'>

Currently not used and subject to change.

entity_deleted = <blinker.base.NamedSignal object at 0x7fe317d05890; 'entity:deleted'>

Currently not used and subject to change.

entity_updated = <blinker.base.NamedSignal object at 0x7fe317d05850; 'entity:updated'>

Currently not used and subject to change.

Module abilian.core.sqlalchemy

Data types for sqlalchemy

class AbilianBaseSAExtension(app=None, use_native_unicode=True, session_options=None)[source]

Base subclass of flask.ext.sqlalchemy.SQLAlchemy. Add our custom driver hacks.

apply_driver_hacks(app, info, options)[source]
class JSON(*args, **kwargs)[source]

Stores any structure serializable with json.

Usage::
JSON() Takes same parameters as sqlalchemy.types.Text
impl

alias of Text

process_bind_param(value, dialect)[source]
process_result_value(value, dialect)[source]
class JSONUniqueListType(*args, **kwargs)[source]

Store a list in JSON format, with items made unique and sorted.

process_bind_param(value, dialect)[source]
python_type[source]
class MutationDict[source]

Provides a dictionary type with mutability support.

clear()[source]
classmethod coerce(key, value)[source]

Convert plain dictionaries to MutationDict.

pop(key, *args)[source]
popitem()[source]
setdefault(key, failobj=None)[source]
update(other)[source]
class MutationList[source]

Provide a list type with mutability support.

append(item)[source]
classmethod coerce(key, value)[source]

Convert list to MutationList.

extend(other)[source]
insert(idx, value)[source]
pop(i=-1)[source]
remove(item)[source]
reverse()[source]
sort(*args, **kwargs)[source]
class SQLAlchemy(app=None, use_native_unicode=True, session_options=None)[source]
create_scoped_session(options=None)[source]

Helper factory method that creates a scoped session.

class SignallingSession(db, autocommit=False, autoflush=True, **options)[source]
class UUID(*args, **kwargs)[source]

Platform-independent UUID type.

Uses Postgresql’s UUID type, otherwise uses CHAR(32), storing as stringified hex values.

From SQLAlchemy documentation.

impl

alias of CHAR

load_dialect_impl(dialect)[source]
process_bind_param(value, dialect)[source]
process_result_value(value, dialect)[source]
JSONDict(*args, **kwargs)[source]

Stores a dict as JSON on database, with mutability support.

JSONList(*args, **kwargs)[source]

Stores a list as JSON on database, with mutability support.

If kwargs has a param unique_sorted (which evaluated to True), list values are made unique and sorted.

filter_cols(model, *filtered_columns)[source]

Return columnsnames for a model except named ones. Useful for defer() for example to retain only columns of interest

Module abilian.core.models

class IdMixin[source]
id = Column(None, Integer(), table=None, primary_key=True, nullable=False)
class Indexable[source]

Mixin with sensible defaults for indexable objects.

object_key[source]
object_type[source]
class Info(**kw)[source]
copy()[source]
class Model(**kwargs)

Base Model class.

metadata = MetaData(bind=None)
query = None
class TimestampedMixin[source]
created_at = Column(None, DateTime(), table=None, default=ColumnDefault(<function <lambda> at 0x7fe317a87758>))
deleted_at = Column(None, DateTime(), table=None)
updated_at = Column(None, DateTime(), table=None, onupdate=ColumnDefault(<function <lambda> at 0x7fe317a87848>), default=ColumnDefault(<function <lambda> at 0x7fe317a877d0>))
SYSTEM = {'auditable': False, 'editable': False}

SYSTEM properties are properties defined by the system and not supposed to be changed manually.

Subject classes (i.e. people, groups, etc.).

See ICOM-ics-v1.0 “Subject Branch”.

TODO: I’m not a big fan of the “subject” name. Could be replaced by something else, like “people” or “principal” ?

class User(password=None, **kwargs)[source]
query_class

alias of UserQuery

authenticate(password)[source]
display_value(field_name, value=<object object at 0x7fe319d1d980>)

Return display value for fields having ‘choices’ mapping (stored value -> human readable value). For other fields it will simply return field value.

display_value should be used instead of directly getting field value.

If value is provided it is “tranlated” to a human-readable value. This is useful for obtaining a human readable label from a raw value

follow(followee)[source]
is_admin_of(group)[source]
is_following(other)[source]
is_member_of(group)[source]
join(group)[source]
leave(group)[source]
set_password(password)[source]

Encrypts and sets password.

unfollow(followee)[source]
can_login
created_at
deleted_at
email
entity_type = u'abilian.core.models.subjects.User'
first_name
followers
id
is_online[source]
last_active
last_name
locale
name[source]
password
photo
updated_at
class Group(**kwargs)[source]
display_value(field_name, value=<object object at 0x7fe319d1d9a0>)

Return display value for fields having ‘choices’ mapping (stored value -> human readable value). For other fields it will simply return field value.

display_value should be used instead of directly getting field value.

If value is provided it is “tranlated” to a human-readable value. This is useful for obtaining a human readable label from a raw value

admins
created_at
deleted_at
description
entity_type = u'abilian.core.models.subjects.Group'
id
members
name
photo
public
updated_at
class Principal[source]

A principal is either a User or a Group.

has_role(role)
class OwnedMixin(*args, **kwargs)[source]
creator = <RelationshipProperty at 0x7fe315abde90; no key>[source]
creator_id = Column(None, NullType(), ForeignKey('user.id'), table=None)[source]
creator_name[source]
owner = <RelationshipProperty at 0x7fe315ac8090; no key>[source]
owner_id = Column(None, NullType(), ForeignKey('user.id'), table=None)[source]
owner_name[source]
class BaseMixin[source]
to_dict()[source]
to_json()[source]
column_names[source]

Module abilian.core.util

Various tools that don’t belong some place specific.

class BasePresenter(model)[source]

A presenter wraps a model an adds specific (often, web-centric) accessors. subclass to make it useful. Presenters are immutable.

classmethod wrap_collection(models)[source]
class Pagination(page, per_page, total_count)[source]
iter_pages(left_edge=2, left_current=2, right_current=5, right_edge=2)[source]
has_next[source]
has_prev[source]
next[source]
pages[source]
prev[source]
class memoized(func)[source]

Decorator. Caches a function’s return value each time it is called. If called later with the same arguments, the cached value is returned (not reevaluated).

class timer(f)[source]

Decorator that mesures the time it takes to run a function.

fqcn(cls)[source]

Fully Qualified Class Name

friendly_fqcn(cls_name)[source]

Friendly name of fully qualified class name. :param cls_name: a string or a class

get_params(names)[source]

Returns a dictionary with params from request.

TODO: I think we don’t use it anymore and it should be removed before someone gets hurt.

local_dt(dt)[source]

Return an aware datetime in system timezone, from a naive or aware datetime. Naive datetime are assumed to be in UTC TZ.

noproxy(obj)[source]

Unwrap obj from werkzeug.local.LocalProxy if needed. This is required if one want to test isinstance(obj, SomeClass).

slugify(value, separator=u'-')[source]

Slugify an unicode string, to make it URL friendly.

utc_dt(dt)[source]

set UTC timezone on a datetime object. A naive datetime is assumed to be in UTC TZ

Package abilian.services

Module abilian.services.base

exception ServiceNotRegistered[source]
class Service(app=None)[source]

Base class for services.

AppStateClass

State class to use for this Service

alias of ServiceState

static if_running(meth)[source]

Decorator for service methods that must be ran only if service is in running state.

init_app(app)[source]
start(ignore_state=False)[source]

Starts the service.

stop(ignore_state=False)[source]

Stops the service.

app_state[source]

Current service state in current application.

:raise:RuntimeError if working outside application context.

name = None

service name in Application.extensions / Application.services

running[source]
Returns:False if working outside application context, if service is not registered on current application, or if service is halted for current application.
class ServiceState(service, running=False)[source]

Service state stored in Application.extensions

running = False
service = None

reference to Service instance

Module abilian.services.conversion

Conversion service.

Hardcoded to manage only conversion to PDF, to text and to image series.

Includes result caching (on filesystem).

Assumes poppler-utils and LibreOffice are installed.

TODO: rename Converter into ConversionService ?

exception ConversionError[source]
class AbiwordPDFHandler(*args, **kwargs)[source]
convert(blob, **kw)[source]
accepts_mime_types = ['application/msword', 'application/vnd.oasis.opendocument.text', 'text/rtf']
produces_mime_types = ['application/pdf']
class AbiwordTextHandler(*args, **kwargs)[source]
convert(blob, **kw)[source]
accepts_mime_types = ['application/msword']
produces_mime_types = ['text/plain']
class Cache[source]
clear()[source]
get(key)[source]
set(key, value)[source]
CACHE_DIR = None
class CloudoooPdfHandler(*args, **kwargs)[source]

Handles conversion from OOo to PDF.

Highly inefficient since file are serialized in base64 over HTTP.

Deactivated because it’s so hard to set up.

convert(key)[source]
SERVER_URL = 'http://localhost:8011'
accepts_mime_types = ['application/.*']
pivot_format_map = {'pptx': 'odp', 'xlsx': 'ods', 'docx': 'odt', 'doc': 'odt', 'ppt': 'odp', 'xls': 'ods'}
produces_mime_types = ['application/pdf']
class Converter[source]
clear()[source]
static digest(blob)[source]
get_image(digest, blob, mime_type, index, size=500)[source]

Return an image for the given content, only if it already exists in the image cache

get_metadata(digest, content, mime_type)[source]

Gets a dictionary representing the metadata embedded in the given content.

has_image(digest, mime_type, index, size=500)[source]

Tell if there is a preview image

init_app(app)[source]
init_work_dirs(cache_dir, tmp_dir)[source]
register_handler(handler)[source]
to_image(digest, blob, mime_type, index, size=500)[source]

Converts a file to a list of images. Returns image at the given index.

to_pdf(digest, blob, mime_type)[source]
to_text(digest, blob, mime_type)[source]

Converts a file to plain text.

Useful for full-text indexing. Returns an unicode string.

class Handler(*args, **kwargs)[source]
accept(source_mime_type, target_mime_type)[source]

Generic matcher based on patterns.

convert(key, **kw)[source]
init_app(app)[source]
accepts_mime_types = []
produces_mime_types = []
class ImageMagickHandler(*args, **kwargs)[source]
convert(blob, **kw)[source]
accepts_mime_types = ['image/.*']
produces_mime_types = ['application/pdf']
class PdfToPpmHandler(*args, **kwargs)[source]
convert(blob, size=500)[source]

Size is the maximum horizontal size.

accepts_mime_types = ['application/pdf']
produces_mime_types = ['image/jpeg']
class PdfToTextHandler(*args, **kwargs)[source]
convert(blob, **kw)[source]
accepts_mime_types = ['application/pdf']
produces_mime_types = ['text/plain']
class UnoconvPdfHandler(*args, **kwargs)[source]

Handles conversion from office documents (MS-Office, OOo) to PDF.

Uses unoconv.

convert(blob, **kw)[source]

Unoconv converter called.

init_app(app)[source]
accepts_mime_types = ['application/vnd.oasis.*', 'application/msword', 'application/mspowerpoint', 'application/vnd.ms-powerpoint', 'application/vnd.ms-excel', 'application/ms-excel', 'application/vnd.openxmlformats-officedocument.*', 'text/rtf']
produces_mime_types = ['application/pdf']
run_timeout = 60
unoconv = 'unoconv'
unoconv_version[source]
class WvwareTextHandler(*args, **kwargs)[source]
convert(blob, **kw)[source]
accepts_mime_types = ['application/msword']
produces_mime_types = ['text/plain']
make_temp_file(blob, prefix='tmp', suffix='')[source]

Module abilian.services.image

Provides tools (currently: only functions, not a real service) for image processing.

resize(orig, hsize)[source]
crop_and_resize(orig, hsize, vsize=0)[source]

Module abilian.services.indexing

service

Index documents using whoosh

class WhooshIndexService(*args, **kwargs)[source]

Index documents using whoosh

AppStateClass

alias of IndexServiceState

after_commit(session)[source]

Any db updates go through here. We check if any of these models have __searchable__ fields, indicating they need to be indexed. With these we update the whoosh index for the model. If no index exists, it will be created here; this could impose a penalty on the initial commit of a model.

after_flush(session, flush_context)[source]
clear()[source]

Remove all content from indexes, and unregister all classes.

After clear() the service is stopped. It must be started again to create new indexes and register classes.

clear_update_queue(app=None)[source]
get_document(obj, adapter=None)[source]
index(name='default')[source]
index_objects(objects, index='default')[source]

Bulk index a list of objects.

init_app(app)[source]
init_indexes()[source]

Create indexes for schemas.

register_class(cls, app_state=None)[source]

Registers a model class

register_classes()[source]
register_search_filter(func)[source]

Register a function that returns a query used for filtering search results. This query is And’ed with other filters.

If no filtering should be performed the function must return None.

register_value_provider(func)[source]

Register a function that may alter content of indexable document.

It is used in get_document() and called after adapter has built document.

The function must accept (document, obj) as arguments, and return the new document object.

search(q, index='default', fields=None, Models=(), object_types=(), prefix=True, facet_by_type=None, **search_args)[source]

Interface to search indexes.

Parameters:
  • q – unparsed search string.
  • index – name of index to use for search.
  • fields – optionnal mapping of field names -> boost factor?
  • Models – list of Model classes to limit search on.
  • object_types – same as Models, but directly the model string.
  • prefix – enable or disable search by prefix
  • facet_by_type – if set, returns a dict of object_type: results with a max of limit matches for each type.
  • search_args – any valid parameter for whoosh.searching.Search.search(). This includes limit, groupedby and sortedby
search_for_class(query, cls, index='default', **search_args)[source]
searchable_object_types()[source]

List of (object_types, friendly name) present in the index.

start()[source]
default_search_fields[source]

Return default field names and boosts to be used for searching. Can be configured with SEARCH_DEFAULT_BOOSTS

name = 'indexing'
indexable_role(principal)

Returns a string suitable for query against allowed_roles_and_users field.

Parameters:principal – It can be Anonymous, Authenticated, or an instance of User or Group.

Module abilian.services.security

service

Security service, manages roles and permissions.

Currently very simple (simplisitic?).

Roles and permissions are just strings, and are currently hardcoded.

class SecurityServiceState(service, running=False)[source]
needs_db_flush = False

True if security has changed

use_cache = True
Anonymous

marker for role assigned to ‘Anonymous’

Authenticated

marker for role assigned to ‘Authenticated’

Package abilian.web

Module abilian.web.decorators

Useful decorators for web views.

templated(template=None)[source]

The idea of this decorator is that you return a dictionary with the values passed to the template from the view function and the template is automatically rendered.

Module abilian.web.filters

Add a few specific filters to Jinja2.

abbrev(s, max_size)[source]
age(dt, now=None)[source]
autoescape(filter_func)[source]

Decorator to autoescape result from filters.

babel2datepicker(pattern)[source]

Converts date format from babel (http://babel.pocoo.org/docs/dates/#date-fields)) to a format understood by bootstrap-datepicker.

date(value, format='EE, d MMMM y')[source]
date_age(dt, now=None)[source]
filesize(d)[source]
init_filters(env)[source]
labelize(s)[source]
linkify(eval_ctx, *args, **kwargs)[source]
nl2br(eval_ctx, *args, **kwargs)[source]

Replace newlines with <br />.

obj_to_url(obj)[source]

Find url for obj using url_for(), return empty string is not found.

url_for() is also provided in jinja context, the filtering version is forgiving when obj has no default view set.

paragraphs(eval_ctx, *args, **kwargs)[source]

Blank lines delimitates paragraphs.

roughsize(size, above=20, mod=10)[source]

6 -> ‘6’ 15 -> ‘15’ 134 -> ‘130+’

to_timestamp(dt)[source]

Module abilian.web.action

class ActionRegistry[source]

The Action registry.

This is a Flask extension which registers Action sets. Actions are grouped by category and are ordered by registering order.

From your application use the instanciated registry actions.

The registry is available in jinja2 templates as actions.

actions(context=None)[source]

Return a mapping of category => actions list.

Actions are filtered according to Action.available().

if context is None, then current action context is used (context).

for_category(category, context=None)[source]

Returns actions list for this category in current application.

Actions are filtered according to Action.available().

if context is None, then current action context is used (context)

init_app(app)[source]
installed(app=None)[source]

Return True if the registry has been installed in current applications

register(*actions)[source]

Register actions in the current application. All actions must be an instance of Action or one of its subclasses.

If overwrite is True, then it is allowed to overwrite an existing action with same name and category; else ValueError is raised.

context[source]

Return action context (dict type). Applications can modify it to suit their needs.

class Action(category, name, title=None, description=None, icon=None, url=None, endpoint=None, condition=None, status=None)[source]

Action interface.

class Endpoint(name, *args, **kwargs)
get_kwargs()

Hook for subclasses.

The key and values in the returned dictionnary can be safely changed without side effects on self.kwargs (provided you don’t alter mutable values, like calling list.pop()).

Action.available(context)[source]

Determine if this actions is available in this context.

Parameters:context – a dict whose content is left to application needs; if condition is a callable it receives context in parameter.
Action.pre_condition(context)[source]

Called by available() before checking condition.

Subclasses may override it to ease creating actions with repetitive check (for example: actions that apply on a given content type only).

Action.render(**kwargs)[source]
Action.url(context=None)[source]
Action.category = None
Action.condition = None

A boolean (or something that can be converted to boolean), or a callable which accepts a context dict as parameter. See available().

Action.description[source]
Action.enabled[source]
Action.endpoint[source]

A Endpoint instance, a string for a simple endpoint, a tuple (endpoint_name, kwargs) or a callable which accept a : context dict and returns one of those a valid values.

Action.icon[source]
Action.name = None
Action.status[source]
Action.template_string = u'<a href="{{ url }}">{%- if action.icon %}{{ action.icon }} {% endif %}{{ action.title }}</a>'
Action.title[source]
class ModalActionMixin[source]
template_string = u'<a href="{{ url }}" data-toggle="modal">{%- if action.icon %}{{ action.icon}} {% endif %}{{ action.title }}</a>'

Module abilian.web.nav

Navigation elements.

Abilian define theses categories:
section:
Used for navigation elements relevant to site section
user:
User for element that should appear in user menu
class BreadcrumbItem(label=u'', url=u'#', icon=None, description=None)[source]

A breadcrumb element has at least a label or an icon.

render()[source]
description = None

Additional text, can be used as tooltip for example

icon = None

Icon to use.

label = None

Label shown to user. May be an i18n string instance

template_string = u'<a href="{{ item.url }}">{%- if item.icon %}{{ item.icon }}\xa0{%- endif %}{{ item.label }}</a>'
url[source]
class NavGroup(category, name, items=(), *args, **kwargs)[source]

A navigation group renders a list of items.

append(item)[source]
insert(pos, item)[source]
status[source]
template_string = '\n <ul class="nav navbar-nav">\n <li class="dropdown">\n <a class="dropdown-toggle" data-toggle="dropdown">\n {%- if action.icon %}{{ action.icon }}{% endif %}\n {{ action.title }} <b class="caret"></b>\n </a>\n <ul class="dropdown-menu">\n {%- for item in action.items %}\n {%- if item.divider %}<li class="divider"></li>{%- endif %}\n <li class="{{ item.status|safe }}">{{ item.render() }}</li>\n {%- endfor %}\n </ul>\n </li>\n </ul>\n '
class NavItem(category, name, divider=False, *args, **kwargs)[source]

A single navigation item.

divider = False
path[source]
status[source]

Module abilian.web.forms

Extensions to WTForms fields, widgets and validators.

class Form(formdata=<class flask_wtf.form._Auto at 0x7fe317d49db8>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)[source]

Module abilian.web.views

class View

Base class to use for all class based views.

The view instance is accessible in g and is set in actions context.

dispatch_request(*args, **kwargs)
prepare_args(args, kwargs)

If view arguments need to be prepared it can be done here.

A typical use case is to take an identifier, convert it to an object instance and maybe store it on view instance and/or replace identifier by object in arguments.

class Registry(*args, **kwargs)

Registry for default (canonical) views for entities.

There is one registry per application instance.

register(entity, url_func)

Associates a url_func with entity’s type.

:param:entity: an abilian.core.extensions.db.Model class or instance.

:param:url_func: any callable that accepts an entity instance and return an url for it.

url_for(entity=None, object_type=None, object_id=None, **kwargs)

Returns canonical view for given entity instance.

If no view has been registered the registry will try to find an endpoint named with entity’s class lowercased followed by ‘.view’ and that accepts object_id=entity.id to generates an url.

Parameters:
  • entity – a instance of a subclass of abilian.core.extensions.db.Model, whoosh.searching.Hit, dict
  • object_id – if entity is not an instance, this parameter must be set to target id. This is usefull when you know the type and id of an object but don’t want to retrieve it from DB.
Raises KeyError:
 

if no view can be found for the given entity.

class default_view(app_or_blueprint, entity, id_attr='object_id', endpoint=None, kw_func=None)

Decorator to register a view as default view for given entity class.

Parameters:
  • id_attr – url parameter name for object id.
  • endpoint – endpoint to use, defaults to view function’s name.
  • kw_func – function to process keywords to be passed to url_for. Useful for additional keywords. This function receives: kw, obj, obj_type, obj_id, **kwargs. It must return kw.
class BaseObjectView(Model=None, pk=None, *args, **kwargs)

Base class common to all database objects views

breadcrumb()

Return nav.BreadcrumbItem instance for this object.

This method may return a list of BreadcrumbItem instances. Return None if nothing.

get()
init_object(args, kwargs)

This method is reponsible for setting obj. It is called during prepare_args().

prepare_args(args, kwargs)
Model = None
base_template = 'base.html'
methods = ['GET']
obj = None
pk = 'object_id'
template = None
template_kwargs

Template render arguments. You can override base_template for instance. Only view and form cannot be overriden.

title = None
class ObjectView(Model=None, pk=None, Form=None, template=None, *args, **kwargs)

View objects

get_form_kwargs()
index_url()
prepare_args(args, kwargs)

form is initialized here. See also View.prepare_args().

redirect_to_index()
Form = None
form = None
methods = ['GET']
template = 'default/object_view.html'
class ObjectEdit(Model=None, pk=None, Form=None, template=None, view_endpoint=None, message_success=None, *args, **kwargs)

Edit objects

before_populate_obj()

This method is called after form has been validated and before calling form.populate_obj(). Sometimes one may want to remove a field from the form because it’s non-sense to store it on edited object, and use it in a specific manner, for example:

image = form.image
del form.image
store_image(image)
cancel()
edit()
get_form_buttons(*args, **kwargs)
get_form_kwargs()
handle_action(action)
message_success()
post(*args, **kwargs)
prepare_args(args, kwargs)
put()
redirect_to_view()
view_url()
action = None
button = None
buttons
data = None
methods = ['GET', 'POST', 'PUT']
template = 'default/object_edit.html'
class ObjectCreate(Model=None, pk=None, Form=None, template=None, view_endpoint=None, message_success=None, *args, **kwargs)

Create a new object

cancel()
chain_create()
create()
get_form_buttons(*args, **kwargs)
init_object(args, kwargs)
chain_create_allowed = False
methods = ['GET', 'POST', 'PUT']
class ObjectDelete(Model=None, pk=None, Form=None, template=None, view_endpoint=None, message_success=None, *args, **kwargs)

Delete object. Supports DELETE verb.

delete(*args, **kwargs)
get_form_buttons(*args, **kwargs)
init_object(args, kwargs)

This method is reponsible for setting obj. It is called during prepare_args().

methods = ['DELETE', 'GET', 'POST', 'PUT']

Module abilian.web.frontend

Front-end for a CRM app.

This should eventually allow implementing very custom CRM-style application.

class CRUDApp(app, modules=None)[source]
add_module(module)[source]
create_blueprint(module)[source]
class DefaultRelatedView(label, attr, column_names, options=None)[source]

Default view used by Module for items directly related to entity

render(entity)[source]
class Module[source]
create_blueprint(crud_app)[source]

Create a Flask blueprint for this module.

entity_delete(entity_id)[source]
entity_edit(*args, **kwargs)[source]
entity_edit_post(entity_id)[source]
entity_new(*args, **kwargs)[source]
entity_new_put()[source]
entity_view(*args, **kwargs)[source]
export_to_csv()[source]
export_to_xls()[source]
is_current()[source]
list_json()[source]

JSON endpoint, for AJAX-backed table views.

list_json2()[source]

Other JSON endpoint, this time used for filling select boxes dynamically.

NB: not used currently.

list_view(*args, **kwargs)[source]
ordered_query(request, query=None)[source]

Order query according to request args.

If query is None, the query is generated according to request args with self.query(request)

query(request)[source]

Return filtered query based on request args

render_entity_view(entity)[source]
blueprint = None
edit_form_class = None
endpoint = None
id = None
label = None
list_view_columns = []
managed_class = None
name = None
related_views = []
search_criterions = (<abilian.web.search.criterion.TextSearchCriterion object at 0x7fe314de7450>,)
single_view = None
static_folder = None
url = None
view_form_class = None
view_new_save_and_add = False
view_options = None
view_template = None
class ModuleMeta(classname, bases, fields)[source]

Module metaclass.

Does some precalculations (like getting list of view methods from the class) to avoid calculating them for each view class instance.

class RelatedView[source]

A base class for related views

render(entity)[source]

Return a dict with keys ‘label’, ‘attr_name’, ‘rendered’, ‘size’

add_to_recent_items(entity, type='ignored')[source]
expose(url='/', methods=('GET', ))[source]

Use this decorator to expose views in your view classes.

url
Relative URL for the view
methods
Allowed HTTP methods. By default only GET is allowed.
labelize(s)[source]
make_single_view(form, **options)[source]

Module abilian.web.util

A few utility functions.

See https://docs.djangoproject.com/en/dev/topics/http/shortcuts/ for more ideas of stuff to implement.

get_object_or_404(cls, *args)[source]

Shorthand similar to Django’s get_object_or_404.

send_file_from_directory(filename, directory, app=None)[source]

Helper to add static rules, like in abilian.app.app

Example use:

app.add_url_rule(
   app.static_url_path + '/abilian/<path:filename>',
   endpoint='abilian_static',
   view_func=partial(send_file_from_directory,
                     directory='/path/to/static/files/dir'))
url_for(obj, **kw)[source]

Polymorphic variant of Flask’s url_for function.

Behaves like the original function when the first argument is a string. When it’s an object, it

Package abilian.testing

Elements to build test cases for an abilian.app.Application

class TestConfig[source]

Base class config settings for test cases.

The environment variable SQLALCHEMY_DATABASE_URI can be set to easily test against different databases.

BABEL_DEFAULT_LOCALE = 'en'
BABEL_DEFAULT_TIMEZONE = 'UTC'
CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
CSRF_ENABLED = False
MAIL_SENDER = 'test@testcase.app.tld'
SECRET_KEY = 'SECRET'
SITE_NAME = u'Abilian Test'
SQLALCHEMY_DATABASE_URI = 'sqlite://'
SQLALCHEMY_ECHO = False
TESTING = True
TRAP_BAD_REQUEST_ERRORS = True
TRAP_HTTP_EXCEPTIONS = False
WTF_CSRF_ENABLED = False
class BaseTestCase(methodName='runTest')[source]

Base test case to test an abilian.app.Application.

It will create an instance path that will be used and shared for all tests defined in this test case.

The test case creates a clean database before running each test by calling abilian.app.Application.create_db() et destroys it after test.

Additionaly if the database is postgresql a schema is created for each test and the connection role is altered to use this DB schema. This is done to ensure harder test isolation.

application_class

Application class to instantiate.

alias of Application

config_class

Config class to use for application_class configuration.

alias of TestConfig

assert_302(response)[source]
assert_valid(response)[source]

Validate response.data as HTML using validator provided by config.VALIDATOR_URL.

client_login(email, password)[source]

Like login() but with a web login request. Can be used as contextmanager.

All subsequent request made with self.client will be authentifed until client_logout() is called or exit of with block.

client_logout()[source]

Like logout() but with a web logout

create_app()[source]
get(url, validate=True)[source]

Validates HTML if asked by the config or the Unix environment.

get_setup_config()[source]

Called by create_app() Override this if you want to tweak the config before application_class is instanciated.

Returns:an instance of config_class, or anything that is a valid config object for Flask.
login(user, remember=False, force=False)[source]

Perform user login for user, so that code needing a logged-in user can work.

This method can also be used as a context manager, so that logout is performed automatically:

with self.login(user):
    self.assertEquals(...)

See also

logout()

login_system()[source]

Perform login with SYSTEM user. Can be used as a context manager.

See also

login(), logout()

logout()[source]

Perform user logout.

See also

login()

setUp()[source]
classmethod setUpClass()[source]
tearDown()[source]
classmethod tearDownClass()[source]
validate(url, content, content_type, validator_url)[source]
CLEAR_PASSWORDS = True

set to False to use cryptographic scheme (standard) for user password. By default the testcase switches to clear text to avoid longer running.

SERVICES = ()

list services names that should be started during setUp. ‘repository’ and

SQLALCHEMY_WARNINGS_AS_ERROR = True

By default sqlalchemy treats warnings as info. This settings makes sqlalchemy warnings treated as errors (and thus making test fail). The rationale is that it improves code quality (for example most frequent warnings are non-unicode string assigned on a Unicode column; this setting force you to be explicit and ensure unicode where appropriate)

TESTING_BUILD_ASSETS = False

enable assets building during tests. False by default.

TEST_INSTANCE_PATH = None

Path to instance folder. Mostly set for internal use, since you should access the value on the application (see Flask instance folders) This parameter is set by setUpClass()

db[source]

Shortcut to the application db object.