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)
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