Example #1
0
def load_behavior(_context, behavior):
    conf = behavior['config']
    klass = resolve_dotted_name(behavior['klass'])
    factory = conf.get('factory') or klass
    real_factory = resolve_dotted_name(factory)
    if IInterface.providedBy(real_factory):
        # create concret class to register for behavior
        schema = real_factory
        from guillotina.behaviors.instance import AnnotationBehavior

        class real_factory(AnnotationBehavior):
            __annotations_data_key__ = conf.get('data_key', 'default')
            auto_serialize = conf.get('auto_serialize', True)
    else:
        schema = resolve_dotted_name(conf['provides'])
    classImplements(real_factory, schema)

    name = conf.get('name')
    name_only = conf.get('name_only', False)
    title = conf.get('title', '')
    for_ = resolve_dotted_name(conf.get('for_'))
    marker = resolve_dotted_name(conf.get('marker'))

    if marker is None and real_factory is None:
        marker = schema

    if marker is not None and real_factory is None and marker is not schema:
        raise ConfigurationError(
            u"You cannot specify a different 'marker' and 'provides' if "
            u"there is no adapter factory for the provided interface."
        )
    if name_only and name is None:
        raise ConfigurationError(
            u"If you decide to only register by 'name', a name must be given."
        )

    # Instantiate the real factory if it's the schema-aware type. We do
    # this here so that the for_ interface may take this into account.
    if factory is not None and IBehaviorSchemaAwareFactory.providedBy(factory):
        factory = factory(schema)

    registration = BehaviorRegistration(
        title=conf.get('title', ''),
        description=conf.get('description', ''),
        interface=schema,
        marker=marker,
        factory=real_factory,
        name=name,
        for_=for_
    )
    if not name_only:
        # behavior registration by provides interface identifier
        component.utility(
            _context,
            provides=IBehavior,
            name=schema.__identifier__,
            component=registration
        )

    if name is not None:
        # for convinience we register with a given name
        component.utility(
            _context,
            provides=IBehavior,
            name=name,
            component=registration
        )

    if factory is None:
        if for_ is not None:
            logger.warning(
                u"Specifying 'for' in behavior '{0}' if no 'factory' is given "
                u"has no effect and is superfluous.".format(title)
            )
        # w/o factory we're done here
        return

    if for_ is None:
        # Attempt to guess the factory's adapted interface and use it as
        # the 'for_'.
        # Fallback to '*' (=Interface).
        adapts = getattr(factory, '__component_adapts__', None) or [Interface]
        if len(adapts) != 1:
            raise ConfigurationError(
                u"The factory can not be declared as multi-adapter."
            )
        for_ = adapts[0]

    adapter_factory = BehaviorAdapterFactory(registration)

    component.adapter(
        _context,
        factory=(adapter_factory,),
        provides=schema,
        for_=(for_,)
    )
Example #2
0
def load_behavior(_context, behavior):
    conf = behavior['config']
    klass = resolve_dotted_name(behavior['klass'])
    factory = conf.get('factory') or klass
    real_factory = resolve_dotted_name(factory)
    if IInterface.providedBy(real_factory):
        # create concret class to register for behavior
        schema = real_factory
        from guillotina.behaviors.instance import AnnotationBehavior

        class real_factory(AnnotationBehavior):
            __annotations_data_key__ = conf.get('data_key', 'default')
            auto_serialize = conf.get('auto_serialize', True)
    else:
        schema = resolve_dotted_name(conf['provides'])
    classImplements(real_factory, schema)

    name = conf.get('name')
    name_only = conf.get('name_only', False)
    title = conf.get('title', '')
    for_ = resolve_dotted_name(conf.get('for_'))
    marker = resolve_dotted_name(conf.get('marker'))

    if marker is None and real_factory is None:
        marker = schema

    if marker is not None and real_factory is None and marker is not schema:
        raise ConfigurationError(
            u"You cannot specify a different 'marker' and 'provides' if "
            u"there is no adapter factory for the provided interface."
        )
    if name_only and name is None:
        raise ConfigurationError(
            u"If you decide to only register by 'name', a name must be given."
        )

    # Instantiate the real factory if it's the schema-aware type. We do
    # this here so that the for_ interface may take this into account.
    if factory is not None and IBehaviorSchemaAwareFactory.providedBy(factory):
        factory = factory(schema)

    registration = BehaviorRegistration(
        title=conf.get('title', ''),
        description=conf.get('description', ''),
        interface=schema,
        marker=marker,
        factory=real_factory,
        name=name,
        for_=for_
    )
    if not name_only:
        # behavior registration by provides interface identifier
        component.utility(
            _context,
            provides=IBehavior,
            name=schema.__identifier__,
            component=registration
        )

    if name is not None:
        # for convinience we register with a given name
        component.utility(
            _context,
            provides=IBehavior,
            name=name,
            component=registration
        )

    if factory is None:
        if for_ is not None:
            logger.warning(
                u"Specifying 'for' in behavior '{0}' if no 'factory' is given "
                u"has no effect and is superfluous.".format(title)
            )
        # w/o factory we're done here
        return

    if for_ is None:
        # Attempt to guess the factory's adapted interface and use it as
        # the 'for_'.
        # Fallback to '*' (=Interface).
        adapts = getattr(factory, '__component_adapts__', None) or [Interface]
        if len(adapts) != 1:
            raise ConfigurationError(
                u"The factory can not be declared as multi-adapter."
            )
        for_ = adapts[0]

    adapter_factory = BehaviorAdapterFactory(registration)

    component.adapter(
        _context,
        factory=(adapter_factory,),
        provides=schema,
        for_=(for_,)
    )