pdm-default-scripts 0.1.5__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.
@@ -0,0 +1,59 @@
1
+ Metadata-Version: 2.1
2
+ Name: pdm-default-scripts
3
+ Version: 0.1.5
4
+ Summary: PDM plugin that adds default scripts after `pdm init`
5
+ Keywords: pdm,plugin,default scripts
6
+ Author-Email: tepek2 <dev@tepek2.com>
7
+ License: MIT
8
+ Requires-Python: >=3.9
9
+ Requires-Dist: pdm>=2.26.7
10
+ Description-Content-Type: text/markdown
11
+
12
+ ![Github Actions](https://github.com/tepek2/pdm-default-scripts/actions/workflows/tests.yml/badge.svg)
13
+
14
+ # pdm-default-scripts
15
+
16
+ `pdm-default-scripts` is a PDM plugin that adds your predefined scripts to new projects right after `pdm init`.
17
+
18
+ ## Installation
19
+
20
+ Install the plugin into your PDM environment:
21
+
22
+ ```bash
23
+ pdm self add pdm-default-scripts
24
+ ```
25
+
26
+ ## Configure default scripts
27
+
28
+ Create a `default-scripts.toml` file in your user PDM config directory.
29
+
30
+ - Linux: `~/.config/pdm/default-scripts.toml`
31
+ - macOS: `~/Library/Application Support/pdm/default-scripts.toml`
32
+ - Windows: `%APPDATA%\\pdm\\default-scripts.toml`
33
+
34
+ ### Example
35
+
36
+ ```toml
37
+ [scripts]
38
+ test = "pytest"
39
+ lint = "ruff check ."
40
+ format = "ruff format ."
41
+
42
+ [scripts.cov]
43
+ cmd = "pytest --cov"
44
+ env = { PYTHONPATH = "src" }
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ 1. Configure `default-scripts.toml` once.
50
+ 2. Run `pdm init` in any new project.
51
+ 3. The plugin adds missing entries into `[tool.pdm.scripts]` in `pyproject.toml`.
52
+
53
+ Existing scripts are not overwritten.
54
+
55
+ ## How it behaves
56
+
57
+ - Runs on the `post_init` PDM signal.
58
+ - Reads `[scripts]` from your `default-scripts.toml`.
59
+ - Writes scripts into `[tool.pdm.scripts]` only when a script name is not already present.
@@ -0,0 +1,48 @@
1
+ ![Github Actions](https://github.com/tepek2/pdm-default-scripts/actions/workflows/tests.yml/badge.svg)
2
+
3
+ # pdm-default-scripts
4
+
5
+ `pdm-default-scripts` is a PDM plugin that adds your predefined scripts to new projects right after `pdm init`.
6
+
7
+ ## Installation
8
+
9
+ Install the plugin into your PDM environment:
10
+
11
+ ```bash
12
+ pdm self add pdm-default-scripts
13
+ ```
14
+
15
+ ## Configure default scripts
16
+
17
+ Create a `default-scripts.toml` file in your user PDM config directory.
18
+
19
+ - Linux: `~/.config/pdm/default-scripts.toml`
20
+ - macOS: `~/Library/Application Support/pdm/default-scripts.toml`
21
+ - Windows: `%APPDATA%\\pdm\\default-scripts.toml`
22
+
23
+ ### Example
24
+
25
+ ```toml
26
+ [scripts]
27
+ test = "pytest"
28
+ lint = "ruff check ."
29
+ format = "ruff format ."
30
+
31
+ [scripts.cov]
32
+ cmd = "pytest --cov"
33
+ env = { PYTHONPATH = "src" }
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ 1. Configure `default-scripts.toml` once.
39
+ 2. Run `pdm init` in any new project.
40
+ 3. The plugin adds missing entries into `[tool.pdm.scripts]` in `pyproject.toml`.
41
+
42
+ Existing scripts are not overwritten.
43
+
44
+ ## How it behaves
45
+
46
+ - Runs on the `post_init` PDM signal.
47
+ - Reads `[scripts]` from your `default-scripts.toml`.
48
+ - Writes scripts into `[tool.pdm.scripts]` only when a script name is not already present.
@@ -0,0 +1,71 @@
1
+ from collections.abc import MutableMapping
2
+ from typing import Any
3
+
4
+ import platformdirs
5
+ import tomlkit
6
+ from pdm.core import Core
7
+ from pdm.project import Project
8
+ from pdm.signals import post_init
9
+ from tomlkit import TOMLDocument
10
+ from tomlkit.items import Table
11
+
12
+ DEFAULT_SCRIPTS_FILE = "default-scripts.toml"
13
+
14
+
15
+ def _get_scripts_for_creation() -> Table | None:
16
+ default_scripts = platformdirs.user_config_path("pdm") / DEFAULT_SCRIPTS_FILE
17
+
18
+ if not default_scripts.exists():
19
+ return None
20
+
21
+ with default_scripts.open("r", encoding="utf-8") as fp:
22
+ scripts = tomlkit.load(fp).get("scripts")
23
+
24
+ if scripts is None:
25
+ return None
26
+
27
+ assert isinstance(scripts, Table), "[scripts] must be a TOML table"
28
+
29
+ return scripts
30
+
31
+
32
+ def _add_script_with_dotted_keys(scripts_table: Table, name: str, command: Any):
33
+ if isinstance(command, MutableMapping):
34
+ for key, value in command.items():
35
+ dotted_key = tomlkit.key([name, str(key)])
36
+ scripts_table.append(dotted_key, value)
37
+ return
38
+ scripts_table[name] = command
39
+
40
+
41
+ def _get_or_create_table(node: TOMLDocument | Table, key: str) -> Table:
42
+
43
+ if node.get(key) is None:
44
+ node[key] = tomlkit.table()
45
+
46
+ table = node[key]
47
+ assert isinstance(table, Table), f"[{key}] must be TOML table"
48
+
49
+ return table
50
+
51
+
52
+ def on_post_init(project: Project, **args):
53
+ scripts_to_add = _get_scripts_for_creation()
54
+
55
+ if scripts_to_add is None:
56
+ return
57
+
58
+ tool_table = _get_or_create_table(project.pyproject.open_for_write(), "tool")
59
+ pdm_table = _get_or_create_table(tool_table, "pdm")
60
+ scripts_table = _get_or_create_table(pdm_table, "scripts")
61
+
62
+ for name, command in scripts_to_add.items():
63
+ if name not in scripts_table:
64
+ _add_script_with_dotted_keys(scripts_table, str(name), command)
65
+ project.core.ui.info(f"Added default script: {name}")
66
+
67
+ project.pyproject.write(show_message=False)
68
+
69
+
70
+ def plugin(core: Core) -> None:
71
+ post_init.connect(on_post_init)
@@ -0,0 +1,91 @@
1
+ [project]
2
+ name = "pdm-default-scripts"
3
+ version = "0.1.5"
4
+ description = "PDM plugin that adds default scripts after `pdm init`"
5
+ authors = [
6
+ { name = "tepek2", email = "dev@tepek2.com" },
7
+ ]
8
+ requires-python = ">=3.9"
9
+ readme = "README.md"
10
+ keywords = [
11
+ "pdm",
12
+ "plugin",
13
+ "default scripts",
14
+ ]
15
+ dependencies = [
16
+ "pdm>=2.26.7",
17
+ ]
18
+
19
+ [project.license]
20
+ text = "MIT"
21
+
22
+ [project.entry-points.pdm]
23
+ default-scripts = "default_scripts:plugin"
24
+
25
+ [build-system]
26
+ requires = [
27
+ "pdm-backend",
28
+ ]
29
+ build-backend = "pdm.backend"
30
+
31
+ [dependency-groups]
32
+ dev = [
33
+ "pytest>=9.0.2",
34
+ "pytest-mock>=3.15.1",
35
+ "pyright>=1.1.408",
36
+ "pytest-cov>=7.1.0",
37
+ "ruff>=0.15.8",
38
+ ]
39
+ release = [
40
+ "commitizen>=4.13.9",
41
+ ]
42
+
43
+ [tool.ruff]
44
+ line-length = 100
45
+
46
+ [tool.ruff.lint]
47
+ select = [
48
+ "E4",
49
+ "E7",
50
+ "E9",
51
+ "F",
52
+ "I",
53
+ ]
54
+
55
+ [tool.commitizen]
56
+ name = "cz_conventional_commits"
57
+ changelog_incremental = false
58
+ tag_format = "v$version"
59
+ version_scheme = "semver2"
60
+ version_provider = "pep621"
61
+
62
+ [tool.pdm]
63
+ distribution = true
64
+
65
+ [tool.pdm.scripts]
66
+ lint = "ruff check"
67
+ test = "pytest"
68
+ type-check = "pyright ."
69
+ coverage = "pytest --cov-fail-under=75"
70
+ release-create = "cz bump --allow-no-commit --version-files-only --changelog --changelog-to-stdout --yes {args}"
71
+
72
+ [tool.pdm.scripts.static-analys]
73
+ composite = [
74
+ "lint",
75
+ "type-check",
76
+ ]
77
+
78
+ [tool.pdm.scripts.tests]
79
+ composite = [
80
+ "static-analys",
81
+ "test",
82
+ ]
83
+
84
+ [tool.pdm.scripts.release-commit]
85
+ shell = "git add pyproject.toml CHANGELOG.md && git commit -m \"release: v$(cz version --project)\" && git tag \"v$(cz version --project)\" && git push && git push --tags\n "
86
+
87
+ [tool.pdm.scripts.release]
88
+ composite = [
89
+ "release-create {args}",
90
+ "release-commit",
91
+ ]
@@ -0,0 +1,51 @@
1
+ import tomlkit
2
+ import tomlkit.items
3
+ from pdm import signals
4
+ from pdm.project.core import Project
5
+ from pdm.pytest import RunResult
6
+ from pytest import MonkeyPatch
7
+
8
+ from default_scripts import on_post_init
9
+
10
+ pytest_plugins = "pdm.pytest"
11
+
12
+
13
+ def test_post_init_signal(
14
+ project_no_init: Project,
15
+ pdm,
16
+ monkeypatch: MonkeyPatch,
17
+ ):
18
+ def _table_data(str_data: str) -> tomlkit.items.Table:
19
+ scripts = tomlkit.parse(str_data).get("scripts")
20
+ assert isinstance(scripts, tomlkit.items.Table)
21
+ return scripts
22
+
23
+ mock_config_file_str = """
24
+ [scripts]
25
+ _.env = { PYTHONPATH = "${PDM_PROJECT_ROOT}" }
26
+ format = "ruff format ."
27
+ cov = { cmd = "pytest --cov", env = { PYTHONPATH = "src" } }
28
+
29
+
30
+ [scripts.cov2]
31
+ cmd = "pytest --cov"
32
+ env = { PYTHONPATH = "src" }
33
+ """
34
+
35
+ expected_data = {
36
+ "_": {"env": {"PYTHONPATH": "${PDM_PROJECT_ROOT}"}},
37
+ "format": "ruff format .",
38
+ "cov": {"cmd": "pytest --cov", "env": {"PYTHONPATH": "src"}},
39
+ "cov2": {"cmd": "pytest --cov", "env": {"PYTHONPATH": "src"}},
40
+ }
41
+
42
+ monkeypatch.setattr(
43
+ "default_scripts._get_scripts_for_creation",
44
+ lambda: _table_data(mock_config_file_str),
45
+ )
46
+
47
+ with signals.post_init.connected_to(on_post_init):
48
+ result: RunResult = pdm(["init", "-n"], obj=project_no_init)
49
+ print(project_no_init.scripts)
50
+ assert result.exit_code == 0
51
+ assert project_no_init.scripts == expected_data