plain 0.51.0__py3-none-any.whl → 0.52.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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # plain changelog
2
2
 
3
+ ## [0.52.1](https://github.com/dropseed/plain/releases/plain@0.52.1) (2025-06-27)
4
+
5
+ ### What's changed
6
+
7
+ - Fixed `plain help` output on newer versions of Click by switching from `MultiCommand` to `Group` when determining sub-commands ([9482e42](https://github.com/dropseed/plain/commit/9482e421ac408ac043d341edda3dba9f27694f08))
8
+
9
+ ### Upgrade instructions
10
+
11
+ - No changes required
12
+
13
+ ## [0.52.0](https://github.com/dropseed/plain/releases/plain@0.52.0) (2025-06-26)
14
+
15
+ ### What's changed
16
+
17
+ - Added `plain-changelog` as a standalone executable so you can view changelogs without importing the full framework ([e4e7324](https://github.com/dropseed/plain/commit/e4e7324cd284c800ff957933748d6639615cbea6))
18
+ - Removed the runtime dependency on the `packaging` library by replacing it with an internal version-comparison helper ([e4e7324](https://github.com/dropseed/plain/commit/e4e7324cd284c800ff957933748d6639615cbea6))
19
+ - Improved the error message when a package changelog cannot be found, now showing the path that was looked up ([f3c82bb](https://github.com/dropseed/plain/commit/f3c82bb59e07c1bddbdb2557f2043e039c1cd1e9))
20
+ - Fixed an f-string issue that broke `plain.debug.dd` on Python 3.11 ([ed24276](https://github.com/dropseed/plain/commit/ed24276a12191e4c8903369002dd32b69eb358b3))
21
+
22
+ ### Upgrade instructions
23
+
24
+ - No changes required
25
+
3
26
  ## [0.51.0](https://github.com/dropseed/plain/releases/plain@0.51.0) (2025-06-24)
4
27
 
5
28
  ### What's changed
plain/cli/changelog.py CHANGED
@@ -3,11 +3,43 @@ from importlib.util import find_spec
3
3
  from pathlib import Path
4
4
 
5
5
  import click
6
- from packaging.version import Version
7
6
 
8
7
  from .output import style_markdown
9
8
 
10
9
 
10
+ def parse_version(version_str):
11
+ """Parse a version string into a tuple of integers for comparison."""
12
+ # Remove 'v' prefix if present and split by dots
13
+ clean_version = version_str.lstrip("v")
14
+ parts = []
15
+ for part in clean_version.split("."):
16
+ # Extract numeric part from each segment
17
+ numeric_part = re.match(r"\d+", part)
18
+ if numeric_part:
19
+ parts.append(int(numeric_part.group()))
20
+ else:
21
+ parts.append(0)
22
+ return tuple(parts)
23
+
24
+
25
+ def compare_versions(v1, v2):
26
+ """Compare two version strings. Returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2."""
27
+ parsed_v1 = parse_version(v1)
28
+ parsed_v2 = parse_version(v2)
29
+
30
+ # Pad shorter version with zeros
31
+ max_len = max(len(parsed_v1), len(parsed_v2))
32
+ parsed_v1 += (0,) * (max_len - len(parsed_v1))
33
+ parsed_v2 += (0,) * (max_len - len(parsed_v2))
34
+
35
+ if parsed_v1 < parsed_v2:
36
+ return -1
37
+ elif parsed_v1 > parsed_v2:
38
+ return 1
39
+ else:
40
+ return 0
41
+
42
+
11
43
  @click.command("changelog")
12
44
  @click.argument("package_label")
13
45
  @click.option("--from", "from_version", help="Show entries from this version onwards")
@@ -28,7 +60,9 @@ def changelog(package_label, from_version, to_version):
28
60
 
29
61
  changelog_path = package_path / "CHANGELOG.md"
30
62
  if not changelog_path.exists():
31
- raise click.ClickException(f"Changelog not found for {package_label}")
63
+ raise click.ClickException(
64
+ f"Changelog not found for {package_label} ({changelog_path})"
65
+ )
32
66
 
33
67
  content = changelog_path.read_text()
34
68
 
@@ -52,7 +86,7 @@ def changelog(package_label, from_version, to_version):
52
86
  entries.append((current_version, current_lines))
53
87
 
54
88
  def version_found(version):
55
- return any(Version(v) == Version(version) for v, _ in entries)
89
+ return any(compare_versions(v, version) == 0 for v, _ in entries)
56
90
 
57
91
  if from_version and not version_found(from_version):
58
92
  click.secho(
@@ -63,10 +97,9 @@ def changelog(package_label, from_version, to_version):
63
97
 
64
98
  selected_lines = []
65
99
  for version, lines in entries:
66
- v = Version(version)
67
- if from_version and v <= Version(from_version):
100
+ if from_version and compare_versions(version, from_version) <= 0:
68
101
  continue
69
- if to_version and v > Version(to_version):
102
+ if to_version and compare_versions(version, to_version) > 0:
70
103
  continue
71
104
  selected_lines.extend(lines)
72
105
 
plain/cli/help.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import click
2
- from click.core import MultiCommand
2
+ from click.core import Group
3
3
 
4
4
 
5
5
  @click.command("help")
@@ -18,7 +18,7 @@ def help_cmd(ctx):
18
18
  click.secho("-" * len(title), fg="green")
19
19
  click.echo(sub_ctx.get_help())
20
20
 
21
- if isinstance(cmd, MultiCommand):
21
+ if isinstance(cmd, Group):
22
22
  for name in cmd.list_commands(sub_ctx):
23
23
  click.echo()
24
24
  sub_cmd = cmd.get_command(sub_ctx, name)
plain/debug.py CHANGED
@@ -13,13 +13,14 @@ def dd(*objs):
13
13
  Dump the object and raise a ResponseException with the dump as the response content.
14
14
  """
15
15
 
16
- print(f"Dumping objects:\n{'\n'.join([pformat(obj) for obj in objs])}")
16
+ print_objs = "\n".join([pformat(obj) for obj in objs])
17
+ print(f"Dumping objects:\n{print_objs}")
17
18
 
18
- dump_strs = [
19
+ html_objs = [
19
20
  Markup("<pre><code>") + escape(pformat(obj)) + Markup("</code></pre>")
20
21
  for obj in objs
21
22
  ]
22
- combined_dump_str = Markup("\n\n").join(dump_strs)
23
+ combined_dump_str = Markup("\n\n").join(html_objs)
23
24
 
24
25
  response = Response()
25
26
  response.status_code = 500
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.51.0
3
+ Version: 0.52.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
@@ -1,7 +1,7 @@
1
- plain/CHANGELOG.md,sha256=lE0zfshrzDi6rsj59KWtZdcM9cqkCtqf7XrC4Tb7JUA,1996
1
+ plain/CHANGELOG.md,sha256=TdNwYCrcE4iKZQLbI89NSKnEz_eH_251d8E2eNpHXzI,3322
2
2
  plain/README.md,sha256=gik6DBZcJAITcm4WRq_L53AxkjY45eQLafyTCSf0CKE,3986
3
3
  plain/__main__.py,sha256=GK39854Lc_LO_JP8DzY9Y2MIQ4cQEl7SXFJy244-lC8,110
4
- plain/debug.py,sha256=abPkJY4aSbBYGEYSZST_ZY3ohXPGDdz9uWQBYRqfd3M,730
4
+ plain/debug.py,sha256=XdjnXcbPGsi0J2SpHGaLthhYU5AjhBlkHdemaP4sbYY,758
5
5
  plain/exceptions.py,sha256=Z9cbPE5im_Y-bjVq8cqC85gBoqOr80rLFG5wTKixrwE,5894
6
6
  plain/json.py,sha256=McJdsbMT1sYwkGRG--f2NSZz0hVXPMix9x3nKaaak2o,1262
7
7
  plain/paginator.py,sha256=iXiOyt2r_YwNrkqCRlaU7V-M_BKaaQ8XZElUBVa6yeU,5844
@@ -21,12 +21,12 @@ plain/chores/registry.py,sha256=V3WjuekRI22LFvJbqSkUXQtiOtuE2ZK8gKV1TRvxRUI,1866
21
21
  plain/cli/README.md,sha256=GzBry6mEilhM80SfVUg02ydGwAk0m-s6FAqQR1nRsMM,2022
22
22
  plain/cli/__init__.py,sha256=6w9T7K2WrPwh6DcaMb2oNt_CWU6Bc57nUTO2Bt1p38Y,63
23
23
  plain/cli/build.py,sha256=dKUYBNegvb6QNckR7XZ7CJJtINwZcmDvbUdv2dWwjf8,3226
24
- plain/cli/changelog.py,sha256=VRcL0v_r8tPSe-6fGGsa-OCgdhLMrwj6TnpmPilQb6Y,2441
24
+ plain/cli/changelog.py,sha256=j-k1yZk9mpm-fLZgeWastiyIisxNSuAJfXTQ2B6WQmk,3457
25
25
  plain/cli/chores.py,sha256=xXSSFvr8T5jWfLWqe6E8YVMw1BkQxyOHHVuY0x9RH0A,2412
26
26
  plain/cli/core.py,sha256=D3t83ujjjHayblM-RuttrGoNf8hMV9-l3zQsbhVAjWU,2991
27
27
  plain/cli/docs.py,sha256=KCJCP_OVFb34zOkA6x7X6-iGFzx2tv4ZgXAM99TjWNg,7443
28
28
  plain/cli/formatting.py,sha256=1hZH13y1qwHcU2K2_Na388nw9uvoeQH8LrWL-O9h8Yc,2207
29
- plain/cli/help.py,sha256=otRSGxOJ5V8JMjpdZ8XYqUbdlYdJvxOMzQroLOWw-l0,801
29
+ plain/cli/help.py,sha256=NefZSEIixrX_WELVSnJDHRpLDWf7_4PXmkkMm3Q2mzo,787
30
30
  plain/cli/output.py,sha256=Fe3xS6Va4Bi1ZNrqi0nh09THTsdCyMW2b9SPY5I4n-o,1318
31
31
  plain/cli/preflight.py,sha256=FWFwMZ0W_t8ObTTRMnBmaiGN8PqdEAWgmSEPGDwZFpA,4148
32
32
  plain/cli/print.py,sha256=XraUYrgODOJquIiEv78wSCYGRBplHXtXSS9QtFG5hqY,217
@@ -149,8 +149,8 @@ plain/views/forms.py,sha256=ESZOXuo6IeYixp1RZvPb94KplkowRiwO2eGJCM6zJI0,2400
149
149
  plain/views/objects.py,sha256=GGbcfg_9fPZ-PiaBwIHG2e__8GfWDR7JQtQ15wTyiHg,5970
150
150
  plain/views/redirect.py,sha256=daq2cQIkdDF78bt43sjuZxRAyJm_t_SKw6tyPmiXPIc,1985
151
151
  plain/views/templates.py,sha256=ivkI7LU7BXDQ0d4Geab96Is4-Cp03KbIntXRT1J8e6I,2139
152
- plain-0.51.0.dist-info/METADATA,sha256=xzYeAOLD7gvPsfMUMhQJIR0nsBc6VAUZ08bZ1Hyodao,4297
153
- plain-0.51.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
154
- plain-0.51.0.dist-info/entry_points.txt,sha256=1Ys2lsSeMepD1vz8RSrJopna0RQfUd951vYvCRsvl6A,45
155
- plain-0.51.0.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
156
- plain-0.51.0.dist-info/RECORD,,
152
+ plain-0.52.1.dist-info/METADATA,sha256=iB2DW8m-StzH4FmWqnnbiiid1CpUVzr82YovQNFdD5Y,4297
153
+ plain-0.52.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
154
+ plain-0.52.1.dist-info/entry_points.txt,sha256=nn4uKTRRZuEKOJv3810s3jtSMW0Gew7XDYiKIvBRR6M,93
155
+ plain-0.52.1.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
156
+ plain-0.52.1.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ plain = plain.cli.core:cli
3
+ plain-changelog = plain.cli.changelog:changelog
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- plain = plain.cli.core:cli
File without changes