plain 0.49.0__py3-none-any.whl → 0.50.0__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/CHANGELOG.md ADDED
@@ -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.
plain/cli/README.md CHANGED
@@ -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
 
plain/cli/preflight.py CHANGED
@@ -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 = "", "", ""
plain/cli/urls.py CHANGED
@@ -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 "
plain/runtime/README.md CHANGED
@@ -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
plain/test/client.py CHANGED
@@ -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
  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
@@ -1,3 +1,4 @@
1
+ plain/CHANGELOG.md,sha256=Bl0GLzelbqK3Tyg-dAGBcHG49JwXtH3g6GHFCl-LEpk,1554
1
2
  plain/README.md,sha256=gik6DBZcJAITcm4WRq_L53AxkjY45eQLafyTCSf0CKE,3986
2
3
  plain/__main__.py,sha256=GK39854Lc_LO_JP8DzY9Y2MIQ4cQEl7SXFJy244-lC8,110
3
4
  plain/debug.py,sha256=abPkJY4aSbBYGEYSZST_ZY3ohXPGDdz9uWQBYRqfd3M,730
@@ -17,7 +18,7 @@ plain/assets/views.py,sha256=T_0Qh6v9qBerEBYbhToigwOzsij-x1z_R-1zETQcIh0,9447
17
18
  plain/chores/README.md,sha256=Da8Nw8ZF7PlAE_iVb0AqJGbLOu0F6HC0cj1K451KBak,1946
18
19
  plain/chores/__init__.py,sha256=r9TXtQCH-VbvfnIJ5F8FxgQC35GRWFOfmMZN3q9niLg,67
19
20
  plain/chores/registry.py,sha256=V3WjuekRI22LFvJbqSkUXQtiOtuE2ZK8gKV1TRvxRUI,1866
20
- plain/cli/README.md,sha256=nkcpS_mWPZ6JbnlKh4fq-b7AlmItAQsT78XAqRlwqNg,2017
21
+ plain/cli/README.md,sha256=GzBry6mEilhM80SfVUg02ydGwAk0m-s6FAqQR1nRsMM,2022
21
22
  plain/cli/__init__.py,sha256=6w9T7K2WrPwh6DcaMb2oNt_CWU6Bc57nUTO2Bt1p38Y,63
22
23
  plain/cli/build.py,sha256=dKUYBNegvb6QNckR7XZ7CJJtINwZcmDvbUdv2dWwjf8,3226
23
24
  plain/cli/chores.py,sha256=xXSSFvr8T5jWfLWqe6E8YVMw1BkQxyOHHVuY0x9RH0A,2412
@@ -25,14 +26,14 @@ plain/cli/core.py,sha256=h8gjeBYQzYTzpmeDMAJTdVDOEoNCNcvnxml-KIsiRPo,2925
25
26
  plain/cli/docs.py,sha256=2CpTv5k-TNWf593tPiglvUVXWBGdfPmbGf8vl5AfJwU,8995
26
27
  plain/cli/formatting.py,sha256=1hZH13y1qwHcU2K2_Na388nw9uvoeQH8LrWL-O9h8Yc,2207
27
28
  plain/cli/help.py,sha256=otRSGxOJ5V8JMjpdZ8XYqUbdlYdJvxOMzQroLOWw-l0,801
28
- plain/cli/preflight.py,sha256=NKyYjcoDjigzfJIDhf7A7degYadaUI05Bw7U9OQ73vs,4170
29
+ plain/cli/preflight.py,sha256=FWFwMZ0W_t8ObTTRMnBmaiGN8PqdEAWgmSEPGDwZFpA,4148
29
30
  plain/cli/print.py,sha256=XraUYrgODOJquIiEv78wSCYGRBplHXtXSS9QtFG5hqY,217
30
31
  plain/cli/registry.py,sha256=yKVMSDjW8g10nlV9sPXFGJQmhC_U-k4J4kM7N2OQVLA,1467
31
32
  plain/cli/scaffold.py,sha256=mcywA9DzfwoBSqWl5-Zpgcy1mTNUGEgdvoxXUrGcEVk,1351
32
33
  plain/cli/settings.py,sha256=9cx4bue664I2P7kUedlf4YhCPB0tSKSE4Q8mGyzEv2o,1995
33
34
  plain/cli/shell.py,sha256=iIwvlTdTBjLBBUdXMAmIRWSoynszOZI79-mrBg4RegU,1373
34
35
  plain/cli/startup.py,sha256=wLaFuyUb4ewWhtehBCGicrRCXIIGCRbeCT3ce9hUv-A,1022
35
- plain/cli/urls.py,sha256=CS9NFpwZBWveAR8F3YsoUNySDEK_PwF73oSgLDfkOdI,3776
36
+ plain/cli/urls.py,sha256=7FOvLjfV1GsYKnb7SGlIgEfchQcrkWdYU1nY6aazGBI,3855
36
37
  plain/cli/utils.py,sha256=VwlIh0z7XxzVV8I3qM2kZo07fkJFPoeeVZa1ODG616k,258
37
38
  plain/csrf/README.md,sha256=nxCpPk1HF5eAM-7paxg9D-9RVCU9jXsSPAVHkJvA_DU,717
38
39
  plain/csrf/middleware.py,sha256=U3B9R7ciO_UAf7O3jdNtVu6QZ_3Yrm8isRdnW6bVKX4,17401
@@ -79,10 +80,10 @@ plain/preflight/README.md,sha256=9fE0Ql2JNd3CI420eg1sP_xmaim-6Ejlzi_hfk3tVS0,151
79
80
  plain/preflight/__init__.py,sha256=j4-yPnrM5hmjumrdkBLOQjFHzRHpA6wCjiFpMNBjIqY,619
80
81
  plain/preflight/files.py,sha256=D_pBSwRXpXy2-3FWywweozuxrhIaR8w5hpPA2d6XMPs,522
81
82
  plain/preflight/messages.py,sha256=B6VyXzu7HTJHaPVK4G1L_1HVHG87CT7JPtcDk8QYSeE,2322
82
- plain/preflight/registry.py,sha256=wHLq6LSMkKunkxElBmNwzMzQx3tc6OGYeKyOOi0tuyQ,2333
83
+ plain/preflight/registry.py,sha256=vcqzaE1MIneNL_ydKPy_1zrSThnzsrWARSClLCJ-4b8,2331
83
84
  plain/preflight/security.py,sha256=oxUZBp2M0bpBfUoLYepIxoex2Y90nyjlrL8XU8UTHYY,2438
84
85
  plain/preflight/urls.py,sha256=cQ-WnFa_5oztpKdtwhuIGb7pXEml__bHsjs1SWO2YNI,1468
85
- plain/runtime/README.md,sha256=yPcrJKnFEqkrb0KlhLZi2VInV-LCl6ENOZs7mOHlhi0,4753
86
+ plain/runtime/README.md,sha256=1h30eRTg5-lY-G7GF_4TdUiUcOLVzKR15mSrmyeU8eI,4584
86
87
  plain/runtime/__init__.py,sha256=8GtvKROf3HUCtneDYXTbEioPcCtwnV76dP57n2PnjuE,2343
87
88
  plain/runtime/global_settings.py,sha256=MpJ6vtBMO2EYALaKXrtgcGoxLh9Y549zwwErC5D5K7I,5343
88
89
  plain/runtime/user_settings.py,sha256=OzMiEkE6ZQ50nxd1WIqirXPiNuMAQULklYHEzgzLWgA,11027
@@ -101,7 +102,7 @@ plain/templates/jinja/filters.py,sha256=t_u8BkWtEpJFLbLywONxWKrenSzOvDJhfOLwlZiX
101
102
  plain/templates/jinja/globals.py,sha256=VMpuMZvwWOmb5MbzKK-ox-QEX_WSsXFxq0mm8biJgaU,558
102
103
  plain/test/README.md,sha256=fv4YzziU2QxgcNHSgv7aDUO45sDOofVuCNrV1NPbWzo,1106
103
104
  plain/test/__init__.py,sha256=MhNHtp7MYBl9kq-pMRGY11kJ6kU1I6vOkjNkit1TYRg,94
104
- plain/test/client.py,sha256=lqzOf8EJo_u54dW_oiPy0m5mW-Nt3-CWyrBh9_MJnms,26930
105
+ plain/test/client.py,sha256=XjLjkeDl1rQRaFoeiCvvD5GXfxIxpuic2OnxjoX05tA,25573
105
106
  plain/test/encoding.py,sha256=YJBOIE-BQRA5yl4zHnQy-9l67mJDTFmfy1DQXK0Wk-Q,3199
106
107
  plain/test/exceptions.py,sha256=b-GHicg87Gh73W3g8QGWuSHi9PrQFVsxgWvEXDLt8gQ,290
107
108
  plain/urls/README.md,sha256=ijFGmrkUY9buBqO_i1GZaN3V55vl9xwEADtHOx_ZHPY,3724
@@ -146,8 +147,8 @@ plain/views/forms.py,sha256=ESZOXuo6IeYixp1RZvPb94KplkowRiwO2eGJCM6zJI0,2400
146
147
  plain/views/objects.py,sha256=GGbcfg_9fPZ-PiaBwIHG2e__8GfWDR7JQtQ15wTyiHg,5970
147
148
  plain/views/redirect.py,sha256=daq2cQIkdDF78bt43sjuZxRAyJm_t_SKw6tyPmiXPIc,1985
148
149
  plain/views/templates.py,sha256=ivkI7LU7BXDQ0d4Geab96Is4-Cp03KbIntXRT1J8e6I,2139
149
- plain-0.49.0.dist-info/METADATA,sha256=h5KgVsVtWFjd4CveudNI0w7_TsFeroqviAiWssBGNwE,4297
150
- plain-0.49.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
- plain-0.49.0.dist-info/entry_points.txt,sha256=1Ys2lsSeMepD1vz8RSrJopna0RQfUd951vYvCRsvl6A,45
152
- plain-0.49.0.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
153
- plain-0.49.0.dist-info/RECORD,,
150
+ plain-0.50.0.dist-info/METADATA,sha256=GLcRDpS06XPtx52qLG5bIfrROE3g8CFffLNSz6Mdxt8,4297
151
+ plain-0.50.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
152
+ plain-0.50.0.dist-info/entry_points.txt,sha256=1Ys2lsSeMepD1vz8RSrJopna0RQfUd951vYvCRsvl6A,45
153
+ plain-0.50.0.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
154
+ plain-0.50.0.dist-info/RECORD,,
File without changes