plain 0.21.5__py3-none-any.whl → 0.22.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
plain/urls/routers.py ADDED
@@ -0,0 +1,112 @@
1
+ import re
2
+ from abc import ABC
3
+ from types import ModuleType
4
+ from typing import TYPE_CHECKING
5
+
6
+ from plain.exceptions import ImproperlyConfigured
7
+
8
+ from .patterns import RegexPattern, RoutePattern, URLPattern
9
+ from .resolvers import (
10
+ URLResolver,
11
+ )
12
+
13
+ if TYPE_CHECKING:
14
+ from plain.views import View
15
+
16
+
17
+ class RouterBase(ABC):
18
+ namespace: str = ""
19
+ urls: list # Required
20
+
21
+
22
+ class RoutersRegistry:
23
+ """Keep track of all the Routers that are explicitly registered in packages."""
24
+
25
+ def __init__(self):
26
+ self._routers = {}
27
+
28
+ def register_router(self, router_class):
29
+ router_module_name = router_class.__module__
30
+ self._routers[router_module_name] = router_class
31
+ return router_class
32
+
33
+ def get_module_router(self, module):
34
+ if isinstance(module, str):
35
+ module_name = module
36
+ else:
37
+ module_name = module.__name__
38
+
39
+ try:
40
+ return self._routers[module_name]
41
+ except KeyError as e:
42
+ registered_routers = ", ".join(self._routers.keys()) or "None"
43
+ raise ImproperlyConfigured(
44
+ f"Router {module_name} is not registered with the resolver. Use @register_router on the Router class in urls.py.\n\nRegistered routers: {registered_routers}"
45
+ ) from e
46
+
47
+
48
+ def include(
49
+ route: str | re.Pattern, module_or_urls: list | tuple | str | ModuleType
50
+ ) -> URLResolver:
51
+ """
52
+ Include URLs from another module or a nested list of URL patterns.
53
+ """
54
+ if isinstance(route, str):
55
+ pattern = RoutePattern(route, is_endpoint=False)
56
+ elif isinstance(route, re.Pattern):
57
+ pattern = RegexPattern(route.pattern, is_endpoint=False)
58
+ else:
59
+ raise TypeError("include() route must be a string or regex")
60
+
61
+ if isinstance(module_or_urls, list | tuple):
62
+ # We were given an explicit list of sub-patterns,
63
+ # so we generate a router for it
64
+ class _IncludeRouter(RouterBase):
65
+ urls = module_or_urls
66
+
67
+ return URLResolver(pattern=pattern, router_class=_IncludeRouter)
68
+ else:
69
+ # We were given a module, so we need to look up the router for that module
70
+ module = module_or_urls
71
+ router_class = routers_registry.get_module_router(module)
72
+
73
+ return URLResolver(
74
+ pattern=pattern,
75
+ router_class=router_class,
76
+ )
77
+
78
+
79
+ def path(route: str | re.Pattern, view: "View", *, name: str = "") -> URLPattern:
80
+ """
81
+ Standard URL with a view.
82
+ """
83
+ from plain.views import View
84
+
85
+ if isinstance(route, str):
86
+ pattern = RoutePattern(route, name=name, is_endpoint=True)
87
+ elif isinstance(route, re.Pattern):
88
+ pattern = RegexPattern(route.pattern, name=name, is_endpoint=True)
89
+ else:
90
+ raise TypeError("path() route must be a string or regex")
91
+
92
+ # You can't pass a View() instance to path()
93
+ if isinstance(view, View):
94
+ view_cls_name = view.__class__.__name__
95
+ raise TypeError(
96
+ f"view must be a callable, pass {view_cls_name} or {view_cls_name}.as_view(*args, **kwargs), not "
97
+ f"{view_cls_name}()."
98
+ )
99
+
100
+ # You typically pass a View class and we call as_view() for you
101
+ if issubclass(view, View):
102
+ return URLPattern(pattern=pattern, view=view.as_view(), name=name)
103
+
104
+ # If you called View.as_view() yourself (or technically any callable)
105
+ if callable(view):
106
+ return URLPattern(pattern=pattern, view=view, name=name)
107
+
108
+ raise TypeError("view must be a View class or View.as_view()")
109
+
110
+
111
+ routers_registry = RoutersRegistry()
112
+ register_router = routers_registry.register_router
@@ -1,37 +1,18 @@
1
- from threading import local
2
-
3
1
  from plain.utils.functional import lazy
4
2
 
5
- from .exceptions import NoReverseMatch, Resolver404
6
- from .resolvers import _get_cached_resolver, get_ns_resolver, get_resolver
7
-
8
- # Overridden URLconfs for each thread are stored here.
9
- _urlconfs = local()
10
-
11
-
12
- def resolve(path, urlconf=None):
13
- if urlconf is None:
14
- urlconf = get_urlconf()
15
- return get_resolver(urlconf).resolve(path)
3
+ from .exceptions import NoReverseMatch
4
+ from .resolvers import get_ns_resolver, get_resolver
16
5
 
17
6
 
18
- def reverse(viewname, urlconf=None, args=None, kwargs=None, using_namespace=None):
19
- if urlconf is None:
20
- urlconf = get_urlconf()
21
- resolver = get_resolver(urlconf)
22
- args = args or []
23
- kwargs = kwargs or {}
7
+ def reverse(viewname, *args, **kwargs):
8
+ resolver = get_resolver()
24
9
 
25
10
  if not isinstance(viewname, str):
26
11
  view = viewname
27
12
  else:
28
13
  *path, view = viewname.split(":")
29
14
 
30
- if using_namespace:
31
- current_path = using_namespace.split(":")
32
- current_path.reverse()
33
- else:
34
- current_path = None
15
+ current_path = None
35
16
 
36
17
  resolved_path = []
37
18
  ns_pattern = ""
@@ -79,40 +60,3 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, using_namespace=None
79
60
 
80
61
 
81
62
  reverse_lazy = lazy(reverse, str)
82
-
83
-
84
- def clear_url_caches():
85
- _get_cached_resolver.cache_clear()
86
- get_ns_resolver.cache_clear()
87
-
88
-
89
- def set_urlconf(urlconf_name):
90
- """
91
- Set the URLconf for the current thread (overriding the default one in
92
- settings). If urlconf_name is None, revert back to the default.
93
- """
94
- if urlconf_name:
95
- _urlconfs.value = urlconf_name
96
- else:
97
- if hasattr(_urlconfs, "value"):
98
- del _urlconfs.value
99
-
100
-
101
- def get_urlconf(default=None):
102
- """
103
- Return the root URLconf to use for the current thread if it has been
104
- changed from the default one.
105
- """
106
- return getattr(_urlconfs, "value", default)
107
-
108
-
109
- def is_valid_path(path, urlconf=None):
110
- """
111
- Return the ResolverMatch if the given path resolves against the default URL
112
- resolver, False otherwise. This is a convenience method to make working
113
- with "is this a match?" cases easier, avoiding try...except blocks.
114
- """
115
- try:
116
- return resolve(path, urlconf)
117
- except Resolver404:
118
- return False
plain/utils/functional.py CHANGED
@@ -18,8 +18,7 @@ class cached_property:
18
18
  @staticmethod
19
19
  def func(instance):
20
20
  raise TypeError(
21
- "Cannot use cached_property instance without calling "
22
- "__set_name__() on it."
21
+ "Cannot use cached_property instance without calling __set_name__() on it."
23
22
  )
24
23
 
25
24
  def __init__(self, func):
plain/views/redirect.py CHANGED
@@ -29,7 +29,7 @@ class RedirectView(View):
29
29
  if self.url:
30
30
  url = self.url % self.url_kwargs
31
31
  elif self.pattern_name:
32
- url = reverse(self.pattern_name, args=self.url_args, kwargs=self.url_kwargs)
32
+ url = reverse(self.pattern_name, *self.url_args, **self.url_kwargs)
33
33
  else:
34
34
  return None
35
35
 
plain/views/templates.py CHANGED
@@ -22,7 +22,7 @@ csrf_token_lazy = lazy(get_token, str)
22
22
 
23
23
  class TemplateView(View):
24
24
  """
25
- Render a template. Pass keyword arguments from the URLconf to the context.
25
+ Render a template.
26
26
  """
27
27
 
28
28
  template_name: str | None = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.21.5
3
+ Version: 0.22.1
4
4
  Summary: A web framework for building products with Python.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-File: LICENSE
@@ -12,11 +12,11 @@ plain/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  plain/assets/compile.py,sha256=Qg-rMWykij_Jheq4THrPFWlmYv07ihHzWiNsD815HYE,3336
13
13
  plain/assets/finders.py,sha256=wMa0GUi4S5SUXKcWSqEesMgU4NbXXDrC4SMJwDakwNc,1215
14
14
  plain/assets/fingerprints.py,sha256=1NKAnnXVlncY5iimXztr0NL3RIjBKsNlZRIe6nmItJc,931
15
- plain/assets/urls.py,sha256=ZTIoM1Zq35JaXZ3wFhXhfGa7VoITDNlH9i5RS0R5xow,933
16
- plain/assets/views.py,sha256=WaWLUjLGXY60gJV0RK34PNrEssJU-N0dFoISHt4nyFU,9271
15
+ plain/assets/urls.py,sha256=lW7VzKNzTKY11JqbszhJQ1Yy0HtljZlsHDnnkTPdLOM,992
16
+ plain/assets/views.py,sha256=z7noLzoelGw_8-MXcvGKjXs9KZ43Tivmy2TIfnZIpgw,9253
17
17
  plain/cli/README.md,sha256=TvWCnNwb1rNthPzJglCRMKacN5H_RLeEjYBMe62Uz4M,2461
18
18
  plain/cli/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
19
- plain/cli/cli.py,sha256=UNWIVnx2r2qn-eZejh2F_UA9C80HDNFysDd1rAWh2K4,14593
19
+ plain/cli/cli.py,sha256=0iHzlXWQTLxWxqxGV4f4K9ABT7s5q5gzSqoNzj0XuKg,18383
20
20
  plain/cli/formatting.py,sha256=1hZH13y1qwHcU2K2_Na388nw9uvoeQH8LrWL-O9h8Yc,2207
21
21
  plain/cli/packages.py,sha256=TiLirp0ccj5K96jOfp_pS18rOnk1aQS9ckiTi27aRwE,2740
22
22
  plain/cli/print.py,sha256=XraUYrgODOJquIiEv78wSCYGRBplHXtXSS9QtFG5hqY,217
@@ -34,7 +34,7 @@ plain/http/README.md,sha256=HjEtoAhn14OoMdgb-wK-uc8No7C4d4gZUhzseOp7Fg4,236
34
34
  plain/http/__init__.py,sha256=DIsDRbBsCGa4qZgq-fUuQS0kkxfbTU_3KpIM9VvH04w,1067
35
35
  plain/http/cookie.py,sha256=11FnSG3Plo6T3jZDbPoCw7SKh9ExdBio3pTmIO03URg,597
36
36
  plain/http/multipartparser.py,sha256=k6BhpilFENQQ1cuGix6aa-jGwbhBVms2A2O01-s3_4c,27304
37
- plain/http/request.py,sha256=sqE83ZaB1P2i7iEUQ6d-K_6X4xhpdRdsPiTVraiDoNU,25984
37
+ plain/http/request.py,sha256=Kp0q-1obg7ZUJBz7iuyHwPmNMnssZmoIdLp8ylxJNAo,25965
38
38
  plain/http/response.py,sha256=RR2sUG-ONWKWcZyIbztjWvtFyh0cR-CoxQvnWOyN0io,23619
39
39
  plain/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  plain/internal/files/README.md,sha256=kMux-NU5qiH0o1K8IajYQT8VjrYl_jLk9LkGG_kGuSc,45
@@ -47,13 +47,13 @@ plain/internal/files/uploadedfile.py,sha256=JRB7T3quQjg-1y3l1ASPxywtSQZhaeMc45uF
47
47
  plain/internal/files/uploadhandler.py,sha256=eEnd5onstypjHYtg367PnVWwCaF1kAPlLPSV7goIf_E,7198
48
48
  plain/internal/files/utils.py,sha256=xN4HTJXDRdcoNyrL1dFd528MBwodRlHZM8DGTD_oBIg,2646
49
49
  plain/internal/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
- plain/internal/handlers/base.py,sha256=M9P3f5JaMmGxzxW7b6p72zAHxFXHuNl57aRcmRCMoWo,4609
51
- plain/internal/handlers/exception.py,sha256=DH9gh1FyqgetFpMaB8yLIVE6phBTVPKQLA1GIn9MOeI,4555
50
+ plain/internal/handlers/base.py,sha256=oRKni79ATI_u7sywGFExrzKvP5dpJTqIp1m521A90Ew,4169
51
+ plain/internal/handlers/exception.py,sha256=rv8shMlTJdIhTm99VacILIiu5JRcmtumg8yWuy7GYto,4592
52
52
  plain/internal/handlers/wsgi.py,sha256=estA1QKHTk3ZqziWxenHsw5UO2cwPp3Zr0XjkDeM5TY,7561
53
53
  plain/internal/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  plain/internal/middleware/headers.py,sha256=ENIW1Gwat54hv-ejgp2R8QTZm-PlaI7k44WU01YQrNk,964
55
55
  plain/internal/middleware/https.py,sha256=XpuQK8HicYX1jNanQHqNgyQ9rqe4NLUOZO3ZzKdsP8k,1203
56
- plain/internal/middleware/slash.py,sha256=1rZsSSzXAA-vBb-dc2RlZaKW9gTT8YM8fJzwYGL4swA,2575
56
+ plain/internal/middleware/slash.py,sha256=FMU8b9w0NSx4eJs9Y7Ew6RAoSTbUqe2oOM68kg3wOng,2817
57
57
  plain/logs/README.md,sha256=H6uVXdInYlasq0Z1WnhWnPmNwYQoZ1MSLPDQ4ZE7u4A,492
58
58
  plain/logs/__init__.py,sha256=rASvo4qFBDIHfkACmGLNGa6lRGbG9PbNjW6FmBt95ys,168
59
59
  plain/logs/configure.py,sha256=6mV7d1IxkDYT3VBz61qhIj0Esuy5l5QdQfsHaGCfI6w,1063
@@ -62,17 +62,17 @@ plain/logs/utils.py,sha256=9UzdCCQXJinGDs71Ngw297mlWkhgZStSd67ya4NOW98,1257
62
62
  plain/packages/README.md,sha256=Vq1Nw3mmEmZ2IriQavuVi4BjcQC2nb8k7YIbnm8QjIg,799
63
63
  plain/packages/__init__.py,sha256=DnHN1wwHXiXib4Y9BV__x9WrbUaTovoTIxW-tVyScTU,106
64
64
  plain/packages/config.py,sha256=6j6Y9Uw4Lbye1M7LVgOhL4rAMkSSkleTzHQU9JRBW7k,11070
65
- plain/packages/registry.py,sha256=WlCGssmtjPss4KhDAyXyEkIUlKtzQcu17c45iqM2bbA,17920
65
+ plain/packages/registry.py,sha256=YMYGGrMWPoj4Bg_MXDVNnnoqOAufG_IBT24DB-twAgw,14860
66
66
  plain/preflight/README.md,sha256=-PKVd0RBMh4ROiMkegPS2PgvT1Kq9qqN1KfNkmUSdFc,177
67
67
  plain/preflight/__init__.py,sha256=H-TNRvaddPtOGmv4RXoc1fxDV1AOb7_K3u7ECF8mV58,607
68
68
  plain/preflight/files.py,sha256=wbHCNgps7o1c1zQNBd8FDCaVaqX90UwuvLgEQ_DbUpY,510
69
69
  plain/preflight/messages.py,sha256=HwatjA6MRFfzFAnSOa_uAw1Pvk_CLuNfW3IYi71_1Mk,2322
70
70
  plain/preflight/registry.py,sha256=7s7f_iEwURzv-Ye515P5lJWcHltd5Ca2fsX1Wpbf1wQ,2306
71
71
  plain/preflight/security.py,sha256=sNpv5AHobPcaO48cOUGRNe2EjusTducjY8vyShR8EhI,2645
72
- plain/preflight/urls.py,sha256=VjK_B6tg22ugPO5VLY9gBCkDPW0mhcRr-64iv_12zCw,3003
72
+ plain/preflight/urls.py,sha256=q3ikavMB8ZFMzzm_JOnm1YKwSONgaHjH4Is4-4mmTKM,3001
73
73
  plain/runtime/README.md,sha256=Q8VVO7JRGuYrDxzuYL6ptoilhclbecxKzpRXKgbWGkU,2061
74
74
  plain/runtime/__init__.py,sha256=ZfypqlhtbWUoJ84vLW4aKgpx2HsdtdJfDZnbbZw6kLE,1510
75
- plain/runtime/global_settings.py,sha256=T871IxXVARnpvxLOGh2YT0PTmafxcH18TuPUNNTE8vo,5499
75
+ plain/runtime/global_settings.py,sha256=SfOhwzpZe2zpNqSpdx3hHgCN89xdbW9KJVR4KJfS_Gk,5498
76
76
  plain/runtime/user_settings.py,sha256=r6uQ-h0QxX3gSB_toJJekEbSikXXdNSb8ykUtwGTpdY,11280
77
77
  plain/signals/README.md,sha256=cd3tKEgH-xc88CUWyDxl4-qv-HBXx8VT32BXVwA5azA,230
78
78
  plain/signals/__init__.py,sha256=eAs0kLqptuP6I31dWXeAqRNji3svplpAV4Ez6ktjwXM,131
@@ -87,17 +87,18 @@ plain/templates/jinja/__init__.py,sha256=jGjtygVB5Bwknpd3u_pBSrtUSGlFkYo6MDo0E3I
87
87
  plain/templates/jinja/environments.py,sha256=T5e8rjVteN3-6IWCXNRsvPgMe0OVvTkX-r6_Q9gxhv8,2046
88
88
  plain/templates/jinja/extensions.py,sha256=AEmmmHDbdRW8fhjYDzq9eSSNbp9WHsXenD8tPthjc0s,1351
89
89
  plain/templates/jinja/filters.py,sha256=3KJKKbxcv9dLzUDWPcaa88k3NU2m1GG3iMIgFhzXrBA,860
90
- plain/templates/jinja/globals.py,sha256=qhvQuikkRkOTpHSW5FwdsvoViJNlRgHq3-O7ZyeajsE,669
90
+ plain/templates/jinja/globals.py,sha256=xx3sQBn0Hkqp9jM0fZDlCM5_35C23FrZL6jKEifL77k,498
91
91
  plain/test/README.md,sha256=Zso3Ir7a8vQerzKB6egjROQWkpveLAbscn7VTROPAiU,37
92
92
  plain/test/__init__.py,sha256=rXe88Y602NP8DBnReSyXb7dUzKoWweLuT43j-qwOUl4,138
93
- plain/test/client.py,sha256=wqypz5iIu28ubaEqMdx4wO7n6IPcBRkgkVXeEdr_qZg,31351
93
+ plain/test/client.py,sha256=36Cir1KbrNEhza-5FTgdwxe1iZ5zaEDtESrqcnyndnY,31318
94
94
  plain/urls/README.md,sha256=pWnCvgYkWN7rG7hSyBOtX4ZUP3iO7FhqM6lvwwYll6c,33
95
- plain/urls/__init__.py,sha256=3UzwIufXjIks2K_X_Vms2MV19IqvyPLrXUeHU3WP47c,753
96
- plain/urls/base.py,sha256=Q1TzI5WvqYkN1U81fDom1q-AID4dXbszEMF6wAeTAI0,3717
97
- plain/urls/conf.py,sha256=3R2dCr4iryMPXgUZqESZvqrhTLa5I7PzNY98SuCYYec,3491
95
+ plain/urls/__init__.py,sha256=XF-W2GqLMA4bHbDRKnpZ7tiUtJ-BhWN-yAzw4nNnHdc,590
98
96
  plain/urls/converters.py,sha256=s2JZVOdzZC16lgobsI93hygcdH5L0Kj4742WEkXsVcs,1193
99
97
  plain/urls/exceptions.py,sha256=q4iPh3Aa-zHbA-tw8v6WyX1J1n5WdAady2xvxFuyXB0,114
100
- plain/urls/resolvers.py,sha256=Fb2F1cdTxKDn0ZvNX81zHBglZs_aKMgnFuSIJVxNiUk,27508
98
+ plain/urls/patterns.py,sha256=bU_xfhZbKMSgRG9OJ8w_NSuYRm_9zGnqoz_WY44fhUk,9358
99
+ plain/urls/resolvers.py,sha256=T_N7hZ2VrWWpLNkMbzpNcPK8OJb4yPt6QoK_qIls4D8,15592
100
+ plain/urls/routers.py,sha256=0vwzL5udLfQDwFfE4_3lzRVq0Lsx9RcDF4rnnEiJJ1w,3613
101
+ plain/urls/utils.py,sha256=WiGq6hHI-5DLFOxCQTAZ2qm0J-UdGosLcjuxlfK6_Tg,2137
101
102
  plain/utils/README.md,sha256=Bf5OG-MkOJDz_U8RGVreDfAI4M4nnPaLtk-LdinxHSc,99
102
103
  plain/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
104
  plain/utils/_os.py,sha256=oqfiKZRbmHwwWSZP36SIajQnFDbImbB6gcyK0idAGl4,1988
@@ -110,11 +111,10 @@ plain/utils/dateparse.py,sha256=u9_tF85YteXSjW9KQzNg_pcCEFDZS3EGorCddcWU0vE,5351
110
111
  plain/utils/dates.py,sha256=hSDKz8eIb3W5QjmGiklFZZELB0inYXsfiRUy49Cx-2Q,1226
111
112
  plain/utils/deconstruct.py,sha256=7NwEFIDCiadAArUBFmiErzDgfIgDWeKqqQFDXwSgQoQ,1830
112
113
  plain/utils/decorators.py,sha256=mLHOo2jLdvYRo2z8lkeVn2vQErlj7xC6XoLwZBYf_z8,358
113
- plain/utils/deprecation.py,sha256=qtj33kHEmJU7mGSrNcKidZsMo5W8MN-zrXzUq3aVVy8,131
114
114
  plain/utils/duration.py,sha256=l0Gc41-DeyyAmpdy2XG-YO5UKxMf1NDpWIlQuD5hAn0,1162
115
115
  plain/utils/email.py,sha256=puRTBVuz44YvpnqV3LT4nNIKqdqfY3L8zbDJIkqHk2Y,328
116
116
  plain/utils/encoding.py,sha256=z8c7HxYW6wQiE4csx5Ui3WvzgbDzLGXY2aCP04_GZd4,7900
117
- plain/utils/functional.py,sha256=7Z1LuPpS1y0ignX7QDzPq6zJqDZdCf_rFYLRR1rTSG0,14806
117
+ plain/utils/functional.py,sha256=Xf51mt5bB8zehR8pTRVnRfV21vJ4n1IGpcwj88SSsUA,14791
118
118
  plain/utils/hashable.py,sha256=uLWobCCh7VcEPJ7xzVGPgigNVuTazYJbyzRzHTCI_wo,739
119
119
  plain/utils/html.py,sha256=K8nJSiNRU54htQOfhezZAYspXaDGN3LjOE3SxmnQml8,13513
120
120
  plain/utils/http.py,sha256=OmnqW_nYUaFN-pAEwjTEh9AkpfjKGmE51Ge6inNGB10,12710
@@ -136,10 +136,10 @@ plain/views/errors.py,sha256=Y4oGX4Z6D2COKcDEfINvXE1acE8Ad15KwNNWPs5BCfc,967
136
136
  plain/views/exceptions.py,sha256=b4euI49ZUKS9O8AGAcFfiDpstzkRAuuj_uYQXzWNHME,138
137
137
  plain/views/forms.py,sha256=RhlaUcZCkeqokY_fvv-NOS-kgZAG4XhDLOPbf9K_Zlc,2691
138
138
  plain/views/objects.py,sha256=g5Lzno0Zsv0K449UpcCtxwCoO7WMRAWqKlxxV2V0_qg,8263
139
- plain/views/redirect.py,sha256=KLnlktzK6ZNMTlaEiZpMKQMEP5zeTgGLJ9BIkIJfwBo,1733
140
- plain/views/templates.py,sha256=nF9CcdhhjAyp3LB0RrSYnBaHpHzMfPSw719RCdcXk7o,2007
141
- plain-0.21.5.dist-info/METADATA,sha256=0oF_0zeaLk49ni4P08nQzXF_3biuj_9pLd2TO68BLeA,319
142
- plain-0.21.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
143
- plain-0.21.5.dist-info/entry_points.txt,sha256=DHHprvufgd7xypiBiqMANYRnpJ9xPPYhYbnPGwOkWqE,40
144
- plain-0.21.5.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
145
- plain-0.21.5.dist-info/RECORD,,
139
+ plain/views/redirect.py,sha256=9zHZgKvtSkdrMX9KmsRM8hJTPmBktxhc4d8OitbuniI,1724
140
+ plain/views/templates.py,sha256=cBkFNCSXgVi8cMqQbhsqJ4M_rIQYVl8cUvq9qu4YIes,1951
141
+ plain-0.22.1.dist-info/METADATA,sha256=lbcAVRTvoSbCtA3Nlt-ShyzQV1UOhb2bk_FSDKL5pS4,319
142
+ plain-0.22.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
143
+ plain-0.22.1.dist-info/entry_points.txt,sha256=DHHprvufgd7xypiBiqMANYRnpJ9xPPYhYbnPGwOkWqE,40
144
+ plain-0.22.1.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
145
+ plain-0.22.1.dist-info/RECORD,,
plain/urls/conf.py DELETED
@@ -1,95 +0,0 @@
1
- """Functions for use in URLsconfs."""
2
-
3
- from functools import partial
4
-
5
- from plain.exceptions import ImproperlyConfigured
6
-
7
- from .resolvers import (
8
- RegexPattern,
9
- RoutePattern,
10
- URLPattern,
11
- URLResolver,
12
- )
13
-
14
-
15
- def include(arg, namespace=None):
16
- default_namespace = None
17
- if isinstance(arg, tuple):
18
- # Callable returning a namespace hint.
19
- try:
20
- urlconf_module, default_namespace = arg
21
- except ValueError:
22
- if namespace:
23
- raise ImproperlyConfigured(
24
- "Cannot override the namespace for a dynamic module that "
25
- "provides a namespace."
26
- )
27
- raise ImproperlyConfigured(
28
- "Passing a %d-tuple to include() is not supported. Pass a " # noqa: UP031
29
- "2-tuple containing the list of patterns and default_namespace, and "
30
- "provide the namespace argument to include() instead." % len(arg)
31
- )
32
- else:
33
- # No namespace hint - use manually provided namespace.
34
- urlconf_module = arg
35
-
36
- patterns = getattr(urlconf_module, "urlpatterns", urlconf_module)
37
- default_namespace = getattr(urlconf_module, "default_namespace", default_namespace)
38
- if namespace and not default_namespace:
39
- raise ImproperlyConfigured(
40
- "Specifying a namespace in include() without providing an default_namespace "
41
- "is not supported. Set the default_namespace attribute in the included "
42
- "module, or pass a 2-tuple containing the list of patterns and "
43
- "default_namespace instead.",
44
- )
45
- namespace = namespace or default_namespace
46
- # Make sure the patterns can be iterated through (without this, some
47
- # testcases will break).
48
- if isinstance(patterns, list | tuple):
49
- for url_pattern in patterns:
50
- getattr(url_pattern, "pattern", None)
51
- return (urlconf_module, default_namespace, namespace)
52
-
53
-
54
- def _path(route, view, kwargs=None, name=None, Pattern=None):
55
- from plain.views import View
56
-
57
- if kwargs is not None and not isinstance(kwargs, dict):
58
- raise TypeError(
59
- f"kwargs argument must be a dict, but got {kwargs.__class__.__name__}."
60
- )
61
-
62
- if isinstance(view, list | tuple):
63
- # For include(...) processing.
64
- pattern = Pattern(route, is_endpoint=False)
65
- urlconf_module, default_namespace, namespace = view
66
- return URLResolver(
67
- pattern,
68
- urlconf_module,
69
- kwargs,
70
- default_namespace=default_namespace,
71
- namespace=namespace,
72
- )
73
-
74
- if isinstance(view, View):
75
- view_cls_name = view.__class__.__name__
76
- raise TypeError(
77
- f"view must be a callable, pass {view_cls_name} or {view_cls_name}.as_view(*args, **kwargs), not "
78
- f"{view_cls_name}()."
79
- )
80
-
81
- # Automatically call view.as_view() for class-based views
82
- if as_view := getattr(view, "as_view", None):
83
- pattern = Pattern(route, name=name, is_endpoint=True)
84
- return URLPattern(pattern, as_view(), kwargs, name)
85
-
86
- # Function-based views or view_class.as_view() usage
87
- if callable(view):
88
- pattern = Pattern(route, name=name, is_endpoint=True)
89
- return URLPattern(pattern, view, kwargs, name)
90
-
91
- raise TypeError("view must be a callable or a list/tuple in the case of include().")
92
-
93
-
94
- path = partial(_path, Pattern=RoutePattern)
95
- re_path = partial(_path, Pattern=RegexPattern)
@@ -1,6 +0,0 @@
1
- class RemovedInDjango51Warning(DeprecationWarning):
2
- pass
3
-
4
-
5
- class RemovedInDjango60Warning(PendingDeprecationWarning):
6
- pass
File without changes