Ejemplo n.º 1
0
    def url_patterns(self):
        # First, add our "positively" flagged URLs, where when the flag
        # matches the defined state, the view is served for the pattern
        # and not the fallback.
        url_patterns = []
        for pattern in super(FlaggedURLResolver, self).url_patterns:
            # Get the fallback view, if there is one, and remove it from
            # the list of fallback patterns.
            fallback = self.fallback
            if isinstance(self.fallback, (list, tuple)):
                fallback = next(
                    (p.callback for p in self.fallback_patterns
                     if p.pattern.describe() == pattern.pattern.describe()),
                    None,
                )

            flag_decorator = flag_check(self.flag_name,
                                        self.state,
                                        fallback=fallback)

            route_pattern = pattern.pattern

            flagged_pattern = URLPattern(
                route_pattern,
                flag_decorator(pattern.callback),
                pattern.default_args,
                pattern.name,
            )

            url_patterns.append(flagged_pattern)

        # Next, add "negatively" flagged URLs, where the flag does not match
        # the defined state, for any remaining fallback patterns that didn't
        # match other url patterns.
        described_patterns = [p.pattern.describe() for p in url_patterns]
        negative_patterns = (p for p in self.fallback_patterns
                             if p.pattern.describe() not in described_patterns)

        for pattern in negative_patterns:
            flag_decorator = flag_check(self.flag_name, not self.state)

            route_pattern = pattern.pattern

            flagged_pattern = URLPattern(
                route_pattern,
                flag_decorator(pattern.callback),
                pattern.default_args,
                pattern.name,
            )

            url_patterns.append(flagged_pattern)

        return url_patterns
def test_process_resolver_wraps_pattern_callbacks(wrap_fun):
    cb1 = Mock()
    pattern1 = URLPattern('', cb1)
    cb2 = Mock()
    pattern2 = URLPattern('', cb2)

    resolver = URLResolver(RegexPattern(r'^$'), [pattern1, pattern2])

    injector = Mock()
    process_resolver(resolver, injector)
    wrap_fun.assert_has_calls([
        call(cb1, injector),
        call(cb2, injector),
    ])
Ejemplo n.º 3
0
def _flagged_path(flag_name, route, view, kwargs=None, name=None,
                  state=True, fallback=None, Pattern=None):
    """ Make a URL depend on the state of a feature flag """
    if callable(view):
        flagged_view = flag_check(flag_name,
                                  state,
                                  fallback=fallback)(view)

        if Pattern:  # pragma: no cover
            route_pattern = Pattern(route, name=name, is_endpoint=True)
        else:  # pragma: no cover
            route_pattern = route

        return URLPattern(route_pattern, flagged_view, kwargs, name)

    elif isinstance(view, (list, tuple)):
        urlconf_module, app_name, namespace = view

        if Pattern:  # pragma: no cover
            route_pattern = Pattern(route, name=name, is_endpoint=True)
        else:  # pragma: no cover
            route_pattern = route

        return FlaggedURLResolver(
            flag_name, route_pattern, urlconf_module, kwargs,
            app_name=app_name, namespace=namespace,
            state=state, fallback=fallback)

    else:
        raise TypeError('view must be a callable')
Ejemplo n.º 4
0
def get_django_admin_dashboard_urls(site):
    import django_sql_dashboard.urls
    from django.urls.resolvers import URLPattern

    urlpatterns = [
        URLPattern(
            pattern=pattern.pattern,
            callback=require_enabled_dashboard(
                site.admin_view(pattern.callback)),
            default_args=pattern.default_args,
            name=pattern.name,
        ) for pattern in django_sql_dashboard.urls.urlpatterns
    ]

    return (urlpatterns, "", "")
Ejemplo n.º 5
0
def recurse_patterns(path,
                     pattern_list,
                     page_id,
                     default_args=None,
                     nested=False):
    """
    Recurse over a list of to-be-hooked patterns for a given path prefix
    """
    newpatterns = []
    for pattern in pattern_list:
        app_pat = getattr(pattern, 'pattern', pattern).regex.pattern
        # make sure we don't get patterns that start with more than one '^'!
        app_pat = app_pat.lstrip('^')
        path = path.lstrip('^')
        regex = r'^%s%s' % (path,
                            app_pat) if not nested else r'^%s' % (app_pat)
        if isinstance(pattern, URLResolver):
            # include default_args
            args = pattern.default_kwargs
            if default_args:
                args.update(default_args)
            # see lines 243 and 236 of urlresolvers.py to understand the next line
            urlconf_module = recurse_patterns(regex,
                                              pattern.url_patterns,
                                              page_id,
                                              args,
                                              nested=True)
            # this is an 'include', recurse!
            regex_pattern = RegexPattern(regex)
            resolver = URLResolver(regex_pattern, urlconf_module,
                                   pattern.default_kwargs, pattern.app_name,
                                   pattern.namespace)
        else:
            # Re-do the URLPattern with the new regular expression
            args = pattern.default_args
            if default_args:
                args.update(default_args)

            regex_pattern = RegexPattern(regex,
                                         name=pattern.name,
                                         is_endpoint=True)
            resolver = URLPattern(regex_pattern, pattern.callback, args,
                                  pattern.name)
        resolver.page_id = page_id
        newpatterns.append(resolver)
    return newpatterns
Ejemplo n.º 6
0
def detype_pattern(pattern):
    """
    return an equivalent pattern that accepts arbitrary values for path parameters.
    de-typing the path will ease determining a matching route without having properly
    formatted dummy values for all path parameters.
    """
    if isinstance(pattern, URLResolver):
        return URLResolver(
            pattern=detype_pattern(pattern.pattern),
            urlconf_name=[detype_pattern(p) for p in pattern.url_patterns],
            default_kwargs=pattern.default_kwargs,
            app_name=pattern.app_name,
            namespace=pattern.namespace,
        )
    elif isinstance(pattern, URLPattern):
        return URLPattern(
            pattern=detype_pattern(pattern.pattern),
            callback=pattern.callback,
            default_args=pattern.default_args,
            name=pattern.name,
        )
    elif isinstance(pattern, RoutePattern):
        return RoutePattern(
            route=re.sub(r'<\w+:(\w+)>', r'<\1>', pattern._route),
            name=pattern.name,
            is_endpoint=pattern._is_endpoint
        )
    elif isinstance(pattern, RegexPattern):
        detyped_regex = pattern._regex
        for name, regex in analyze_named_regex_pattern(pattern._regex).items():
            detyped_regex = detyped_regex.replace(
                f'(?P<{name}>{regex})',
                f'(?P<{name}>[^/]+)',
            )
        return RegexPattern(
            regex=detyped_regex,
            name=pattern.name,
            is_endpoint=pattern._is_endpoint
        )
    else:
        warn(f'unexpected pattern "{pattern}" encountered while simplifying urlpatterns.')
        return pattern
Ejemplo n.º 7
0
def route(path: OpenAPIPath,
          view: ty.Callable,
          kwargs: ty.Optional[ty.Mapping[str, ty.Any]] = None,
          name: ty.Optional[str] = None) -> URLPattern:
    return URLPattern(PathPattern(path), view, default_args=kwargs, name=name)