def _add(self, uri, methods, handler, host=None):
if host is not None:<EOL><INDENT>if isinstance(host, str):<EOL><INDENT>uri = host + uri<EOL>self.hosts.add(host)<EOL><DEDENT>else:<EOL><INDENT>if not isinstance(host, Iterable):<EOL><INDENT>raise ValueError("<STR_LIT>"<EOL>"<STR_LIT>".format(host))<EOL><DEDENT>for host_ in host:<EOL><INDENT>self.add(uri, methods, handler, host_)<EOL><DEDENT>return<EOL><DEDENT><DEDENT>if methods:<EOL><INDENT>methods = frozenset(methods)<EOL><DEDENT>parameters = []<EOL>properties = {"<STR_LIT>": None}<EOL>def add_parameter(match):<EOL><INDENT>name = match.group(<NUM_LIT:1>)<EOL>name, _type, pattern = self.parse_parameter_string(name)<EOL>parameter = Parameter(<EOL>name=name, cast=_type)<EOL>parameters.append(parameter)<EOL>if re.search(r'<STR_LIT>', pattern):<EOL><INDENT>properties['<STR_LIT>'] = True<EOL><DEDENT>elif re.search(r'<STR_LIT:/>', pattern):<EOL><INDENT>properties['<STR_LIT>'] = True<EOL><DEDENT>return '<STR_LIT>'.format(pattern)<EOL><DEDENT>pattern_string = re.sub(self.parameter_pattern, add_parameter, uri)<EOL>pattern = re.compile(r'<STR_LIT>'.format(pattern_string))<EOL>def merge_route(route, methods, handler):<EOL><INDENT>if not route.methods or not methods:<EOL><INDENT>raise RouteExists(<EOL>"<STR_LIT>".format(uri))<EOL><DEDENT>elif route.methods.intersection(methods):<EOL><INDENT>duplicated = methods.intersection(route.methods)<EOL>raise RouteExists(<EOL>"<STR_LIT>".format(<EOL>uri, '<STR_LIT:U+002C>'.join(list(duplicated))))<EOL><DEDENT>if isinstance(route.handler, self._composition_view_class):<EOL><INDENT>view = route.handler<EOL><DEDENT>else:<EOL><INDENT>view = self._composition_view_class()<EOL>view.add(route.methods, route.handler)<EOL><DEDENT>view.add(methods, handler)<EOL>route = route._replace(<EOL>handler=view, methods=methods.union(route.methods))<EOL>return route<EOL><DEDENT>if parameters:<EOL><INDENT>if properties['<STR_LIT>']:<EOL><INDENT>routes_to_check = self.routes_always_check<EOL>ndx, route = self.check_dynamic_route_exists(<EOL>pattern, routes_to_check)<EOL><DEDENT>else:<EOL><INDENT>routes_to_check = self.routes_dynamic[url_hash(uri)]<EOL>ndx, route = self.check_dynamic_route_exists(<EOL>pattern, routes_to_check)<EOL><DEDENT>if ndx != -<NUM_LIT:1>:<EOL><INDENT>routes_to_check.pop(ndx)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>route = self.routes_all.get(uri)<EOL><DEDENT>if route:<EOL><INDENT>route = merge_route(route, methods, handler)<EOL><DEDENT>else:<EOL><INDENT>if hasattr(handler, '<STR_LIT>'):<EOL><INDENT>handler_name = '<STR_LIT>'.format(<EOL>handler.__blueprintname__, handler.__name__)<EOL><DEDENT>else:<EOL><INDENT>handler_name = getattr(handler, '<STR_LIT>', None)<EOL><DEDENT>route = Route(<EOL>handler=handler, methods=methods, pattern=pattern,<EOL>parameters=parameters, name=handler_name, uri=uri)<EOL><DEDENT>self.routes_all[uri] = route<EOL>if properties['<STR_LIT>']:<EOL><INDENT>self.routes_always_check.append(route)<EOL><DEDENT>elif parameters:<EOL><INDENT>self.routes_dynamic[url_hash(uri)].append(route)<EOL><DEDENT>else:<EOL><INDENT>self.routes_static[uri] = route<EOL><DEDENT>
Add a handler to the route list

        :param uri: path to match
        :param methods: sequence of accepted method names. If none are
            provided, any method is allowed
        :param handler: request handler function.
            When executed, it should provide a response object.
        :return: Nothing