project-toolbox 0.1.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.
@@ -0,0 +1,17 @@
1
+ Metadata-Version: 2.3
2
+ Name: project-toolbox
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Author: Farid Smaï
6
+ Author-email: Farid Smaï <f.smai@brgm.fr>
7
+ Requires-Dist: click>=8.3.1
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+
11
+ # project-toolbox
12
+
13
+ ```shell
14
+ uv add --dev project-toolbox
15
+ uv run project-toolbox
16
+ uv run release-tag
17
+ ```
@@ -0,0 +1,7 @@
1
+ # project-toolbox
2
+
3
+ ```shell
4
+ uv add --dev project-toolbox
5
+ uv run project-toolbox
6
+ uv run release-tag
7
+ ```
@@ -0,0 +1,20 @@
1
+ [project]
2
+ name = "project-toolbox"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Farid Smaï", email = "f.smai@brgm.fr" }
8
+ ]
9
+ requires-python = ">=3.11"
10
+ dependencies = [
11
+ "click>=8.3.1",
12
+ ]
13
+
14
+ [project.scripts]
15
+ release-tag = "project_toolbox.release_tag:main"
16
+ project-toolbox = "project_toolbox:main"
17
+
18
+ [build-system]
19
+ requires = ["uv_build>=0.9.26,<0.10.0"]
20
+ build-backend = "uv_build"
@@ -0,0 +1,15 @@
1
+ """project-toolbox -- a collection of tools to help you manage coding projects.
2
+
3
+ Philosophy:
4
+ - projects use git and uv
5
+ - tools automate repetitive tasks
6
+ - tools reduce the number of command to remember
7
+ - tools avoid mistakes by checking project sanity
8
+
9
+ Available tools:
10
+ release-tag Add and push git tag for project release.
11
+ """
12
+
13
+
14
+ def main():
15
+ print(__doc__)
@@ -0,0 +1,118 @@
1
+ # /// script
2
+ # requires-python = ">=3.11"
3
+ # dependencies = [
4
+ # "click>=8.3.1",
5
+ # ]
6
+ # ///
7
+
8
+
9
+ import pathlib
10
+ import tomllib
11
+ import subprocess
12
+ import click
13
+
14
+
15
+ DEFAULT_BRANCH = "main"
16
+ PROJECT_FILE = "pyproject.toml"
17
+ INDENT = " " * 4
18
+ BAR = "=" * 80
19
+
20
+
21
+ def get_project_file(cwd='.'):
22
+ directory = pathlib.Path(cwd).resolve()
23
+ if not directory.exists():
24
+ return None
25
+ child = None
26
+ while directory != child:
27
+ file = directory / PROJECT_FILE
28
+ if file.exists():
29
+ return file
30
+ child, directory = directory, directory.parent
31
+ return None
32
+
33
+
34
+ def shell(args, **kwds):
35
+ out = subprocess.run(args, encoding="utf8", capture_output=True, **kwds)
36
+ out.stdout = out.stdout.strip()
37
+ out.stderr = out.stderr.strip()
38
+ return out
39
+
40
+
41
+ @click.command(context_settings={"help_option_names": ['-h', '--help']})
42
+ def main() -> None:
43
+ """ Add and push git tag for project release.
44
+
45
+ It will look for project version, check repo sanity, create tag and push it.
46
+
47
+ \b
48
+ Project version is found in the 'project.version' entry of pyproject.toml.
49
+ A good way to handle that is with `uv version` command:
50
+ Start branch with:
51
+ uv version --bump dev --bump patch
52
+ Close branch with:
53
+ uv version --bump stable
54
+ """
55
+
56
+ # get project file
57
+ project_file = get_project_file()
58
+ if project_file is None:
59
+ click.echo(f"error: unable to find project file ({PROJECT_FILE})", err=True)
60
+ exit(1)
61
+ click.echo(f"Found project file: {project_file}")
62
+
63
+ # get version from project file
64
+ config = tomllib.load(project_file.open("rb"))
65
+ version = config.get("project", {}).get("version", None)
66
+ if version is None:
67
+ click.echo("error: unable to find '[project.version]' key in project file.", err=True)
68
+ exit(1)
69
+ version = version.strip()
70
+ version_tag = f"v{version}"
71
+ click.echo(f"Found version: {version}")
72
+
73
+ # get active branch
74
+ branch = shell(["git", "branch", "--show-current"]).stdout
75
+ if branch != DEFAULT_BRANCH:
76
+ click.echo(f"warning: current branch is '{branch}', should be '{DEFAULT_BRANCH}'")
77
+ if not click.confirm(f"Do you want to release from '{branch}' instead ?"):
78
+ exit(1)
79
+
80
+ # check if repo is clean
81
+ repo_not_clean = shell(["git", "diff-index", "--quiet", "HEAD"]).returncode
82
+ if repo_not_clean:
83
+ click.echo("warning: git repo is not clean, current changes won't be released", err=True)
84
+ if not click.confirm(f"Continue with not clean repo ?"):
85
+ exit(1)
86
+
87
+ # check if new tag already exists
88
+ tags = shell(["git", "tag", "--list"]).stdout.splitlines()
89
+ if version_tag in tags:
90
+ click.echo("error: git tag already exists [{version_tag}]", err=True)
91
+ exit(1)
92
+
93
+ # show commit to be released
94
+ click.echo("Commit to be released:")
95
+ click.echo(BAR)
96
+ subprocess.run(["git", "log", "HEAD^..HEAD"])
97
+ click.echo(BAR)
98
+
99
+ # prepare commands modifying repo
100
+ cmd_git = [
101
+ ["git", "tag", "-a", version_tag, "-m", f"\"release of {version_tag}\""],
102
+ ["git", "push", "origin", version_tag],
103
+ ]
104
+
105
+ # ask confirmation for commands
106
+ click.echo("The following commands will be executed:")
107
+ click.echo("\n".join(INDENT + " ".join(cmd) for cmd in cmd_git))
108
+ if not click.confirm("Confirm execution ?"):
109
+ exit(1)
110
+
111
+ # run commands
112
+ for cmd in cmd_git:
113
+ click.echo(f"running: {' '.join(cmd)}")
114
+ subprocess.run(cmd)
115
+
116
+
117
+ if __name__ == "__main__":
118
+ main()