示例#1
0
    def _add_config_arg(self, type_, content_type, name, default=None, required=False, methods=ALL_HTTP_METHODS):
        """Add an arg that can be passed to ``@config``.

        .. note:: This shouldn't be called directly. It's used by both
            :meth:`add_config_field` and :meth:`add_representation_arg`
            because they work in exactly the same way.

        ``name`` is the name of the arg as it would be passed to
        ``@config`` as a keyword arg.

        If a ``default`` is specified, it can be a callable or any other
        type of object. If it's a callable, it will be used as a factory
        for generating the default. If it's any other type of object, it
        will be used as is.

        If the arg is ``required``, then it *must* be passed via
        ``@config``.

        A list of ``methods`` can be passed to constrain which HTTP
        methods the arg can be used on. By default, all methods are
        allowed. ``methods`` can be specified as a string like ``'GET'``
        or ``'GET,POST'`` or as a list of methods like
        ``('GET', 'POST')``.

        """
        if methods == "*":
            methods = ALL_HTTP_METHODS
        methods = as_tuple(methods, sep=",")
        arg = type_(methods, content_type, name, default, required)
        for method in methods:
            differentiator = (method, content_type)
            if not self.contains(type_, differentiator):
                self.register(type_, Registry(), differentiator)
            registry = self.get(type_, differentiator)
            registry.register(type_, arg, name)
示例#2
0
    def __init__(self, name, factory, path, methods=(), method_name=None,
                 add_slash=False):
        if not path.startswith('/'):
            path = '/' + path

        if path == '/':
            add_slash = False
        else:
            if path.endswith('/'):
                add_slash = True
            elif add_slash:
                path = '{}/'.format(path)

        self.name = name
        self.factory = factory
        self.path = path  # normalized path
        self.methods = set(as_tuple(methods, sep=','))
        self.method_name = method_name
        self.add_slash = add_slash

        urlvars_info = {}
        path_regex = []
        format_string = []
        i = 0

        for match in re.finditer(self.urlvar_regex, path):
            info = match.groupdict()
            identifier = info['identifier']

            if identifier in urlvars_info:
                raise ValueError('{} already present'.format(identifier))

            regex = info['regex'] or r'[\w-]+'

            converter = info['converter']
            if converter:
                if ':' in converter:
                    converter = load_object(converter)
                else:
                    converter = get_converter(converter)
            else:
                converter = str

            urlvars_info[identifier] = {'regex': regex, 'converter': converter}

            # Get the non-matching part of the string after the previous
            # match and before the current match.
            s, e = match.span()
            if i != s:
                before_match = path[i:s]
                path_regex.append(before_match)
                format_string.append(before_match)
            i = e

            path_regex.append(r'(?P<{}>{})'.format(identifier, regex))
            format_string.extend(('{', identifier, '}'))

        if i != len(path):
            remainder = path[i:]
            path_regex.append(remainder)
            format_string.append(remainder)

        path_regex = ''.join(path_regex)

        self.urlvars_info = urlvars_info
        self.segments = path_regex.strip('/').split('/')
        self.format_string = ''.join(format_string)

        if add_slash:
            path_regex = r'{}(?:/?)'.format(path_regex.rstrip('/'))

        self.path_regex = path_regex