plain 0.49.0__tar.gz → 0.50.0__tar.gz

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.
Files changed (164) hide show
  1. {plain-0.49.0 → plain-0.50.0}/.gitignore +0 -3
  2. {plain-0.49.0 → plain-0.50.0}/PKG-INFO +1 -1
  3. plain-0.50.0/plain/CHANGELOG.md +33 -0
  4. {plain-0.49.0 → plain-0.50.0}/plain/cli/README.md +1 -1
  5. {plain-0.49.0 → plain-0.50.0}/plain/cli/preflight.py +4 -5
  6. {plain-0.49.0 → plain-0.50.0}/plain/cli/urls.py +8 -2
  7. {plain-0.49.0 → plain-0.50.0}/plain/preflight/registry.py +2 -2
  8. {plain-0.49.0 → plain-0.50.0}/plain/runtime/README.md +13 -20
  9. {plain-0.49.0 → plain-0.50.0}/plain/test/client.py +7 -44
  10. {plain-0.49.0 → plain-0.50.0}/pyproject.toml +1 -1
  11. {plain-0.49.0 → plain-0.50.0}/LICENSE +0 -0
  12. {plain-0.49.0 → plain-0.50.0}/README.md +0 -0
  13. {plain-0.49.0 → plain-0.50.0}/plain/README.md +0 -0
  14. {plain-0.49.0 → plain-0.50.0}/plain/__main__.py +0 -0
  15. {plain-0.49.0 → plain-0.50.0}/plain/assets/README.md +0 -0
  16. {plain-0.49.0 → plain-0.50.0}/plain/assets/__init__.py +0 -0
  17. {plain-0.49.0 → plain-0.50.0}/plain/assets/compile.py +0 -0
  18. {plain-0.49.0 → plain-0.50.0}/plain/assets/finders.py +0 -0
  19. {plain-0.49.0 → plain-0.50.0}/plain/assets/fingerprints.py +0 -0
  20. {plain-0.49.0 → plain-0.50.0}/plain/assets/urls.py +0 -0
  21. {plain-0.49.0 → plain-0.50.0}/plain/assets/views.py +0 -0
  22. {plain-0.49.0 → plain-0.50.0}/plain/chores/README.md +0 -0
  23. {plain-0.49.0 → plain-0.50.0}/plain/chores/__init__.py +0 -0
  24. {plain-0.49.0 → plain-0.50.0}/plain/chores/registry.py +0 -0
  25. {plain-0.49.0 → plain-0.50.0}/plain/cli/__init__.py +0 -0
  26. {plain-0.49.0 → plain-0.50.0}/plain/cli/build.py +0 -0
  27. {plain-0.49.0 → plain-0.50.0}/plain/cli/chores.py +0 -0
  28. {plain-0.49.0 → plain-0.50.0}/plain/cli/core.py +0 -0
  29. {plain-0.49.0 → plain-0.50.0}/plain/cli/docs.py +0 -0
  30. {plain-0.49.0 → plain-0.50.0}/plain/cli/formatting.py +0 -0
  31. {plain-0.49.0 → plain-0.50.0}/plain/cli/help.py +0 -0
  32. {plain-0.49.0 → plain-0.50.0}/plain/cli/print.py +0 -0
  33. {plain-0.49.0 → plain-0.50.0}/plain/cli/registry.py +0 -0
  34. {plain-0.49.0 → plain-0.50.0}/plain/cli/scaffold.py +0 -0
  35. {plain-0.49.0 → plain-0.50.0}/plain/cli/settings.py +0 -0
  36. {plain-0.49.0 → plain-0.50.0}/plain/cli/shell.py +0 -0
  37. {plain-0.49.0 → plain-0.50.0}/plain/cli/startup.py +0 -0
  38. {plain-0.49.0 → plain-0.50.0}/plain/cli/utils.py +0 -0
  39. {plain-0.49.0 → plain-0.50.0}/plain/csrf/README.md +0 -0
  40. {plain-0.49.0 → plain-0.50.0}/plain/csrf/middleware.py +0 -0
  41. {plain-0.49.0 → plain-0.50.0}/plain/csrf/views.py +0 -0
  42. {plain-0.49.0 → plain-0.50.0}/plain/debug.py +0 -0
  43. {plain-0.49.0 → plain-0.50.0}/plain/exceptions.py +0 -0
  44. {plain-0.49.0 → plain-0.50.0}/plain/forms/README.md +0 -0
  45. {plain-0.49.0 → plain-0.50.0}/plain/forms/__init__.py +0 -0
  46. {plain-0.49.0 → plain-0.50.0}/plain/forms/boundfield.py +0 -0
  47. {plain-0.49.0 → plain-0.50.0}/plain/forms/exceptions.py +0 -0
  48. {plain-0.49.0 → plain-0.50.0}/plain/forms/fields.py +0 -0
  49. {plain-0.49.0 → plain-0.50.0}/plain/forms/forms.py +0 -0
  50. {plain-0.49.0 → plain-0.50.0}/plain/http/README.md +0 -0
  51. {plain-0.49.0 → plain-0.50.0}/plain/http/__init__.py +0 -0
  52. {plain-0.49.0 → plain-0.50.0}/plain/http/cookie.py +0 -0
  53. {plain-0.49.0 → plain-0.50.0}/plain/http/multipartparser.py +0 -0
  54. {plain-0.49.0 → plain-0.50.0}/plain/http/request.py +0 -0
  55. {plain-0.49.0 → plain-0.50.0}/plain/http/response.py +0 -0
  56. {plain-0.49.0 → plain-0.50.0}/plain/internal/__init__.py +0 -0
  57. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/__init__.py +0 -0
  58. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/base.py +0 -0
  59. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/locks.py +0 -0
  60. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/move.py +0 -0
  61. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/temp.py +0 -0
  62. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/uploadedfile.py +0 -0
  63. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/uploadhandler.py +0 -0
  64. {plain-0.49.0 → plain-0.50.0}/plain/internal/files/utils.py +0 -0
  65. {plain-0.49.0 → plain-0.50.0}/plain/internal/handlers/__init__.py +0 -0
  66. {plain-0.49.0 → plain-0.50.0}/plain/internal/handlers/base.py +0 -0
  67. {plain-0.49.0 → plain-0.50.0}/plain/internal/handlers/exception.py +0 -0
  68. {plain-0.49.0 → plain-0.50.0}/plain/internal/handlers/wsgi.py +0 -0
  69. {plain-0.49.0 → plain-0.50.0}/plain/internal/middleware/__init__.py +0 -0
  70. {plain-0.49.0 → plain-0.50.0}/plain/internal/middleware/headers.py +0 -0
  71. {plain-0.49.0 → plain-0.50.0}/plain/internal/middleware/https.py +0 -0
  72. {plain-0.49.0 → plain-0.50.0}/plain/internal/middleware/slash.py +0 -0
  73. {plain-0.49.0 → plain-0.50.0}/plain/json.py +0 -0
  74. {plain-0.49.0 → plain-0.50.0}/plain/logs/README.md +0 -0
  75. {plain-0.49.0 → plain-0.50.0}/plain/logs/__init__.py +0 -0
  76. {plain-0.49.0 → plain-0.50.0}/plain/logs/configure.py +0 -0
  77. {plain-0.49.0 → plain-0.50.0}/plain/logs/loggers.py +0 -0
  78. {plain-0.49.0 → plain-0.50.0}/plain/logs/utils.py +0 -0
  79. {plain-0.49.0 → plain-0.50.0}/plain/packages/README.md +0 -0
  80. {plain-0.49.0 → plain-0.50.0}/plain/packages/__init__.py +0 -0
  81. {plain-0.49.0 → plain-0.50.0}/plain/packages/config.py +0 -0
  82. {plain-0.49.0 → plain-0.50.0}/plain/packages/registry.py +0 -0
  83. {plain-0.49.0 → plain-0.50.0}/plain/paginator.py +0 -0
  84. {plain-0.49.0 → plain-0.50.0}/plain/preflight/README.md +0 -0
  85. {plain-0.49.0 → plain-0.50.0}/plain/preflight/__init__.py +0 -0
  86. {plain-0.49.0 → plain-0.50.0}/plain/preflight/files.py +0 -0
  87. {plain-0.49.0 → plain-0.50.0}/plain/preflight/messages.py +0 -0
  88. {plain-0.49.0 → plain-0.50.0}/plain/preflight/security.py +0 -0
  89. {plain-0.49.0 → plain-0.50.0}/plain/preflight/urls.py +0 -0
  90. {plain-0.49.0 → plain-0.50.0}/plain/runtime/__init__.py +0 -0
  91. {plain-0.49.0 → plain-0.50.0}/plain/runtime/global_settings.py +0 -0
  92. {plain-0.49.0 → plain-0.50.0}/plain/runtime/user_settings.py +0 -0
  93. {plain-0.49.0 → plain-0.50.0}/plain/signals/README.md +0 -0
  94. {plain-0.49.0 → plain-0.50.0}/plain/signals/__init__.py +0 -0
  95. {plain-0.49.0 → plain-0.50.0}/plain/signals/dispatch/__init__.py +0 -0
  96. {plain-0.49.0 → plain-0.50.0}/plain/signals/dispatch/dispatcher.py +0 -0
  97. {plain-0.49.0 → plain-0.50.0}/plain/signals/dispatch/license.txt +0 -0
  98. {plain-0.49.0 → plain-0.50.0}/plain/signing.py +0 -0
  99. {plain-0.49.0 → plain-0.50.0}/plain/templates/README.md +0 -0
  100. {plain-0.49.0 → plain-0.50.0}/plain/templates/__init__.py +0 -0
  101. {plain-0.49.0 → plain-0.50.0}/plain/templates/core.py +0 -0
  102. {plain-0.49.0 → plain-0.50.0}/plain/templates/jinja/__init__.py +0 -0
  103. {plain-0.49.0 → plain-0.50.0}/plain/templates/jinja/environments.py +0 -0
  104. {plain-0.49.0 → plain-0.50.0}/plain/templates/jinja/extensions.py +0 -0
  105. {plain-0.49.0 → plain-0.50.0}/plain/templates/jinja/filters.py +0 -0
  106. {plain-0.49.0 → plain-0.50.0}/plain/templates/jinja/globals.py +0 -0
  107. {plain-0.49.0 → plain-0.50.0}/plain/test/README.md +0 -0
  108. {plain-0.49.0 → plain-0.50.0}/plain/test/__init__.py +0 -0
  109. {plain-0.49.0 → plain-0.50.0}/plain/test/encoding.py +0 -0
  110. {plain-0.49.0 → plain-0.50.0}/plain/test/exceptions.py +0 -0
  111. {plain-0.49.0 → plain-0.50.0}/plain/urls/README.md +0 -0
  112. {plain-0.49.0 → plain-0.50.0}/plain/urls/__init__.py +0 -0
  113. {plain-0.49.0 → plain-0.50.0}/plain/urls/converters.py +0 -0
  114. {plain-0.49.0 → plain-0.50.0}/plain/urls/exceptions.py +0 -0
  115. {plain-0.49.0 → plain-0.50.0}/plain/urls/patterns.py +0 -0
  116. {plain-0.49.0 → plain-0.50.0}/plain/urls/resolvers.py +0 -0
  117. {plain-0.49.0 → plain-0.50.0}/plain/urls/routers.py +0 -0
  118. {plain-0.49.0 → plain-0.50.0}/plain/urls/utils.py +0 -0
  119. {plain-0.49.0 → plain-0.50.0}/plain/utils/README.md +0 -0
  120. {plain-0.49.0 → plain-0.50.0}/plain/utils/__init__.py +0 -0
  121. {plain-0.49.0 → plain-0.50.0}/plain/utils/cache.py +0 -0
  122. {plain-0.49.0 → plain-0.50.0}/plain/utils/crypto.py +0 -0
  123. {plain-0.49.0 → plain-0.50.0}/plain/utils/datastructures.py +0 -0
  124. {plain-0.49.0 → plain-0.50.0}/plain/utils/dateparse.py +0 -0
  125. {plain-0.49.0 → plain-0.50.0}/plain/utils/deconstruct.py +0 -0
  126. {plain-0.49.0 → plain-0.50.0}/plain/utils/decorators.py +0 -0
  127. {plain-0.49.0 → plain-0.50.0}/plain/utils/duration.py +0 -0
  128. {plain-0.49.0 → plain-0.50.0}/plain/utils/encoding.py +0 -0
  129. {plain-0.49.0 → plain-0.50.0}/plain/utils/functional.py +0 -0
  130. {plain-0.49.0 → plain-0.50.0}/plain/utils/hashable.py +0 -0
  131. {plain-0.49.0 → plain-0.50.0}/plain/utils/html.py +0 -0
  132. {plain-0.49.0 → plain-0.50.0}/plain/utils/http.py +0 -0
  133. {plain-0.49.0 → plain-0.50.0}/plain/utils/inspect.py +0 -0
  134. {plain-0.49.0 → plain-0.50.0}/plain/utils/ipv6.py +0 -0
  135. {plain-0.49.0 → plain-0.50.0}/plain/utils/itercompat.py +0 -0
  136. {plain-0.49.0 → plain-0.50.0}/plain/utils/module_loading.py +0 -0
  137. {plain-0.49.0 → plain-0.50.0}/plain/utils/regex_helper.py +0 -0
  138. {plain-0.49.0 → plain-0.50.0}/plain/utils/safestring.py +0 -0
  139. {plain-0.49.0 → plain-0.50.0}/plain/utils/text.py +0 -0
  140. {plain-0.49.0 → plain-0.50.0}/plain/utils/timesince.py +0 -0
  141. {plain-0.49.0 → plain-0.50.0}/plain/utils/timezone.py +0 -0
  142. {plain-0.49.0 → plain-0.50.0}/plain/utils/tree.py +0 -0
  143. {plain-0.49.0 → plain-0.50.0}/plain/validators.py +0 -0
  144. {plain-0.49.0 → plain-0.50.0}/plain/views/README.md +0 -0
  145. {plain-0.49.0 → plain-0.50.0}/plain/views/__init__.py +0 -0
  146. {plain-0.49.0 → plain-0.50.0}/plain/views/base.py +0 -0
  147. {plain-0.49.0 → plain-0.50.0}/plain/views/csrf.py +0 -0
  148. {plain-0.49.0 → plain-0.50.0}/plain/views/errors.py +0 -0
  149. {plain-0.49.0 → plain-0.50.0}/plain/views/exceptions.py +0 -0
  150. {plain-0.49.0 → plain-0.50.0}/plain/views/forms.py +0 -0
  151. {plain-0.49.0 → plain-0.50.0}/plain/views/objects.py +0 -0
  152. {plain-0.49.0 → plain-0.50.0}/plain/views/redirect.py +0 -0
  153. {plain-0.49.0 → plain-0.50.0}/plain/views/templates.py +0 -0
  154. {plain-0.49.0 → plain-0.50.0}/plain/wsgi.py +0 -0
  155. {plain-0.49.0 → plain-0.50.0}/tests/.gitignore +0 -0
  156. {plain-0.49.0 → plain-0.50.0}/tests/app/.gitignore +0 -0
  157. {plain-0.49.0 → plain-0.50.0}/tests/app/settings.py +0 -0
  158. {plain-0.49.0 → plain-0.50.0}/tests/app/test/__init__.py +0 -0
  159. {plain-0.49.0 → plain-0.50.0}/tests/app/test/default_settings.py +0 -0
  160. {plain-0.49.0 → plain-0.50.0}/tests/app/urls.py +0 -0
  161. {plain-0.49.0 → plain-0.50.0}/tests/conftest.py +0 -0
  162. {plain-0.49.0 → plain-0.50.0}/tests/test_cli.py +0 -0
  163. {plain-0.49.0 → plain-0.50.0}/tests/test_runtime.py +0 -0
  164. {plain-0.49.0 → plain-0.50.0}/tests/test_wsgi.py +0 -0
@@ -6,9 +6,6 @@ __pycache__
6
6
  *.DS_Store
7
7
  .coverage
8
8
 
9
- # Symlinks to personal packages
10
- /ext
11
-
12
9
  # Test apps
13
10
  plain*/tests/.plain
14
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.49.0
3
+ Version: 0.50.0
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
@@ -0,0 +1,33 @@
1
+ # plain changelog
2
+
3
+ ## [0.50.0](https://github.com/dropseed/plain/releases/plain@0.50.0) (2025-06-23)
4
+
5
+ ### What's changed
6
+
7
+ - The URL inspection command has moved; run `plain urls list` instead of the old `plain urls` command ([6146fcb](https://github.com/dropseed/plain/commit/6146fcba536c551277d625bd750c385431ea18eb))
8
+ - `plain preflight` gains a simpler `--database` flag that enables database checks for your default database. The previous behaviour that accepted one or more database aliases has been removed ([d346d81](https://github.com/dropseed/plain/commit/d346d81567d2cc45bbed93caba18a195de10c572))
9
+ - Settings overhaul: use a single `DATABASE` setting instead of `DATABASES`/`DATABASE_ROUTERS` ([d346d81](https://github.com/dropseed/plain/commit/d346d81567d2cc45bbed93caba18a195de10c572))
10
+
11
+ ### Upgrade instructions
12
+
13
+ - Update any scripts or documentation that call `plain urls …`:
14
+ - Replace `plain urls --flat` with `plain urls list --flat`
15
+ - If you invoke preflight checks in CI or locally:
16
+ - Replace `plain preflight --database <alias>` (or multiple aliases) with the new boolean flag: `plain preflight --database`
17
+ - In `settings.py` migrate to the new database configuration:
18
+ ```python
19
+ # Before
20
+ DATABASES = {
21
+ "default": {
22
+ "ENGINE": "plain.backends.sqlite3",
23
+ "NAME": BASE_DIR / "db.sqlite3",
24
+ }
25
+ }
26
+
27
+ # After
28
+ DATABASE = {
29
+ "ENGINE": "plain.backends.sqlite3",
30
+ "NAME": BASE_DIR / "db.sqlite3",
31
+ }
32
+ ```
33
+ Remove any `DATABASES` and `DATABASE_ROUTERS` settings – they are no longer read.
@@ -52,7 +52,7 @@ __all__ = [
52
52
  ]
53
53
  ```
54
54
 
55
- ### `plain urls`
55
+ ### `plain urls list`
56
56
 
57
57
  List all the URL patterns in your app.
58
58
 
@@ -19,11 +19,10 @@ from plain.packages import packages_registry
19
19
  )
20
20
  @click.option(
21
21
  "--database",
22
- "databases",
23
- multiple=True,
24
- help="Run database related checks against these aliases.",
22
+ is_flag=True,
23
+ help="Run database related checks as part of preflight.",
25
24
  )
26
- def preflight_checks(package_label, deploy, fail_level, databases):
25
+ def preflight_checks(package_label, deploy, fail_level, database):
27
26
  """
28
27
  Use the system check framework to validate entire Plain project.
29
28
  Raise CommandError for any serious message (error or critical errors).
@@ -42,7 +41,7 @@ def preflight_checks(package_label, deploy, fail_level, databases):
42
41
  all_issues = preflight.run_checks(
43
42
  package_configs=package_configs,
44
43
  include_deployment_checks=include_deployment_checks,
45
- databases=databases,
44
+ database=database,
46
45
  )
47
46
 
48
47
  header, body, footer = "", "", ""
@@ -3,9 +3,15 @@ import sys
3
3
  import click
4
4
 
5
5
 
6
- @click.command()
6
+ @click.group()
7
+ def urls():
8
+ """URL related commands"""
9
+ pass
10
+
11
+
12
+ @urls.command("list")
7
13
  @click.option("--flat", is_flag=True, help="List all URLs in a flat list")
8
- def urls(flat):
14
+ def list_urls(flat):
9
15
  """Print all URL patterns under settings.URLS_ROUTER"""
10
16
  from plain.runtime import settings
11
17
  from plain.urls import URLResolver, get_resolver
@@ -42,7 +42,7 @@ class CheckRegistry:
42
42
  self,
43
43
  package_configs=None,
44
44
  include_deployment_checks=False,
45
- databases=None,
45
+ database=False,
46
46
  ):
47
47
  """
48
48
  Run all registered checks and return list of Errors and Warnings.
@@ -51,7 +51,7 @@ class CheckRegistry:
51
51
  checks = self.get_checks(include_deployment_checks)
52
52
 
53
53
  for check in checks:
54
- new_errors = check(package_configs=package_configs, databases=databases)
54
+ new_errors = check(package_configs=package_configs, database=database)
55
55
  if not is_iterable(new_errors):
56
56
  raise TypeError(
57
57
  f"The function {check!r} did not return a list. All functions "
@@ -79,28 +79,21 @@ from os import environ
79
79
 
80
80
  from . import database_url
81
81
 
82
- # Make DATABASES a required setting
83
- DATABASES: dict
82
+ # Make DATABASE a required setting
83
+ DATABASE: dict
84
84
 
85
- # Automatically configure DATABASES if a DATABASE_URL was given in the environment
85
+ # Automatically configure DATABASE if a DATABASE_URL was given in the environment
86
86
  if "DATABASE_URL" in environ:
87
- DATABASES = {
88
- "default": database_url.parse_database_url(
89
- environ["DATABASE_URL"],
90
- # Enable persistent connections by default
91
- conn_max_age=int(environ.get("DATABASE_CONN_MAX_AGE", 600)),
92
- conn_health_checks=environ.get(
93
- "DATABASE_CONN_HEALTH_CHECKS", "true"
94
- ).lower()
95
- in [
96
- "true",
97
- "1",
98
- ],
99
- )
100
- }
101
-
102
- # Classes used to implement DB routing behavior.
103
- DATABASE_ROUTERS = []
87
+ DATABASE = database_url.parse_database_url(
88
+ environ["DATABASE_URL"],
89
+ # Enable persistent connections by default
90
+ conn_max_age=int(environ.get("DATABASE_CONN_MAX_AGE", 600)),
91
+ conn_health_checks=environ.get("DATABASE_CONN_HEALTH_CHECKS", "true").lower()
92
+ in [
93
+ "true",
94
+ "1",
95
+ ],
96
+ )
104
97
  ```
105
98
 
106
99
  ### .env files
@@ -6,7 +6,7 @@ from http.cookies import SimpleCookie
6
6
  from io import BytesIO, IOBase
7
7
  from urllib.parse import unquote_to_bytes, urljoin, urlparse, urlsplit
8
8
 
9
- from plain.http import HttpHeaders, HttpRequest, QueryDict
9
+ from plain.http import HttpHeaders, QueryDict
10
10
  from plain.internal import internalcode
11
11
  from plain.internal.handlers.base import BaseHandler
12
12
  from plain.internal.handlers.wsgi import WSGIRequest
@@ -775,57 +775,20 @@ class Client(RequestFactory):
775
775
  @property
776
776
  def session(self):
777
777
  """Return the current session variables."""
778
- from plain.sessions import SessionStore
778
+ from plain.sessions.test import get_client_session
779
779
 
780
- cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
781
- if cookie:
782
- return SessionStore(cookie.value)
783
- session = SessionStore()
784
- session.save()
785
- self.cookies[settings.SESSION_COOKIE_NAME] = session.session_key
786
- return session
780
+ return get_client_session(self)
787
781
 
788
782
  def force_login(self, user):
789
- self._login(user)
783
+ from plain.auth.test import login_client
790
784
 
791
- def _login(self, user):
792
- from plain.auth import login
793
- from plain.sessions import SessionStore
794
-
795
- # Create a fake request to store login details.
796
- request = HttpRequest()
797
- if self.session:
798
- request.session = self.session
799
- else:
800
- request.session = SessionStore()
801
- login(request, user)
802
- # Save the session values.
803
- request.session.save()
804
- # Set the cookie to represent the session.
805
- session_cookie = settings.SESSION_COOKIE_NAME
806
- self.cookies[session_cookie] = request.session.session_key
807
- cookie_data = {
808
- "max-age": None,
809
- "path": "/",
810
- "domain": settings.SESSION_COOKIE_DOMAIN,
811
- "secure": settings.SESSION_COOKIE_SECURE or None,
812
- "expires": None,
813
- }
814
- self.cookies[session_cookie].update(cookie_data)
785
+ login_client(self, user)
815
786
 
816
787
  def logout(self):
817
788
  """Log out the user by removing the cookies and session object."""
818
- from plain.auth import get_user, logout
819
- from plain.sessions import SessionStore
789
+ from plain.auth.test import logout_client
820
790
 
821
- request = HttpRequest()
822
- if self.session:
823
- request.session = self.session
824
- request.user = get_user(request)
825
- else:
826
- request.session = SessionStore()
827
- logout(request)
828
- self.cookies = SimpleCookie()
791
+ logout_client(self)
829
792
 
830
793
  def _parse_json(self, response, **extra):
831
794
  if not hasattr(response, "_json"):
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain"
3
- version = "0.49.0"
3
+ version = "0.50.0"
4
4
  description = "A web framework for building products with Python."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes