Coverage for /Users/davegaeddert/Development/dropseed/plain/plain/plain/urls/conf.py: 67%

1"""Functions for use in URLsconfs."""

2 from functools import partial

3

4 from plain.exceptions import ImproperlyConfigured

5

6 from .resolvers import (

7 RegexPattern,

8 RoutePattern,

9 URLPattern,

10 URLResolver,

11)

12

13

14 def include(arg, namespace=None):

15 default_namespace = None

16 if isinstance(arg, tuple):

17 # Callable returning a namespace hint.

18 try:

19 urlconf_module, default_namespace = arg

20 except ValueError:

21 if namespace:

22 raise ImproperlyConfigured(

23 "Cannot override the namespace for a dynamic module that "

24 "provides a namespace."

25 )

26 raise ImproperlyConfigured(

27 "Passing a %d-tuple to include() is not supported. Pass a "

28 "2-tuple containing the list of patterns and default_namespace, and "

29 "provide the namespace argument to include() instead." % len(arg)

30 )

31 else:

32 # No namespace hint - use manually provided namespace.

33 urlconf_module = arg

34

35 patterns = getattr(urlconf_module, "urlpatterns", urlconf_module)

36 default_namespace = getattr(urlconf_module, "default_namespace", default_namespace)

37 if namespace and not default_namespace:

38 raise ImproperlyConfigured(

39 "Specifying a namespace in include() without providing an default_namespace "

40 "is not supported. Set the default_namespace attribute in the included "

41 "module, or pass a 2-tuple containing the list of patterns and "

42 "default_namespace instead.",

43 )

44 namespace = namespace or default_namespace

45 # Make sure the patterns can be iterated through (without this, some

46 # testcases will break).

47 if isinstance(patterns, list | tuple):

48 for url_pattern in patterns:

49 getattr(url_pattern, "pattern", None)

50 return (urlconf_module, default_namespace, namespace)

51

52

53 def _path(route, view, kwargs=None, name=None, Pattern=None):

54 from plain.views import View

55

56 if kwargs is not None and not isinstance(kwargs, dict):

57 raise TypeError(

58 f"kwargs argument must be a dict, but got {kwargs.__class__.__name__}."

59 )

60

61 if isinstance(view, list | tuple):

62 # For include(...) processing.

63 pattern = Pattern(route, is_endpoint=False)

64 urlconf_module, default_namespace, namespace = view

65 return URLResolver(

66 pattern,

67 urlconf_module,

68 kwargs,

69 default_namespace=default_namespace,

70 namespace=namespace,

71 )

72

73 if isinstance(view, View):

74 view_cls_name = view.__class__.__name__

75 raise TypeError(

76 f"view must be a callable, pass {view_cls_name} or {view_cls_name}.as_view(*args, **kwargs), not "

77 f"{view_cls_name}()."

78 )

79

80 # Automatically call view.as_view() for class-based views

81 if as_view := getattr(view, "as_view", None):

82 pattern = Pattern(route, name=name, is_endpoint=True)

83 return URLPattern(pattern, as_view(), kwargs, name)

84

85 # Function-based views or view_class.as_view() usage

86 if callable(view):

87 pattern = Pattern(route, name=name, is_endpoint=True)

88 return URLPattern(pattern, view, kwargs, name)

89

90 raise TypeError("view must be a callable or a list/tuple in the case of include().")

91

92

93 path = partial(_path, Pattern=RoutePattern)

94 re_path = partial(_path, Pattern=RegexPattern)