コード例 #1
0
ファイル: controller.py プロジェクト: klmitch/appathy
    def __new__(mcs, name, bases, namespace):
        """
        Create a new Controller subclass.
        """

        # Normalize any specified path prefix
        if 'wsgi_path_prefix' in namespace:
            prefix = utils.norm_path(namespace['wsgi_path_prefix'], False)

            # If one of our bases has wsgi_path_prefix, prepend the
            # first one
            base_pfxs = [getattr(b, 'wsgi_path_prefix') for b in bases
                         if hasattr(b, 'wsgi_path_prefix')]
            if base_pfxs:
                prefix = base_pfxs[0] + prefix

            namespace['wsgi_path_prefix'] = prefix

        # Initialize the sets of actions and extensions
        actions = set()
        extensions = set()

        # Initialize serializers and deserializers
        serializers = {}
        deserializers = {}

        # Add the sets to the class dictionary
        namespace['_wsgi_actions'] = actions
        namespace['_wsgi_extensions'] = extensions

        # Add the serializers and deserializers to the class
        # dictionary
        namespace['_wsgi_serializers'] = serializers
        namespace['_wsgi_deserializers'] = deserializers

        # Find the action and extension methods
        for key, value in namespace.items():
            # Skip internal symbols and non-callables
            if key[0] == '_' or key.startswith('wsgi_') or not callable(value):
                continue

            # Is it an action or extension?
            if hasattr(value, '_wsgi_action'):
                actions.add(key)
            elif hasattr(value, '_wsgi_extension'):
                extensions.add(key)

        # Allow inheritance in our actions, extensions, serializers,
        # and deserializers
        for base in mcs.iter_bases(bases):
            mcs.inherit_set(base, namespace, '_wsgi_actions')
            mcs.inherit_set(base, namespace, '_wsgi_extensions')
            mcs.inherit_dict(base, namespace, '_wsgi_serializers')
            mcs.inherit_dict(base, namespace, '_wsgi_deserializers')
            mcs.inherit_dict(base, namespace, 'wsgi_method_map')

        return super(ControllerMeta, mcs).__new__(mcs, name, bases, namespace)
コード例 #2
0
ファイル: controller.py プロジェクト: klmitch/appathy
    def _route(self, action, method):
        """
        Given an action method, generates a route for it.
        """

        # First thing, determine the path for the method
        path = method._wsgi_path
        methods = None
        if path is None:
            map_rule = self.wsgi_method_map.get(method.__name__)
            if map_rule is None:
                # Can't connect this method
                LOG.warning("No path specified for action method %s() of "
                            "resource %s" % (method.__name__, self.wsgi_name))
                return

            # Compute the path and the method list
            path = utils.norm_path(map_rule[0] % self.wsgi_name)
            methods = map_rule[1]

        # Compute route name
        name = '%s_%s' % (self.wsgi_name, action)

        # Set up path
        path = getattr(self, 'wsgi_path_prefix', '') + path

        # Build up the conditions
        conditions = {}
        if hasattr(method, '_wsgi_methods'):
            conditions['method'] = methods if methods else method._wsgi_methods
        if hasattr(method, '_wsgi_condition'):
            conditions['function'] = method._wsgi_condition

        # Create the route
        self.wsgi_mapper.connect(name, path,
                                 controller=self,
                                 action=action,
                                 conditions=conditions,
                                 **getattr(method, '_wsgi_keywords', {}))
コード例 #3
0
ファイル: test_utils.py プロジェクト: klmitch/appathy
    def test_trailing_prohibited(self):
        result = utils.norm_path('/foo/', False)

        self.assertEqual(result, '/foo')
コード例 #4
0
ファイル: test_utils.py プロジェクト: klmitch/appathy
    def test_trailing_allowed(self):
        result = utils.norm_path('/foo/')

        self.assertEqual(result, '/foo/')
コード例 #5
0
ファイル: test_utils.py プロジェクト: klmitch/appathy
    def test_collapse(self):
        result = utils.norm_path('///foo/////bar')

        self.assertEqual(result, '/foo/bar')
コード例 #6
0
ファイル: test_utils.py プロジェクト: klmitch/appathy
    def test_leading(self):
        result = utils.norm_path('foobar')

        self.assertEqual(result, '/foobar')
コード例 #7
0
ファイル: controller.py プロジェクト: klmitch/appathy
def action(*methods, **kwargs):
    """
    Decorator which marks a method as an action.  The first positional
    argument identifies a Routes-compatible path for the action
    method, which must begin with a '/'.  If specified, the remaining
    positional arguments identify permitted HTTP methods.  The
    following keyword arguments are also recognized:

    * conditions
        Identifies a single function which will be passed the request
        (an instance of `webob.Request` and the match dictionary.  It
        should return True if the route matches, and False otherwise.

    * code
        Specifies the default HTTP return code to use for the
        response.  If not specified, defaults to 200.  Note that the
        action method may always return a ResponseObject instance with
        an alternate code, if desired.

    All other keyword arguments will be statically passed to the
    action method when called.
    """

    # Convert methods to a list, so it can be mutated if needed
    methods = list(methods)

    # Build up the function attributes
    attrs = dict(_wsgi_action=True)

    # Get the path...
    if methods and methods[0][0] == '/':
        # Normalize the path and set the attr
        attrs['_wsgi_path'] = utils.norm_path(methods.pop(0))

        # Are we restricting the methods?
        if methods:
            attrs['_wsgi_methods'] = [meth.upper() for meth in methods]
    else:
        # Path will be computed from collection/resource and method
        # name
        attrs['_wsgi_path'] = None

        # Allowed methods will be based on the function name; provide
        # some value for the attribute so they get set by the _route()
        # method
        attrs['_wsgi_methods'] = None

    # If we have a condition function, set it up
    if 'conditions' in kwargs:
        condition = kwargs.pop('conditions')

        @functools.wraps(condition)
        def wrapper(req, match_dict):
            if isinstance(req, dict):
                req = webob.Request(req)
            return condition(req, match_dict)

        attrs['_wsgi_condition'] = wrapper

    # If we have a default code, set it up
    if 'code' in kwargs:
        attrs['_wsgi_code'] = kwargs.pop('code')

    # Strip out action and controller arguments
    kwargs.pop('action', None)
    kwargs.pop('controller', None)

    # Save additional keyword arguments
    if kwargs:
        attrs['_wsgi_keywords'] = kwargs

    # Now, build the decorator we're going to return
    def decorator(func):
        # Save the attributes
        func.__dict__.update(attrs)
        return func

    return decorator