Source code for

# coding=utf-8
from __future__ import absolute_import, print_function, division

from whoosh.analysis import (
    CharsetFilter, RegexTokenizer, LowercaseFilter,
    PathTokenizer, NgramFilter)

from import accent_map
from whoosh.formats import Existence
from whoosh.fields import (
    SchemaClass, FieldType,

from import Role, Anonymous
from abilian.core.util import noproxy
from abilian.core.models.subjects import User, Group

#: A Whoosh analyzer that splits on word boundaries and folds accents and case.
accent_folder = (RegexTokenizer(r'\w+')  # defaults doesn't split on '.'
                 | LowercaseFilter()
                 | CharsetFilter(accent_map))

#: Analyzer for edge-ngrams, from 2 to 6 characters long
edge_ngram = accent_folder | NgramFilter(minsize=2, maxsize=6, at='start')

def EdgeNgramField():
  return TEXT(stored=False, analyzer=edge_ngram)

class _DefaultSearchSchema(SchemaClass):
  General search schema
  object_key = ID(stored=True, unique=True)
  id = NUMERIC(numtype=int, bits=64, signed=False, stored=True, unique=False)
  object_type = ID(stored=True, unique=False)
  creator = ID(stored=True)
  owner = ID(stored=True)

  #: security index. This list roles and user/group ids allowed to *see* this
  #: content
  allowed_roles_and_users = KEYWORD(stored=True)

  # hierarchical index of ids path ('/' is the separator)
  parent_ids = FieldType(format=Existence(), analyzer=PathTokenizer(),
                         stored=True, unique=False)

  name = TEXT(stored=True, analyzer=accent_folder)
  slug = ID(stored=True)
  description = TEXT(stored=True, analyzer=accent_folder)
  text = TEXT(stored=False, analyzer=accent_folder)

_default_dyn_fields = {
    '*_prefix': EdgeNgramField(),
    '*_at': DATETIME(stored=True, sortable=True),

def DefaultSearchSchema(*args, **kwargs):
  schema = _DefaultSearchSchema()
  for name, field in _default_dyn_fields.items():
    schema.add(name, field, glob=True)
  return schema

[docs]def indexable_role(principal): """ Returns a string suitable for query against `allowed_roles_and_users` field. :param principal: It can be :data:`Anonymous`, :data:`Authenticated`, or an instance of :class:`User` or :class:`Group`. """ principal = noproxy(principal) if (hasattr(principal, 'is_anonymous') and principal.is_anonymous()): # transform anonymous user to anonymous role principal = Anonymous if isinstance(principal, Role): return u'role:{}'.format( elif isinstance(principal, User): fmt = u'user:{:d}' elif isinstance(principal, Group): fmt = u'group:{:d}' else: raise ValueError(repr(principal)) return fmt.format(