def route(*args):
    def _validate_route(route):
        if not isinstance(route, six.string_types):
            raise TypeError('%s must be a string' % route)
        if route in ('.', '..') or not re.match(
            '^[0-9a-zA-Z-_$\(\)\.~!,;:*+@=]+$', route
        ):
            raise ValueError(
                '%s must be a valid path segment.  Keep in mind '
                'that path segments should not contain path separators '
                '(e.g., /) ' % route
            )
    if len(args) == 2:
        route, handler = args
        if ismethod(handler):
            handler = handler.__func__
        if not iscontroller(handler):
            raise TypeError(
                '%s must be a callable decorated with @pecan.expose' % handler
            )
        obj, attr, value = handler, 'custom_route', route
        if handler.__name__ in ('_lookup', '_default', '_route'):
            raise ValueError(
                '%s is a special method in pecan and cannot be used in '
                'combination with custom path segments.' % handler.__name__
            )
    elif len(args) == 3:
        _, route, handler = args
        obj, attr, value = args
        if hasattr(obj, attr):
            raise RuntimeError(
                (
                    "%(module)s.%(class)s already has an "
                    "existing attribute named \"%(route)s\"." % {
                        'module': obj.__module__,
                        'class': obj.__name__,
                        'route': attr
                    }
                ),
            )
    else:
        raise TypeError(
            'pecan.route should be called in the format '
            'route(ParentController, "path-segment", SubController())'
        )
    _validate_route(route)
    setattr(obj, attr, value)