Exemplo n.º 1
0
def test_classgeneric_function_directive():
    class app(morepath.App):
        pass

    @reg.dispatch(reg.match_class('o', lambda o: o))
    def mygeneric(o):
        return "The object"

    class Foo(object):
        pass

    @app.function(mygeneric, o=Foo)
    def mygeneric_for_foo(o):
        return "The foo object"

    a = app()

    assert mygeneric(object, lookup=a.lookup) == 'The object'
    assert mygeneric(Foo, lookup=a.lookup) == 'The foo object'
Exemplo n.º 2
0
def test_classgeneric_function_directive():
    class app(morepath.App):
        pass

    @reg.dispatch(reg.match_class('o', lambda o: o))
    def mygeneric(o):
        return "The object"

    class Foo(object):
        pass

    @app.function(mygeneric, o=Foo)
    def mygeneric_for_foo(o):
        return "The foo object"

    a = app()

    assert mygeneric(object, lookup=a.lookup) == 'The object'
    assert mygeneric(Foo, lookup=a.lookup) == 'The foo object'
Exemplo n.º 3
0
class App(ChameleonApp, morpfw.SQLApp, DefaultAuthzPolicy):

    request_class = WebAppRequest

    portlet = dectate.directive(directive.PortletFactoryAction)
    portletprovider = dectate.directive(directive.PortletProviderFactoryAction)
    structure_column = dectate.directive(directive.StructureColumnAction)

    @reg.dispatch_method(reg.match_instance('model'),
                         reg.match_instance('request'), reg.match_key('name'))
    def get_structure_column(self, model, request, name):
        raise NotImplementedError('Get structure columns for %s structure:%s' %
                                  (model, name))

    def get_portletprovider(self, name):
        return self.config.portletprovider_registry.get_provider(name)

    @reg.dispatch_method(reg.match_class('schema'))
    def get_schemaextender(self, schema):
        return None
Exemplo n.º 4
0
 def __init__(self):
     self.get_converter = reg.dispatch(
         reg.match_class("type"),
         get_key_lookup=reg.DictCachingKeyLookup)(get_converter)
     self.register_converter(type(None), IDENTITY_CONVERTER)
Exemplo n.º 5
0
 def __init__(self):
     self.get_converter = reg.dispatch(
         reg.match_class('type'),
         get_key_lookup=reg.DictCachingKeyLookup)(get_converter)
     self.register_converter(type(None), IDENTITY_CONVERTER)
Exemplo n.º 6
0
import reg
from webob.exc import HTTPNotFound


@reg.dispatch('obj')
def path(obj):
    """Get the path and parameters for a model object in its own application.

    :param obj: model object or :class:`morepath.App` instance.
    :return: a tuple with a URL path and URL parameters, or ``None`` if
      path cannot be determined.
    """
    return None


@reg.dispatch(reg.match_class('cls', lambda cls: cls))
def class_path(cls, variables):
    """Get the path for a model class.

    :param cls: model class or :class:`morepath.App` subclass.
    :param variables: dictionary with variables to reconstruct
      the path and URL paramaters from path pattern.
    :return: a tuple with URL path and URL parameters, or ``None`` if
      path cannot be determined.
    """
    return None


@reg.dispatch('obj')
def deferred_link_app(mounted, obj):
    """Get application used for link generation.
Exemplo n.º 7
0
 def __init__(self):
     self._registry = PredicateRegistry(match_class('cls', lambda cls: cls))
Exemplo n.º 8
0
 class app(morepath.App):
     @morepath.dispatch_method(reg.match_class('o'))
     def mygeneric(self, o):
         return "The object"
Exemplo n.º 9
0
@reg.dispatch()
def remember_identity(response, request, identity):
    """Modify response so that identity is remembered by client.
    """
    raise NotImplementedError  # pragma: nocoverage


@reg.dispatch()
def forget_identity(response, request):
    """Modify response so that identity is forgotten by client.
    """
    raise NotImplementedError  # pragma: nocoverage


@reg.dispatch('identity', 'obj',
              reg.match_class('permission',
                              lambda permission: permission))
def permits(identity, obj, permission):
    """Returns True if identity has permission for model.

    identity can be the special NO_IDENTITY singleton; register for
    NoIdentity to handle this case separately.
    """
    return False


@reg.dispatch()
def load_json(request, json):
    """Load JSON as some object.

    Can return any Python object.
    """
Exemplo n.º 10
0
The functions are made pluggable by the use of the
:func:`reg.dispatch` and :func:`reg.dispatch_external_predicates`
decorators. Morepath's configuration function uses this to register
implementations using :meth:`reg.Registry.register_function`.

:func:`morepath.remember_identity`, :func:`morepath.forget_identity`
and :func:`morepath.settings`, currently exported to the public API,
are now deprecated.

"""
import reg
from webob.exc import HTTPNotFound


@reg.dispatch(reg.match_class('model', lambda model: model))
def class_path(model, variables):
    """Get the path for a model class.

    :param model: model class or :class:`morepath.App` subclass.
    :param variables: dictionary with variables to reconstruct
      the path and URL paramaters from path pattern.
    :return: a tuple with URL path and URL parameters, or ``None`` if
      path cannot be determined.
    """
    return None


@reg.dispatch('obj')
def path_variables(obj, lookup):
    """Get variables to use in path generation.
Exemplo n.º 11
0
class App(ChameleonApp, morpfw.SQLApp, MorpCCAuthzPolicy):

    request_class = WebAppRequest

    portlet = dectate.directive(directive.PortletFactoryAction)
    portletprovider = dectate.directive(directive.PortletProviderFactoryAction)
    contextportletprovider = dectate.directive(
        directive.ContextPortletProviderFactoryAction)
    structure_column = dectate.directive(directive.StructureColumnAction)
    schemaextender = dectate.directive(directive.SchemaExtenderAction)
    messagingprovider = dectate.directive(directive.MessagingProviderAction)
    vocabulary = dectate.directive(directive.VocabularyAction)
    indexer = dectate.directive(directive.IndexerAction)
    indexresolver = dectate.directive(directive.IndexResolverAction)
    behavior = dectate.directive(directive.BehaviorAction)
    application_behavior = dectate.directive(
        directive.ApplicationBehaviorAction)
    default_factory = dectate.directive(directive.DefaultFactoryAction)
    restricted_module = dectate.directive(directive.RestrictedModuleAction)
    breadcrumb = dectate.directive(directive.BreadcrumbAction)
    setting_page = dectate.directive(directive.SettingPageAction)
    setting_modules = dectate.directive(directive.SettingModuleAction)
    license_cert = dectate.directive(directive.LicenseCertAction)
    license_key = dectate.directive(directive.LicenseKeyAction)
    copyright_notice = dectate.directive(directive.CopyrightNoticeAction)
    datasource = dectate.directive(directive.DataSourceAction)
    permission_resolver = dectate.directive(directive.PermissionResolverAction)

    @reg.dispatch_method(reg.match_instance("model"), reg.match_key("name"))
    def get_indexer(self, model, name):
        return None

    @reg.dispatch_method(
        reg.match_instance("model"),
        reg.match_instance("request"),
        reg.match_key("name"),
    )
    def get_structure_column(self, model, request, name):
        raise NotImplementedError("Get structure columns for %s structure:%s" %
                                  (model, name))

    def get_portletprovider(self, name):
        return self.config.portletprovider_registry.get_provider(name)

    @reg.dispatch_method(reg.match_instance("model"), reg.match_key("name"))
    def get_contextportletprovider(self, model, name):
        return None

    @reg.dispatch_method(reg.match_class("schema"))
    def get_schemaextender(self, schema):
        return schema

    @reg.dispatch_method(reg.match_instance("request"), reg.match_key("name"))
    def get_messagingprovider(self, request, name):
        raise NotImplementedError("Messaging provider %s is not available" %
                                  name)

    @reg.dispatch_method(reg.match_instance("request"), reg.match_key("name"))
    def get_vocabulary(self, request, name):
        return None

    @reg.dispatch_method(reg.match_key("name"))
    def get_behavior_factory(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_application_behavior_factory(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_default_factory(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_index_resolver(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_restricted_module(self, name):
        raise ImportError(
            "Module {} is not allowed to be imported in this context".format(
                name))

    @reg.dispatch_method(
        reg.match_instance("model"),
        reg.match_instance("request"),
    )
    def get_breadcrumb(self, model, request):
        return []

    @reg.dispatch_method(reg.match_instance("request"))
    def get_license_cert(self, request):
        return None

    @reg.dispatch_method(reg.match_instance("request"))
    def get_license_key(self, request):
        return None

    @reg.dispatch_method(reg.match_instance("request"))
    def get_copyright_notice(self, request):
        dt = date.today()
        return (
            "Morp Control Center. © 2018-%s Mohd Izhar Firdaus Bin Ismail"
            % dt.year)

    @reg.dispatch_method(reg.match_key("name"))
    def get_datasource_factory(self, name):
        raise NotImplementedError()

    def get_datasource(self, name, request):
        return self.config.datasource_registry.get(name=name, request=request)

    def resolve_permissionassignment(self, request, model, permission,
                                     identity):
        return self.config.permissionresolver_registry.resolve(
            request, model, permission, identity)

    def render_view(self, context, request, name=""):
        lookup = self.get_view.by_predicates(model=context.__class__,
                                             name=name)
        if lookup and lookup.component:
            try:
                return lookup.component(obj=context, request=request, app=self)
            except HTTPException as e:
                return None
        return None
Exemplo n.º 12
0
class App(JsonSchemaApp, signals.SignalApp):
    jslcrud_dataprovider = dectate.directive(actions.DataProviderAction)
    jslcrud_jsonprovider = dectate.directive(actions.JSONProviderAction)
    jslcrud_jsontransfrom = dectate.directive(actions.JSONTransformAction)
    jslcrud_formvalidators = dectate.directive(actions.FormValidatorAction)
    jslcrud_identifierfields = dectate.directive(
        actions.IdentifierFieldsAction)
    jslcrud_default_identifier = dectate.directive(
        actions.DefaultIdentifierAction)

    jslcrud_rulesadapter = dectate.directive(actions.RulesAdapterAction)
    jslcrud_uuidfield = dectate.directive(actions.UUIDFieldAction)
    jslcrud_statemachine = dectate.directive(actions.StateMachineAction)

    @reg.dispatch_method(
        reg.match_class('schema', lambda self, schema, obj, storage: schema),
        reg.match_instance('obj'), reg.match_instance('storage'))
    def get_jslcrud_dataprovider(self, schema, obj, storage):
        raise NotImplementedError('Dataprovider for %s/%s' %
                                  (storage.__class__, obj.__class__))

    @reg.dispatch_method(reg.match_instance('obj'))
    def get_jslcrud_jsonprovider(self, obj):
        raise NotImplementedError('JSONProvider for %s' % obj.__class__)

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_jslcrud_jsontransform(self, schema):
        raise NotImplementedError('JSONTransform for %s' % schema)

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_jslcrud_formvalidators(self, schema):
        return []

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_jslcrud_identifierfields(self, schema):
        raise NotImplementedError('IdentifierFields for %s' % schema)

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_jslcrud_uuidfield(self, schema):
        return 'uuid'

    @reg.dispatch_method(
        reg.match_class('schema', lambda self, schema, obj, request: schema))
    def get_jslcrud_default_identifier(self, schema, obj, request):
        return None

    @reg.dispatch_method(reg.match_instance('model', lambda self, obj: obj))
    def _jslcrud_rulesadapter(self, obj):
        raise NotImplementedError

    @reg.dispatch_method(
        reg.match_instance('model', lambda self, context: context))
    def _jslcrud_statemachine(self, context):
        raise NotImplementedError

    def get_jslcrud_compositekey_separator(self):
        morp_settings = getattr(self.settings, 'jslcrud', {})
        return morp_settings.get('compositekey_separator', '!!!')

    def jslcrud_join_identifier(self, *args):
        separator = self.get_jslcrud_compositekey_separator()
        return separator.join(args)
Exemplo n.º 13
0
 def clear(self):
     self._registry = PredicateRegistry(match_class('cls', lambda cls: cls))
Exemplo n.º 14
0
 def __init__(self):
     self._registry = PredicateRegistry(match_class('cls'))
Exemplo n.º 15
0
class App(ChameleonApp, morpfw.SQLApp, DefaultAuthzPolicy):

    request_class = WebAppRequest

    portlet = dectate.directive(directive.PortletFactoryAction)
    portletprovider = dectate.directive(directive.PortletProviderFactoryAction)
    structure_column = dectate.directive(directive.StructureColumnAction)
    schemaextender = dectate.directive(directive.SchemaExtenderAction)
    messagingprovider = dectate.directive(directive.MessagingProviderAction)
    vocabulary = dectate.directive(directive.VocabularyAction)
    indexer = dectate.directive(directive.IndexerAction)
    indexresolver = dectate.directive(directive.IndexResolverAction)
    behavior = dectate.directive(directive.BehaviorAction)
    application_behavior = dectate.directive(
        directive.ApplicationBehaviorAction)
    default_factory = dectate.directive(directive.DefaultFactoryAction)
    restricted_module = dectate.directive(directive.RestrictedModuleAction)

    @reg.dispatch_method(reg.match_instance("model"), reg.match_key("name"))
    def get_indexer(self, model, name):
        return None

    @reg.dispatch_method(
        reg.match_instance("model"),
        reg.match_instance("request"),
        reg.match_key("name"),
    )
    def get_structure_column(self, model, request, name):
        raise NotImplementedError("Get structure columns for %s structure:%s" %
                                  (model, name))

    def get_portletprovider(self, name):
        return self.config.portletprovider_registry.get_provider(name)

    @reg.dispatch_method(reg.match_class("schema"))
    def get_schemaextender(self, schema):
        return schema

    @reg.dispatch_method(reg.match_instance("request"), reg.match_key("name"))
    def get_messagingprovider(self, request, name):
        raise NotImplementedError("Messaging provider %s is not available" %
                                  name)

    @reg.dispatch_method(reg.match_instance("request"), reg.match_key("name"))
    def get_vocabulary(self, request, name):
        return None

    @reg.dispatch_method(reg.match_key("name"))
    def get_behavior_factory(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_application_behavior_factory(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_default_factory(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_index_resolver(self, name):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key("name"))
    def get_restricted_module(self, name):
        raise ImportError(
            "Module {} is not allowed to be imported in this context".format(
                name))

    def render_view(self, context, request, name=""):
        lookup = self.get_view.by_predicates(model=context.__class__,
                                             name=name)
        if lookup and lookup.component:
            try:
                return lookup.component(obj=context, request=request, app=self)
            except HTTPException as e:
                return None
        return None
Exemplo n.º 16
0
class App(dectate.App):
    """A Morepath-based application object.

    You subclass App to create a morepath application class. You can
    then configure this class using Morepath decorator directives.

    An application can extend one or more other applications, if
    desired, by subclassing them. By subclassing App itself, you get
    the base configuration of the Morepath framework itself.

    Conflicting configuration within an app is automatically
    rejected. An subclass app cannot conflict with the apps it is
    subclassing however; instead configuration is overridden.

    You can turn your app class into a `WSGI`_ application by instantiating
    it. You can then call it with the ``environ`` and ``start_response``
    arguments.

    .. _`WSGI`: https://www.python.org/dev/peps/pep-3333/

    Subclasses from :class:`dectate.App`, which provides the
    :meth:`dectate.App.directive` decorator that lets you register
    new directives.
    """
    parent = None
    """The parent in which this app was mounted."""

    request_class = Request
    """The class of the Request to create. Must be a subclass of
    :class:`morepath.Request`.

    By default the request class is :class:`morepath.Request`
    """

    logger_name = 'morepath.directive'
    """Prefix used by dectate to log configuration actions.
    """

    setting = directive(action.SettingAction)
    setting_section = directive(action.SettingSectionAction)
    predicate_fallback = directive(action.PredicateFallbackAction)
    predicate = directive(action.PredicateAction)
    method = directive(action.MethodAction)
    converter = directive(action.ConverterAction)
    _path = directive(action.PathAction)
    path = directive(action.PathCompositeAction)
    permission_rule = directive(action.PermissionRuleAction)
    template_directory = directive(action.TemplateDirectoryAction)
    template_loader = directive(action.TemplateLoaderAction)
    template_render = directive(action.TemplateRenderAction)
    view = directive(action.ViewAction)
    json = directive(action.JsonAction)
    html = directive(action.HtmlAction)
    mount = directive(action.MountAction)
    defer_links = directive(action.DeferLinksAction)
    defer_class_links = directive(action.DeferClassLinksAction)
    tween_factory = directive(action.TweenFactoryAction)
    identity_policy = directive(action.IdentityPolicyAction)
    verify_identity = directive(action.VerifyIdentityAction)
    dump_json = directive(action.DumpJsonAction)
    load_json = directive(action.LoadJsonAction)
    link_prefix = directive(action.LinkPrefixAction)

    def __init__(self):
        pass

    def request(self, environ):
        """Create a :class:`Request` given WSGI environment for this app.

        :param environ: WSGI environment
        :return: :class:`morepath.Request` instance
        """
        return self.request_class(environ, self)

    def __call__(self, environ, start_response):
        """This app as a WSGI application.

        See the WSGI_ spec for more information.

        Uses :meth:`App.request` to generate a
        :class:`morepath.Request` instance, then uses
        meth:`App.publish` get the :class:`morepath.Response`
        instance.

        :param environ: WSGI environment
        :param start_response: WSGI start_response
        :return: WSGI iterable.
        """
        request = self.request(environ)
        response = self.publish(request)
        return response(environ, start_response)

    @reify
    def publish(self):
        """Publish functionality wrapped in tweens.

        You can use middleware (:doc:`tweens`) that can hooks in
        before a request is passed into the application and just after
        the response comes out of the application. Here we use
        :meth:`morepath.tween.TweenRegistry.wrap` to wrap the
        :func:`morepath.publish.publish` function into the configured
        tweens.

        This property uses :func:`morepath.reify.reify` so that the
        tween wrapping only happens once when the first request is
        handled and is cached afterwards.

        :return: a function that a :class:`morepath.Request` instance
          and returns a :class:`morepath.Response` instance.

        """
        # the last chance we have to commit the app is here, the
        # lookup may not be touched yet at this point
        if not self.is_committed():
            self.commit()
        return self.config.tween_registry.wrap(self)

    def ancestors(self):
        """Return iterable of all ancestors of this app.

        Includes this app itself as the first ancestor, all the way
        up to the root app in the mount chain.
        """
        app = self
        while app is not None:
            yield app
            app = app.parent

    @reify
    def root(self):
        """The root application.
        """
        return list(self.ancestors())[-1]

    def child(self, app, **variables):
        """Get app mounted in this app.

        Either give it an instance of the app class as the first
        parameter, or the app class itself (or name under which it was
        mounted) as the first parameter and as ``variables`` the
        parameters that go to its ``mount`` function.

        Returns the mounted application object, with its ``parent``
        attribute set to this app object, or ``None`` if this
        application cannot be mounted in this one.
        """
        if isinstance(app, App):
            result = app
            # XXX assert that variables is empty

            # XXX do we need to deal with subclasses of apps?
            if app.__class__ not in self.config.path_registry.mounted:
                return None
        else:
            if isinstance(app, compat.string_types):
                factory = self.config.path_registry.named_mounted.get(app)
            else:
                factory = self.config.path_registry.mounted.get(app)
            if factory is None:
                return None
            result = factory(**variables)
        result.parent = self
        return result

    def sibling(self, app, **variables):
        """Get app mounted next to this app.

        Either give it an instance of the app class as the first
        parameter, or the app class itself (or name under which it was
        mounted) as the first parameter and as ``variables`` the
        parameters that go to its ``mount`` function.

        Returns the mounted application object, with its ``parent``
        attribute set to the same parent as this one, or ``None`` if such
        a sibling application does not exist.
        """
        parent = self.parent
        if parent is None:
            return None
        return parent.child(app, **variables)

    @property
    def settings(self):
        """Returns the settings bound to this app."""
        return self.config.setting_registry

    @classmethod
    def mounted_app_classes(cls, callback=None):
        """Returns a set of this app class and any mounted under it.

        This assumes all app classes involved have already been
        committed previously, for instance by
        :meth:`morepath.App.commit`.

        Mounted apps are discovered in breadth-first order.

        The optional ``callback`` argument is used to implement
        :meth:`morepath.App.commit`.

        :param callback: a function that is called with app classes as
          its arguments. This can be used to do something with the app
          classes when they are first discovered, like commit
          them. Optional.
        :return: the set of app classes.

        """
        discovery = set()
        found = {cls}
        while found:
            discovery.update(found)
            if callback is not None:
                callback(*found)
            found = (
                {c
                 for a in found
                 for c in a.config.path_registry.mounted} - discovery)
        return discovery

    @classmethod
    def commit(cls):
        """Commit the app, and recursively, the apps mounted under it.

        Mounted apps are discovered in breadth-first order.

        :return: the set of discovered app clasess.
        """
        return cls.mounted_app_classes(dectate.commit)

    @classmethod
    def init_settings(cls, settings):
        """Pre-fill the settings before the app is started.

        Add settings to App, which can act as normal, can be overridden, etc.

        :param settings: a dictionary of setting sections which contain
          dictionaries of settings.
        """
        def set_setting_section(section, section_settings):
            cls.setting_section(section)(lambda: section_settings)

        for section, section_settings in settings.items():
            set_setting_section(section, section_settings)

    @dispatch_method()
    def get_view(self, obj, request):
        """Get the view that represents the obj in the context of a request.

        This view is a representation of the obj that can be rendered to a
        response. It may also return a :class:`morepath.Response`
        directly.

        Predicates are installed in :mod:`morepath.core` that inspect both
        ``obj`` and ``request`` to see whether a matching view can be found.

        You can also install additional predicates using the
        :meth:`morepath.App.predicate` and
        :meth:`morepath.App.precicate_fallback` directives.

        :param obj: model object to represent with view.
        :param request: :class:`morepath.Request` instance.
        :return: :class:`morepath.Response` object, or
          :class:`webob.exc.HTTPNotFound` if view cannot be found.
        """
        return HTTPNotFound()

    @dispatch_method('identity')
    def _verify_identity(self, identity):
        """Returns True if the claimed identity can be verified.

        Look in the database to verify the identity, or in case of auth
        tokens, always consider known identities to be correct.

        :param: :class:`morepath.Identity` instance.
        :return: ``True`` if identity can be verified. By default no identity
        can be verified so this returns ``False``.
        """
        return False

    @dispatch_method('identity', 'obj', reg.match_class('permission'))
    def _permits(self, identity, obj, permission):
        """Returns ``True`` if identity has permission for model object.

        identity can be the special :data:`morepath.NO_IDENTITY`
        singleton; register for :class:`morepath.NoIdentity` to handle
        this case separately.

        :param identity: :class:`morepath.Identity`
        :param obj: model object
        :param permission: permission class.
        :return: ``True`` if identity has permission for obj.
        """
        return False

    def _load_json(self, json, request):
        """Load JSON as some object.

        By default JSON is loaded as itself.

        :param json: JSON (in Python form) to convert into object.
        :param request: :class:`morepath.Request`
        :return: Any Python object, including JSON.
        """
        return json

    @dispatch_method('obj')
    def _dump_json(self, obj, request):
        """Dump an object as JSON.

        ``obj`` is any Python object, try to interpret it as JSON.

        :param obj: any Python object to convert to JSON.
        :param request: :class:`morepath.Request`
        :return: JSON representation (in Python form).
        """
        return obj

    def _link_prefix(self, request):
        """Returns a prefix that's added to every link generated by request.

        By default :attr:`webob.request.BaseRequest.application_url` is used.

        :param request: :class:`morepath.Request`
        :return: prefix string to add before links.
        """
        return request.application_url

    @dispatch_method(reg.match_class('model'))
    def _class_path(self, model, variables):
        """Get the path for a model class.

        :param model: model class or :class:`morepath.App` subclass.
        :param variables: dictionary with variables to reconstruct
        the path and URL paramaters from path pattern.
        :return: a :class:`morepath.path.PathInfo` with path within this app,
          or ``None`` if the path couldn't be determined.
        """
        return None

    @dispatch_method('obj')
    def _path_variables(self, obj):
        """Get variables to use in path generation.

        :param obj: model object or :class:`morepath.App` instance.
        :return: a dict with the variables to use for constructing the path,
        or ``None`` if no such dict can be found.
        """
        return self._default_path_variables(obj)

    @dispatch_method('obj')
    def _default_path_variables(self, obj):
        """Get default variables to use in path generation.

        Invoked if no specific ``path_variables`` is registered.

        :param obj: model object for ::class:`morepath.App` instance.
        :return: a dict with the variables to use for constructing the
        path, or ``None`` if no such dict can be found.
        """
        return None

    @dispatch_method('obj')
    def _deferred_link_app(self, obj):
        """Get application used for link generation.

        :param obj: model object to link to.
        :return: instance of :class:`morepath.App` subclass that handles
        link generation for this model, or ``None`` if no app exists
        that can construct link.
        """
        return None

    @dispatch_method(reg.match_class('model'))
    def _deferred_class_link_app(self, model, variables):
        """Get application used for link generation for a model class.

        :param model: model class
        :param variables: dict of variables used to construct class link
        :return: instance of :class:`morepath.App` subclass that handles
        link generation for this model class, or ``None`` if no app exists
        that can construct link.
        """
        return None

    @classmethod
    def clean(cls):
        reg.clean_dispatch_methods(cls)

    def _identify(self, request):
        """Determine identity for request.

        :param request: a :class:`morepath.Request` instance.
        :return: a :class:`morepath.Identity` instance or ``None`` if
        no identity can be found. Can also return :data:`morepath.NO_IDENTITY`,
        but ``None`` is converted automatically to this.
        """
        return None

    def remember_identity(self, response, request, identity):
        """Modify response so that identity is remembered by client.

        :param response: :class:`morepath.Response` to remember identity on.
        :param request: :class:`morepath.Request`
        :param identity: :class:`morepath.Identity`
        """
        pass

    def forget_identity(self, response, request):
        """Modify response so that identity is forgotten by client.

        :param response: :class:`morepath.Response` to forget identity on.
        :param request: :class:`morepath.Request`
        """
        pass

    def _get_path(self, obj):
        """Path for a model obj.

        Only includes path within the current app, does not take
        mounting into account.

        :param obj: model object
        :return: a :class:`morepath.path.PathInfo` with path within this app.
        """
        return self._class_path(obj.__class__, self._path_variables(obj))

    def _get_mounted_path(self, obj):
        """Path for model obj including mounted path.

        Includes path to this app itself, so takes mounting into account.

        :param obj: model object (or :class:`morepath.App` instance).
        :return: a :class:`morepath.path.PathInfo` with fully resolved
          path in mounts.
        """
        paths = []
        parameters = {}
        app = self
        while app is not None:
            info = app._get_path(obj)
            if info is None:
                return None
            paths.append(info.path)
            parameters.update(info.parameters)
            obj = app
            app = app.parent
        paths.reverse()
        return PathInfo('/'.join(paths).strip('/'), parameters)

    def _get_mounted_class_path(self, model, variables):
        """Path for model class and variables including mounted path.

        Includes path to this app itself, so takes mounting into account.

        :param model: model class
        :param variables: dict with variables to use in the path
        :return: a :class:`morepath.path.PathInfo` with fully resolved
          path in mounts.
        """
        info = self._class_path(model, variables)
        if info is None:
            return None
        if self.parent is None:
            return info
        mount_info = self.parent._get_mounted_path(self)
        path = mount_info.path
        if info.path:
            path += '/' + info.path
        parameters = info.parameters.copy()
        parameters.update(mount_info.parameters)
        return PathInfo(path, parameters)

    def _get_deferred_mounted_path(self, obj):
        """Path for obj taking into account deferring apps.

        Like :meth:`morepath.App._get_mounted_path` but takes
        :meth:`morepath.App.defer_links` and
        :meth:`morepath.App.defer_class_links` directives into
        account.
        """
        def find(app, obj):
            return app._get_mounted_path(obj)

        info, app = self._follow_defers(find, obj)
        return info

    def _get_deferred_mounted_class_path(self, model, variables):
        """Path for model and variables taking into account deferring apps.

        Like :meth:`morepath.App._get_mounted_class_path` but takes
        :meth:`morepath.App.defer_class_links` directive into
        account.
        """
        def find(app, model, variables):
            return app._get_mounted_class_path(model, variables)

        info, app = self._follow_class_defers(find, model, variables)
        return info

    def _follow_defers(self, find, obj):
        """Resolve to deferring app and find something.

        For ``obj``, look up deferring app as defined by
        :class:`morepath.App.defer_links` recursively. Use the
        supplied ``find`` function to find something for ``obj`` in
        that app. When something found, return what is found and
        the app where it was found.

        :param find: a function that takes an ``app`` and ``obj`` parameter and
          should return something when it is found, or ``None`` when not.
        :param obj: the model object to find things for.
        :return: a tuple with the thing found (or ``None``) and the app in
          which it was found.
        """
        seen = set()
        app = self
        while app is not None:
            if app in seen:
                raise LinkError("Circular defer. Cannot link to: %r" % obj)
            result = find(app, obj)
            if result is not None:
                return result, app
            seen.add(app)
            next_app = app._deferred_link_app(obj)
            if next_app is None:
                # only if we can establish the variables of the app here
                # fall back on using class link app
                variables = app._path_variables(obj)
                if variables is not None:
                    next_app = app._deferred_class_link_app(
                        obj.__class__, variables)
            app = next_app
        return None, app

    def _follow_class_defers(self, find, model, variables):
        """Resolve to deferring app and find something.

        For ``model`` and ``variables``, look up deferring app as defined
        by :class:`morepath.App.defer_class_links` recursively. Use the
        supplied ``find`` function to find something for ``model`` and
        ``variables`` in that app. When something found, return what is
        found and the app where it was found.

        :param find: a function that takes an ``app``, ``model`` and
          ``variables`` arguments and should return something when it is
          found, or ``None`` when not.
        :param model: the model class to find things for.
        :return: a tuple with the thing found (or ``None``) and the app in
          which it was found.
        """
        seen = set()
        app = self
        while app is not None:
            if app in seen:
                raise LinkError("Circular defer. Cannot link to: %r" % model)
            result = find(app, model, variables)
            if result is not None:
                return result, app
            seen.add(app)
            app = app._deferred_class_link_app(model, variables)
        return None, app
Exemplo n.º 17
0
class App(JsonSchemaApp, signals.SignalApp):

    dataprovider = dectate.directive(actions.DataProviderAction)
    jsonprovider = dectate.directive(actions.JSONProviderAction)
    formvalidators = dectate.directive(actions.FormValidatorAction)
    identifierfields = dectate.directive(actions.IdentifierFieldsAction)
    default_identifier = dectate.directive(actions.DefaultIdentifierAction)
    rulesprovider = dectate.directive(actions.RulesProviderAction)
    uuidfield = dectate.directive(actions.UUIDFieldAction)
    statemachine = dectate.directive(actions.StateMachineAction)
    searchprovider = dectate.directive(actions.SearchProviderAction)
    aggregateprovider = dectate.directive(actions.AggregateProviderAction)
    xattrprovider = dectate.directive(actions.XattrProviderAction)
    storage = dectate.directive(actions.StorageAction)
    blobstorage = dectate.directive(actions.BlobStorageAction)
    typeinfo = dectate.directive(actions.TypeInfoFactoryAction)

    def get_storage(self, model, request):
        blobstorage = self.get_blobstorage(model, request)
        return self._get_storage(model, request, blobstorage)

    def get_blobstorage(self, model, request):
        return self._get_blobstorage(model, request)

    @reg.dispatch_method(reg.match_class('model'),
                         reg.match_instance('request'),
                         reg.match_instance('blobstorage'))
    def _get_storage(self, model, request, blobstorage):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_class('model'),
                         reg.match_instance('request'))
    def _get_blobstorage(self, model, request):
        return NullBlobStorage()

    @reg.dispatch_method(
        reg.match_class('schema', lambda self, schema, obj, storage: schema),
        reg.match_instance('obj'), reg.match_instance('storage'))
    def get_dataprovider(self, schema, obj, storage):
        raise NotImplementedError('Dataprovider for %s/%s' %
                                  (storage.__class__, obj.__class__))

    @reg.dispatch_method(reg.match_instance('obj'))
    def get_jsonprovider(self, obj):
        raise NotImplementedError('JSONProvider for %s' % obj.__class__)

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_formvalidators(self, schema):
        return []

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_identifierfields(self, schema):
        raise NotImplementedError('IdentifierFields for %s' % schema)

    @reg.dispatch_method(reg.match_class('schema',
                                         lambda self, schema: schema))
    def get_uuidfield(self, schema):
        return 'uuid'

    @reg.dispatch_method(
        reg.match_class('schema', lambda self, schema, obj, request: schema))
    def get_default_identifier(self, schema, obj, request):
        return None

    @reg.dispatch_method(
        reg.match_instance('model', lambda self, context: context))
    def get_rulesprovider(self, context):
        raise NotImplementedError

    @reg.dispatch_method(
        reg.match_instance('model', lambda self, context: context))
    def get_statemachine(self, context):
        raise NotImplementedError

    @reg.dispatch_method(
        reg.match_instance('model', lambda self, context: context))
    def get_searchprovider(self, context):
        raise NotImplementedError

    @reg.dispatch_method(
        reg.match_instance('model', lambda self, context: context))
    def get_aggregateprovider(self, context):
        raise NotImplementedError

    @reg.dispatch_method(
        reg.match_instance('model', lambda self, context: context))
    def get_xattrprovider(self, context):
        raise NotImplementedError

    @reg.dispatch_method(reg.match_key('name'))
    def get_typeinfo_factory(self, name):
        raise NotImplementedError

    def get_compositekey_separator(self):
        morp_settings = self.settings.application
        return morp_settings.compositekey_separator

    def join_identifier(self, *args):
        separator = self.get_compositekey_separator()
        return separator.join(args)

    def permits(self, request: morepath.Request, context: Model,
                permission: str):
        identity = request.identity
        return self._permits(identity, context, permission)
Exemplo n.º 18
0
 def __init__(self):
     self._registry = PredicateRegistry(match_class('cls', lambda cls: cls))
Exemplo n.º 19
0
from zope.sqlalchemy import register as register_session
from more.basicauth import BasicAuthIdentityPolicy
from .exc import ConfigurationError
import transaction
import sqlalchemy
from celery import Celery
import yaml
import copy

default_settings = open(
    os.path.join(os.path.dirname(__file__), 'default_settings.yml')).read()
default_settings = default_settings.replace(r'%(here)s', os.getcwd())
default_settings = yaml.load(default_settings)


@reg.dispatch(reg.match_class('app', lambda app, *args, **kwargs: app))
def create_app(app, settings, scan=True, **kwargs):
    raise NotImplementedError


@create_app.register(app=BaseApp)
def create_baseapp(app, settings, scan=True, **kwargs):

    s = copy.deepcopy(default_settings)
    for k in settings.keys():
        if k in s.keys():
            for j, v in settings[k].items():
                s[k][j] = v
        else:
            s[k] = settings[k]