2. The VRegistry, selectors and application objects — CubicWeb 3.11.0

### Navigation

- index
- modules |
- next |
- previous |
- CubicWeb 3.11.0 »
- Repository development »

# 2. The VRegistry, selectors and application objects

This chapter deals with some of the core concepts of the CubicWeb framework which make it different from other frameworks (and maybe not easy to grasp at a first glance). To be able to do advanced development with CubicWeb you need a good understanding of what is explained below.

This chapter goes deep into details. You don’t have to remember them all but keep it in mind so you can go back there later.

An overview of AppObjects, the VRegistry and Selectors is given in the Registries and application objects chapter.

## 2.1. The VRegistry

The VRegistry can be seen as a two-level dictionary. It contains all dynamically loaded objects (subclasses of The AppObject class) to build a CubicWeb application. Basically:

- the first level key returns a registry. This key corresponds to the __registry__ attribute of application object classes
- the second level key returns a list of application objects which share the same identifier. This key corresponds to the __regid__ attribute of application object classes.

A registry holds a specific kind of application objects. There is for instance a registry for entity classes, another for views, etc...

The VRegistry has two main responsibilities:

- being the access point to all registries
- handling the registration process at startup time, and during automatic reloading in debug mode.

### 2.1.1. Details of the recording process

On startup, CubicWeb loads application objects defined in its library and in cubes used by the instance. Application objects from the library are loaded first, then those provided by cubes are loaded in dependency order (e.g. if your cube depends on an other, objects from the dependency will be loaded first). The layout of the modules or packages in a cube is explained in Standard structure for a cube.

For each module:

- by default all objects are registered automatically
- if some objects have to replace other objects, or have to be included only if some condition is met, you’ll have to define a registration_callback(vreg) function in your module and explicitly register all objects in this module, using the api defined below.

Note

Once the function registration_callback(vreg) is implemented in a module, all the objects from this module have to be explicitly registered as it disables the automatic objects registration.

### 2.1.2. API for objects registration

Here are the registration methods that you can use in the registration_callback to register your objects to the VRegistry instance given as argument (usually named vreg):

`CubicWebVRegistry.` `register_all`(objects, modname, butclasses=())

  register all objects given. Objects which are not from the module modname or which are in butclasses won’t be registered.

  Typical usage is:

      vreg.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))

  So you get partially automatic registration, keeping manual registration for some object (to use `register_and_replace()` for instance)

`CubicWebVRegistry.` `register_and_replace`(obj, replaced, registryname=None)
  register obj application object into registryname or obj.__registry__ if not specified. If found, the replaced object will be unregistered first (else a warning will be issued as it’s generally unexpected).

`CubicWebVRegistry.` `register`(obj, *args, **kwargs)

  register obj application object into registryname or obj.__registry__ if not specified, with identifier oid or obj.__regid__ if not specified.

  If clear is true, all objects with the same identifier will be previously unregistered.

`CubicWebVRegistry.` `unregister`(obj, registryname=None)
  unregister obj application object from the registry registryname or obj.__registry__ if not specified.

Examples:

    # web/views/basecomponents.py
    def registration_callback(vreg):
       # register everything in the module except SeeAlsoComponent
       vreg.register_all(globals().values(), __name__, (SeeAlsoVComponent,))
       # conditionally register SeeAlsoVComponent
       if 'see_also' in vreg.schema:
           vreg.register(SeeAlsoVComponent)

In this example, we register all application object classes defined in the module except SeeAlsoVComponent. This class is then registered only if the ‘see_also’ relation type is defined in the instance’schema.

    # goa/appobjects/sessions.py
    def registration_callback(vreg):
       vreg.register(SessionsCleaner)
       # replace AuthenticationManager by GAEAuthenticationManager
       vreg.register_and_replace(GAEAuthenticationManager, AuthenticationManager)
       # replace PersistentSessionManager by GAEPersistentSessionManager
       vreg.register_and_replace(GAEPersistentSessionManager, PersistentSessionManager)

In this example, we explicitly register classes one by one:

- the SessionCleaner class
- the GAEAuthenticationManager to replace the AuthenticationManager
- the GAEPersistentSessionManager to replace the PersistentSessionManager

If at some point we register a new appobject class in this module, it won’t be registered at all without modification to the registration_callback implementation. The previous example will register it though, thanks to the call to the register_all method.

### 2.1.3. Runtime objects selection

Now that we have all application objects loaded, the question is : when I want some specific object, for instance the primary view for a given entity, how do I get the proper object ? This is what we call the selection mechanism.

As explained in the The Core Concepts of CubicWeb section:

- each application object has a selector, defined by its __select__ class attribute
- this selector is responsible to return a score for a given context
  - 0 score means the object doesn’t apply to this context
  - else, the higher the score, the better the object suits the context
- the object with the highest score is selected.

Note

When no single object has the highest score, an exception is raised in development mode to let you know that the engine was not able to identify the view to apply. This error is silenced in production mode and one of the objects with the highest score is picked.

In such cases you would need to review your design and make sure your selectors or appobjects are properly defined. Such an error is typically caused by either forgetting to change the __regid__ in a derived class, or by having copy-pasted some code.

For instance, if you are selecting the primary (__regid__ = ‘primary’) view (__registry__ = ‘views’) for a result set containing a Card entity, two objects will probably be selectable:

- the default primary view (__select__ = is_instance(‘Any’)), meaning that the object is selectable for any kind of entity type
- the specific Card primary view (__select__ = is_instance(‘Card’), meaning that the object is selectable for Card entities

Other primary views specific to other entity types won’t be selectable in this case. Among selectable objects, the is_instance(‘Card’) selector will return a higher score since it’s more specific, so the correct view will be selected as expected.

### 2.1.4. API for objects selections

Here is the selection API you’ll get on every registry. Some of them, as the ‘etypes’ registry, containing entity classes, extend it. In those methods, *args, **kwargs is what we call the context. Those arguments are given to selectors that will inspect their content and return a score accordingly.

`Registry.` `select`(_Registry__oid, *args, **kwargs)

  return the most specific object among those with the given oid according to the given context.

  raise `ObjectNotFound` if not object with id <oid> in <registry>

  raise `NoSelectableObject` if not object apply

`Registry.` `select_or_none`(_Registry__oid, *args, **kwargs)
  return the most specific object among those with the given oid according to the given context, or None if no object applies.

`Registry.` `possible_objects`(*args, **kwargs)
  return an iterator on possible objects in this registry for the given context

`Registry.` `object_by_id`(oid, *args, **kwargs)

  return object with the oid identifier. Only one object is expected to be found.

  raise `ObjectNotFound` if not object with id <oid> in <registry>

  raise `AssertionError` if there is more than one object there

## 2.2. Selectors

### 2.2.1. Using and combining existant selectors

You can combine selectors using the &, | and ~ operators.

When two selectors are combined using the & operator, it means that both should return a positive score. On success, the sum of scores is returned.

When two selectors are combined using the | operator, it means that one of them should return a positive score. On success, the first positive score is returned.

You can also “negate” a selector by precedeing it by the ~ unary operator.

Of course you can use parenthesis to balance expressions.

### 2.2.2. Example

The goal: when on a blog, one wants the RSS link to refer to blog entries, not to the blog entity itself.

To do that, one defines a method on entity classes that returns the RSS stream url for a given entity. The default implementation on `AnyEntity` (the generic entity class used as base for all others) and a specific implementation on Blog will do what we want.

But when we have a result set containing several Blog entities (or different entities), we don’t know on which entity to call the aforementioned method. In this case, we keep the generic behaviour.

Hence we have two cases here, one for a single-entity rsets, the other for multi-entities rsets.

In web/views/boxes.py lies the RSSIconBox class. Look at its selector:

    class RSSIconBox(box.Box):
      ''' just display the RSS icon on uniform result set '''
      __select__ = box.Box.__select__ & non_final_entity()

It takes into account:

- the inherited selection criteria (one has to look them up in the class hierarchy to know the details)
- `non_final_entity`, which filters on result sets containing non final entities (a ‘final entity’ being synonym for entity attributes type, eg String, Int, etc)

This matches our second case. Hence we have to provide a specific component for the first case:

    class EntityRSSIconBox(RSSIconBox):
      '''just display the RSS icon on uniform result set for a single entity'''
      __select__ = RSSIconBox.__select__ & one_line_rset()

Here, one adds the `one_line_rset` selector, which filters result sets of size 1. Thus, on a result set containing multiple entities, `one_line_rset` makes the EntityRSSIconBox class non selectable. However for a result set with one entity, the EntityRSSIconBox class will have a higher score than RSSIconBox, which is what we wanted.

Of course, once this is done, you have to:

- fill in the call method of EntityRSSIconBox
- provide the default implementation of the method returning the RSS stream url on `AnyEntity`
- redefine this method on Blog.

### 2.2.3. When to use selectors?

Selectors are to be used whenever arises the need of dispatching on the shape or content of a result set or whatever else context (value in request form params, authenticated user groups, etc...). That is, almost all the time.

Here is a quick example:

    class UserLink(component.Component):
        '''if the user is the anonymous user, build a link to login else a link
        to the connected user object with a logout link
        '''
        __regid__ = 'loggeduserlink'

        def call(self):
            if self._cw.session.anonymous_session:
                # display login link
                ...
            else:
                # display a link to the connected user object with a loggout link
                ...

The proper way to implement this with CubicWeb is two have two different classes sharing the same identifier but with different selectors so you’ll get the correct one according to the context.

    class UserLink(component.Component):
        '''display a link to the connected user object with a loggout link'''
        __regid__ = 'loggeduserlink'
        __select__ = component.Component.__select__ & authenticated_user()

        def call(self):
            # display useractions and siteactions
            ...

    class AnonUserLink(component.Component):
        '''build a link to login'''
        __regid__ = 'loggeduserlink'
        __select__ = component.Component.__select__ & anonymous_user()

        def call(self):
            # display login link
            ...

The big advantage, aside readability once you’re familiar with the system, is that your cube becomes much more easily customizable by improving componentization.

### 2.2.4. Defining your own selectors

Most of the time, a simple score function is enough to build a selector. The `objectify_selector()` decorator turn it into a proper selector class:

    @objectify_selector
    def one(cls, req, rset=None, **kwargs):
        return 1

    class MyView(View):
        __select__ = View.__select__ & one()

In other cases, you can take a look at the following abstract base classes:

class `cubicweb.selectors.` `ExpectedValueSelector`(*expected)

  Take a list of expected values as initializer argument and store them into the `expected` set attribute.

  You should implement the `_get_value(cls, req, **kwargs)()` method which should return the value for the given context. The selector will then return 1 if the value is expected, else 0.

class `cubicweb.selectors.` `EClassSelector`(once_is_enough=False, accept_none=True)

  abstract class for selectors working on entity class(es) specified explicitly or found of the result set.

  Here are entity lookup / scoring rules:

  - if entity is specified, return score for this entity’s class
  - elif row is specified, return score for the class of the entity found in the specified cell, using column specified by col or 0
  - else return the sum of scores for each entity class found in the column specified specified by the col argument or in column 0 if not specified, unless:
    - once_is_enough is False (the default) and some entity class is scored to 0, in which case 0 is returned
    - once_is_enough is True, in which case the first non-zero score is returned
    - accept_none is False and some cell in the column has a None value (this may occurs with outer join)

class `cubicweb.selectors.` `EntitySelector`(once_is_enough=False, accept_none=True)

  abstract class for selectors working on entity instance(s) specified explicitly or found of the result set.

  Here are entity lookup / scoring rules:

  - if entity is specified, return score for this entity
  - elif row is specified, return score for the entity found in the specified cell, using column specified by col or 0
  - else return the sum of scores for each entity found in the column specified specified by the col argument or in column 0 if not specified, unless:
    - once_is_enough is False (the default) and some entity is scored to 0, in which case 0 is returned
    - once_is_enough is True, in which case the first non-zero score is returned
    - accept_none is False and some cell in the column has a None value (this may occurs with outer join)

  Note

  using `EntitySelector` or `EClassSelector` as base selector class impacts performance, since when no entity or row is specified the later works on every different entity class found in the result set, while the former works on each entity (eg each row of the result set), which may be much more costly.

Also, think to use the `lltrace()` decorator on your selector class’ `__call__()` method or below the `objectify_selector()` decorator of your selector function so it gets traceable when `traced_selection` is activated (see Debugging selection).

`cubicweb.appobject.` `lltrace`(selector)
  use this decorator on your selectors so the becomes traceable with `traced_selection`

Note

Selectors __call__ should always return a positive integer, and shall never return None.

### 2.2.5. Debugging selection

Once in a while, one needs to understand why a view (or any application object) is, or is not selected appropriately. Looking at which selectors fired (or did not) is the way. The `cubicweb.appobject.traced_selection` context manager to help with that, if you’re running your instance in debug mode.

class `cubicweb.appobject.` `traced_selection`(traced='all')

  Typical usage is :

      >>> from cubicweb.selectors import traced_selection
      >>> with traced_selection():
      ...     # some code in which you want to debug selectors
      ...     # for all objects

  Don’t forget the ‘from __future__ import with_statement’ at the module top-level if you’re using python prior to 2.6.

  This will yield lines like this in the logs:

      selector one_line_rset returned 0 for <class 'cubicweb.web.views.basecomponents.WFHistoryVComponent'>

  You can also give to `traced_selection` the identifiers of objects on which you want to debug selection (‘oid1’ and ‘oid2’ in the example above).

      >>> with traced_selection( ('regid1', 'regid2') ):
      ...     # some code in which you want to debug selectors
      ...     # for objects with __regid__ 'regid1' and 'regid2'

  A potentially usefull point to set up such a tracing function is the cubicweb.vregistry.Registry.select method body.

## 2.3. The AppObject class

The AppObject class is the base class for all dynamically loaded objects (application objects) accessible through the vregistry.

We can find a certain number of attributes and methods defined in this class and common to all the application objects.

class `cubicweb.appobject.` `AppObject`(req, **extra)

  This is the base class for CubicWeb application objects which are selected according to a context (usually at least a request and a result set).

  The following attributes should be set on concret appobject classes:

  `__registry__`
    name of the registry for this object (string like ‘views’, ‘templates’...)
  `__regid__`
    object’s identifier in the registry (string like ‘main’, ‘primary’, ‘folder_box’)
  `__select__`
    class’selector

  Moreover, the __abstract__ attribute may be set to True to indicate that a class is abstract and should not be registered.

  At selection time, the following attributes are set on the instance:

  `_cw`
    current request
  `cw_extra_kwargs`
    other received arguments

  And also the following, only if rset is found in arguments (in which case rset/row/col will be removed from cwextra_kwargs):

  `cw_rset`
    context result set or None
  `cw_row`
    if a result set is set and the context is about a particular cell in the result set, and not the result set as a whole, specify the row number we are interested in, else None
  `cw_col`
    if a result set is set and the context is about a particular cell in the result set, and not the result set as a whole, specify the col number we are interested in, else None

  Note

  - do not inherit directly from this class but from a more specific class such as AnyEntity, EntityView, AnyRsetView, Action...

  - to be recordable, a subclass has to define its registry (attribute __registry__) and its identifier (attribute __regid__). Usually you don’t have to take care of the registry since it’s set by the base class, only the identifier id

  - application objects are designed to be loaded by the vregistry and should be accessed through it, not by direct instantiation, besides to use it as base classe.

  - When we inherit from AppObject (even not directly), you always have to use super() to get the methods and attributes of the superclasses, and not use the class identifier.

    For example, instead of writting:

        class Truc(PrimaryView):
            def f(self, arg1):
                PrimaryView.f(self, arg1)

    You must write:

        class Truc(PrimaryView):
            def f(self, arg1):
                super(Truc, self).f(arg1)

## 2.4. Base selectors

Selectors are scoring functions that are called by the registry to tell whenever an appobject can be selected in a given context. Selector sets are for instance the glue that tie views to the data model. Using them appropriately is an essential part of the construction of well behaved cubes.

Of course you may have to write your own set of selectors as your needs grows and you get familiar with the framework (see Defining your own selectors).

Here is a description of generic selectors provided by CubicWeb that should suit most of your needs.

### 2.4.1. Bare selectors

Those selectors are somewhat dumb, which doesn’t mean they’re not (very) useful.

class `cubicweb.appobject.` `yes`(score=0.5)

  Return the score given as parameter, with a default score of 0.5 so any other selector take precedence.

  Usually used for appobjects which can be selected whatever the context, or also sometimes to add arbitrary points to a score.

  Take care, yes(0) could be named ‘no’...

class `cubicweb.selectors.` `match_kwargs`(*expected)
  Return non-zero score if parameter names specified as initializer arguments are specified in the input context. When multiple parameters are specified, all of them should be specified in the input context. Return a score corresponding to the number of expected parameters.

class `cubicweb.selectors.` `appobject_selectable`(registry, *regids)

  Return 1 if another appobject is selectable using the same input context.

  Initializer arguments:

  - registry, a registry name
  - regids, object identifiers in this registry, one of them should be selectable.

class `cubicweb.selectors.` `adaptable`(*regids)

  Return 1 if another appobject is selectable using the same input context.

  Initializer arguments:

  - regids, adapter identifiers (e.g. interface names) to which the context (usually entities) should be adaptable. One of them should be selectable when multiple identifiers are given.

class `cubicweb.selectors.` `configuration_values`(key, values)
  Return 1 if the instance has an option set to a given value(s) in its configuration file.

### 2.4.2. Result set selectors

Those selectors are looking for a result set in the context (‘rset’ argument or the input context) and match or not according to its shape. Some of these selectors have different behaviour if a particular cell of the result set is specified using ‘row’ and ‘col’ arguments of the input context or not.

class `cubicweb.selectors.` `none_rset`
  Return 1 if the result set is None (eg usually not specified).

class `cubicweb.selectors.` `any_rset`
  Return 1 for any result set, whatever the number of rows in it, even 0.

class `cubicweb.selectors.` `nonempty_rset`
  Return 1 for result set containing one ore more rows.

class `cubicweb.selectors.` `empty_rset`
  Return 1 for result set which doesn’t contain any row.

class `cubicweb.selectors.` `one_line_rset`
  Return 1 if the result set is of size 1, or greater but a specific row in the result set is specified (‘row’ argument).

class `cubicweb.selectors.` `multi_lines_rset`(expected=None, operator=<built-in function eq>)

  Return 1 if the operator expression matches between num elements in the result set and the expected value if defined.

  By default, multi_lines_rset(expected) matches equality expression:
    nb row(s) in result set equals to expected value
  But, you can perform richer comparisons by overriding default operator:
    multi_lines_rset(expected, operator.gt)

  If expected is None, return 1 if the result set contains at least two rows. If rset is None, return 0.

class `cubicweb.selectors.` `multi_columns_rset`(expected=None, operator=<built-in function eq>)
  If nb is specified, return 1 if the result set has exactly nb column per row. Else (nb is None), return 1 if the result set contains at least two columns per row. Return 0 for empty result set.

class `cubicweb.selectors.` `paginated_rset`(nbpages=1)

  Return 1 or more for result set with more rows than one or more page size. You can specify expected number of pages to the initializer (default to one), and you’ll get that number of pages as score if the result set is big enough.

  Page size is searched in (respecting order): * a page_size argument * a page_size form parameters * the navigation.page-size property

class `cubicweb.selectors.` `sorted_rset`
  Return 1 for sorted result set (e.g. from an RQL query containing an ORDERBY clause), with exception that it will return 0 if the rset is ‘ORDERBY FTIRANK(VAR)’ (eg sorted by rank value of the has_text index).

class `cubicweb.selectors.` `one_etype_rset`
  Return 1 if the result set contains entities which are all of the same type in the column specified by the col argument of the input context, or in column 0.

class `cubicweb.selectors.` `multi_etypes_rset`(expected=None, operator=<built-in function eq>)
  If nb is specified, return 1 if the result set contains nb different types of entities in the column specified by the col argument of the input context, or in column 0. If nb is None, return 1 if the result set contains at least two different types of entities.

### 2.4.3. Entity selectors

Those selectors are looking for either an entity argument in the input context, or entity found in the result set (‘rset’ argument or the input context) and match or not according to entity’s (instance or class) properties.

class `cubicweb.selectors.` `non_final_entity`(once_is_enough=False, accept_none=True)

  Return 1 for entity of a non final entity type(s). Remember, “final” entity types are String, Int, etc... This is equivalent to is_instance(‘Any’) but more optimized.

  See `EClassSelector` documentation for entity class lookup / score rules according to the input context.

class `cubicweb.selectors.` `is_instance`(*expected_etypes, **kwargs)

  Return non-zero score for entity that is an instance of the one of given type(s). If multiple arguments are given, matching one of them is enough.

  Entity types should be given as string, the corresponding class will be fetched from the registry at selection time.

  See `EClassSelector` documentation for entity class lookup / score rules according to the input context.

  Note

  the score will reflect class proximity so the most specific object will be selected.

class `cubicweb.selectors.` `score_entity`(scorefunc, once_is_enough=False)

  Return score according to an arbitrary function given as argument which will be called with input content entity as argument.

  This is a very useful selector that will usually interest you since it allows a lot of things without having to write a specific selector.

  The function can return arbitrary value which will be casted to an integer value at the end.

  See `EntitySelector` documentation for entity lookup / score rules according to the input context.

class `cubicweb.selectors.` `rql_condition`(expression, once_is_enough=False)

  Return non-zero score if arbitrary rql specified in expression initializer argument return some results for entity found in the input context. Returned score is the number of items returned by the rql condition.

  expression is expected to be a string containing an rql expression, which must use ‘X’ variable to represent the context entity and may use ‘U’ to represent the request’s user.

  Warning

  If simply testing value of some attribute/relation of context entity (X), you should rather use the `score_entity` selector which will benefit from the ORM’s request entities cache.

  See `EntitySelector` documentation for entity lookup / score rules according to the input context.

class `cubicweb.selectors.` `relation_possible`(rtype, role='subject', target_etype=None, action='read', strict=False, **kwargs)

  Return 1 for entity that supports the relation, provided that the request’s user may do some action on it (see below).

  The relation is specified by the following initializer arguments:

  - rtype, the name of the relation
  - role, the role of the entity in the relation, either ‘subject’ or ‘object’, default to ‘subject’
  - target_etype, optional name of an entity type that should be supported at the other end of the relation
  - action, a relation schema action (e.g. one of ‘read’, ‘add’, ‘delete’, default to ‘read’) which must be granted to the user, else a 0 score will be returned. Give None if you don’t want any permission checking.
  - strict, boolean (default to False) telling what to do when the user has not globally the permission for the action (eg the action is not granted to one of the user’s groups)
    - when strict is False, if there are some local role defined for this action (e.g. using rql expressions), then the permission will be considered as granted
    - when strict is True, then the permission will be actually checked for each entity

  Setting strict to True impacts performance for large result set since you’ll then get the `EntitySelector` behaviour while otherwise you get the `EClassSelector`‘s one. See those classes documentation for entity lookup / score rules according to the input context.

class `cubicweb.selectors.` `partial_relation_possible`(action='read', **kwargs)

  Same as :class:~`cubicweb.selectors.relation_possible`, but will look for attributes of the selected class to get information which is otherwise expected by the initializer, except for action and strict which are kept as initializer arguments.

  This is useful to predefine selector of an abstract class designed to be customized.

class `cubicweb.selectors.` `has_related_entities`(rtype, role='subject', target_etype=None, **kwargs)

  Return 1 if entity support the specified relation and has some linked entities by this relation , optionaly filtered according to the specified target type.

  The relation is specified by the following initializer arguments:

  - rtype, the name of the relation
  - role, the role of the entity in the relation, either ‘subject’ or ‘object’, default to ‘subject’.
  - target_etype, optional name of an entity type that should be found at the other end of the relation

  See `EntitySelector` documentation for entity lookup / score rules according to the input context.

class `cubicweb.selectors.` `partial_has_related_entities`(**kwargs)

  Same as :class:~`cubicweb.selectors.has_related_entity`, but will look for attributes of the selected class to get information which is otherwise expected by the initializer.

  This is useful to predefine selector of an abstract class designed to be customized.

class `cubicweb.selectors.` `has_permission`(action)

  Return non-zero score if request’s user has the permission to do the requested action on the entity. action is an entity schema action (eg one of ‘read’, ‘add’, ‘delete’, ‘update’).

  Here are entity lookup / scoring rules:

  - if entity is specified, check permission is granted for this entity
  - elif row is specified, check permission is granted for the entity found in the specified cell
  - else check permission is granted for each entity found in the column specified specified by the col argument or in column 0

class `cubicweb.selectors.` `has_add_permission`(etype=None, **kwargs)

  Return 1 if request’s user has the add permission on entity type specified in the etype initializer argument, or according to entity found in the input content if not specified.

  It also check that then entity type is not a strict subobject (e.g. may only be used as a composed of another entity).

  See `EClassSelector` documentation for entity class lookup / score rules according to the input context when etype is not specified.

class `cubicweb.selectors.` `has_mimetype`(mimetype, once_is_enough=False)

  Return 1 if the entity adapt to IDownloadable and has the given MIME type.

  You can give ‘image/’ to match any image for instance, or ‘image/png’ to match only PNG images.

class `cubicweb.selectors.` `is_in_state`(*expected)

  Return 1 if entity is in one of the states given as argument list

  You should use this instead of your own `score_entity` selector to avoid some gotchas:

  - possible views gives a fake entity with no state
  - you must use the latest tr info thru the workflow adapter for repository side checking of the current state

  In debug mode, this selector can raise: :raises: `ValueError` for unknown states names

  > (etype workflow only not checked in custom workflow)

  Return type: | int

class `cubicweb.selectors.` `on_transition`(*expected)

  Return 1 if entity is in one of the transitions given as argument list

  Especially useful to match passed transition to enable notifications when your workflow allows several transition to the same states.

  Note that if workflow change_state adapter method is used, this selector will not be triggered.

  You should use this instead of your own `score_entity` selector to avoid some gotchas:

  - possible views gives a fake entity with no state
  - you must use the latest tr info thru the workflow adapter for repository side checking of the current state

  In debug mode, this selector can raise: :raises: `ValueError` for unknown transition names

  > (etype workflow only not checked in custom workflow)

  Return type: | int

class `cubicweb.selectors.` `implements`(*expected_ifaces, **kwargs)

  Return non-zero score for entity that are of the given type(s) or implements at least one of the given interface(s). If multiple arguments are given, matching one of them is enough.

  Entity types should be given as string, the corresponding class will be fetched from the entity types registry at selection time.

  See `EClassSelector` documentation for entity class lookup / score rules according to the input context.

  Note

  when interface is an entity class, the score will reflect class proximity so the most specific object will be selected.

  Note

  deprecated in cubicweb >= 3.9, use either `is_instance` or `adaptable`.

### 2.4.4. Logged user selectors

Those selectors are looking for properties of the user issuing the request.

class `cubicweb.selectors.` `anonymous_user`

  Return 1 if the user is not authenticated (e.g. is the anonymous user).

  May only be used on the web side, not on the data repository side.

class `cubicweb.selectors.` `authenticated_user`

  Return 1 if the user is authenticated (e.g. not the anonymous user).

  May only be used on the web side, not on the data repository side.

class `cubicweb.selectors.` `match_user_groups`(*expected)

  Return a non-zero score if request’s user is in at least one of the groups given as initializer argument. Returned score is the number of groups in which the user is.

  If the special ‘owners’ group is given and rset is specified in the input context:

  - if row is specified check the entity at the given row/col (default to 0) is owned by the user
  - else check all entities in col (default to 0) are owned by the user

### 2.4.5. Web request selectors

Those selectors are looking for properties of web request, they can not be used on the data repository side.

class `cubicweb.selectors.` `match_form_params`(*expected)
  Return non-zero score if parameter names specified as initializer arguments are specified in request’s form parameters. When multiple parameters are specified, all of them should be found in req.form. Return a score corresponding to the number of expected parameters.

class `cubicweb.selectors.` `match_search_state`(*expected)

  Return 1 if the current request search state is in one of the expected states given to the initializer.

  Known search states are either ‘normal’ or ‘linksearch’ (eg searching for an object to create a relation with another).

  This selector is usually used by action that want to appears or not according to the ui search state.

class `cubicweb.selectors.` `match_context_prop`

  Return 1 if:

  - no context is specified in input context (take care to confusion, here context refers to a string given as an argument to the input context...)
  - specified context is matching the context property value for the appobject using this selector
  - the appobject’s context property value is None

  This selector is usually used by contextual components that want to appears in a configurable place.

class `cubicweb.selectors.` `match_view`(*expected)
  Return 1 if a view is specified an as its registry id is in one of the expected view id given to the initializer.

class `cubicweb.selectors.` `primary_view`

  Return 1 if:

  - no view is specified in the input context
  - a view is specified and its .is_primary() method return True

  This selector is usually used by contextual components that only want to appears for the primary view of an entity.

class `cubicweb.selectors.` `specified_etype_implements`(*expected_etypes, **kwargs)

  Return non-zero score if the entity type specified by an ‘etype’ key searched in (by priority) input context kwargs and request form parameters match a known entity type (case insensitivly), and it’s associated entity class is of one of the type(s) given to the initializer. If multiple arguments are given, matching one of them is enough.

  Note

  as with `is_instance`, entity types should be given as string and the score will reflect class proximity so the most specific object will be selected.

  This selector is usually used by views holding entity creation forms (since we’ve no result set to work on).

class `cubicweb.selectors.` `attribute_edited`(attribute, once_is_enough=False)

  Scores if the specified attribute has been edited This is useful for selection of forms by the edit controller.

  The initial use case is on a form, in conjunction with match_transition, which will not score at edit time:

      is_instance('Version') & (match_transition('ready') |
                                attribute_edited('publication_date'))

### 2.4.6. Other selectors

class `cubicweb.selectors.` `match_transition`(*expected)
  Return 1 if transition argument is found in the input context which has a .name attribute matching one of the expected names given to the initializer.

class `cubicweb.selectors.` `debug_mode`
  Return 1 if running in debug mode.

You’ll also find some other (very) specific selectors hidden in other modules than `cubicweb.selectors`.

### Navigation

- index
- modules |
- next |
- previous |
- CubicWeb 3.11.0 »
- Repository development »