def _add(self, uri, methods, handler, host=None):
        """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
        """
        if host is not None:
            if isinstance(host, str):
                uri = host + uri
                self.hosts.add(host)

            else:
                if not isinstance(host, Iterable):
                    raise ValueError("Expected either string or Iterable of "
                                     "host strings, not {!r}".format(host))

                for host_ in host:
                    self.add(uri, methods, handler, host_)
                return

        # Dict for faster lookups of if method allowed
        if methods:
            methods = frozenset(methods)

        parameters = []
        properties = {"unhashable": None}

        def add_parameter(match):
            name = match.group(1)
            name, _type, pattern = self.parse_parameter_string(name)

            parameter = Parameter(
                name=name, cast=_type)
            parameters.append(parameter)

            # Mark the whole route as unhashable if it has the hash key in it
            if re.search(r'(^|[^^]){1}/', pattern):
                properties['unhashable'] = True
            # Mark the route as unhashable if it matches the hash key
            elif re.search(r'/', pattern):
                properties['unhashable'] = True

            return '({})'.format(pattern)

        pattern_string = re.sub(self.parameter_pattern, add_parameter, uri)
        pattern = re.compile(r'^{}$'.format(pattern_string))

        def merge_route(route, methods, handler):
            # merge to the existing route when possible.
            if not route.methods or not methods:
                # method-unspecified routes are not mergeable.
                raise RouteExists(
                    "Route already registered: {}".format(uri))
            elif route.methods.intersection(methods):
                # already existing method is not overloadable.
                duplicated = methods.intersection(route.methods)
                raise RouteExists(
                    "Route already registered: {} [{}]".format(
                        uri, ','.join(list(duplicated))))
            if isinstance(route.handler, self._composition_view_class):
                view = route.handler
            else:
                view = self._composition_view_class()
                view.add(route.methods, route.handler)
            view.add(methods, handler)
            route = route._replace(
                handler=view, methods=methods.union(route.methods))
            return route

        if parameters:
            # TODO: This is too complex, we need to reduce the complexity
            if properties['unhashable']:
                routes_to_check = self.routes_always_check
                ndx, route = self.check_dynamic_route_exists(
                    pattern, routes_to_check)
            else:
                routes_to_check = self.routes_dynamic[url_hash(uri)]
                ndx, route = self.check_dynamic_route_exists(
                    pattern, routes_to_check)
            if ndx != -1:
                # Pop the ndx of the route, no dups of the same route
                routes_to_check.pop(ndx)
        else:
            route = self.routes_all.get(uri)

        if route:
            route = merge_route(route, methods, handler)
        else:
            # prefix the handler name with the blueprint name
            # if available
            if hasattr(handler, '__blueprintname__'):
                handler_name = '{}.{}'.format(
                    handler.__blueprintname__, handler.__name__)
            else:
                handler_name = getattr(handler, '__name__', None)

            route = Route(
                handler=handler, methods=methods, pattern=pattern,
                parameters=parameters, name=handler_name, uri=uri)

        self.routes_all[uri] = route
        if properties['unhashable']:
            self.routes_always_check.append(route)
        elif parameters:
            self.routes_dynamic[url_hash(uri)].append(route)
        else:
            self.routes_static[uri] = route
def _add ( self , uri , methods , handler , host = None ) : if host is not None : if isinstance ( host , str ) : uri = host + uri self . hosts . add ( host ) else : if not isinstance ( host , Iterable ) : raise ValueError ( "Expected either string or Iterable of " "host strings, not {!r}" . format ( host ) ) for host_ in host : self . add ( uri , methods , handler , host_ ) return if methods : methods = frozenset ( methods ) parameters = [ ] properties = { "unhashable" : None } def add_parameter ( match ) : name = match . group ( 1 ) name , _type , pattern = self . parse_parameter_string ( name ) parameter = Parameter ( name = name , cast = _type ) parameters . append ( parameter ) if re . search ( r'(^|[^^]){1}/' , pattern ) : properties [ 'unhashable' ] = True elif re . search ( r'/' , pattern ) : properties [ 'unhashable' ] = True return '({})' . format ( pattern ) pattern_string = re . sub ( self . parameter_pattern , add_parameter , uri ) pattern = re . compile ( r'^{}$' . format ( pattern_string ) ) def merge_route ( route , methods , handler ) : if not route . methods or not methods : raise RouteExists ( "Route already registered: {}" . format ( uri ) ) elif route . methods . intersection ( methods ) : duplicated = methods . intersection ( route . methods ) raise RouteExists ( "Route already registered: {} [{}]" . format ( uri , ',' . join ( list ( duplicated ) ) ) ) if isinstance ( route . handler , self . _composition_view_class ) : view = route . handler else : view = self . _composition_view_class ( ) view . add ( route . methods , route . handler ) view . add ( methods , handler ) route = route . _replace ( handler = view , methods = methods . union ( route . methods ) ) return route if parameters : if properties [ 'unhashable' ] : routes_to_check = self . routes_always_check ndx , route = self . check_dynamic_route_exists ( pattern , routes_to_check ) else : routes_to_check = self . routes_dynamic [ url_hash ( uri ) ] ndx , route = self . check_dynamic_route_exists ( pattern , routes_to_check ) if ndx != - 1 : routes_to_check . pop ( ndx ) else : route = self . routes_all . get ( uri ) if route : route = merge_route ( route , methods , handler ) else : if hasattr ( handler , '__blueprintname__' ) : handler_name = '{}.{}' . format ( handler . __blueprintname__ , handler . __name__ ) else : handler_name = getattr ( handler , '__name__' , None ) route = Route ( handler = handler , methods = methods , pattern = pattern , parameters = parameters , name = handler_name , uri = uri ) self . routes_all [ uri ] = route if properties [ 'unhashable' ] : self . routes_always_check . append ( route ) elif parameters : self . routes_dynamic [ url_hash ( uri ) ] . append ( route ) else : self . routes_static [ uri ] = route
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