Skip to content

Commit 244867f

Browse files
authored
Feature/uv (#2)
* updated reqs del for uv * updated makes for uv * updated toml for uv * had to remove pip-audit for uv * removed pip-audit for uv dev reqs
1 parent caa751d commit 244867f

File tree

7 files changed

+307
-20
lines changed

7 files changed

+307
-20
lines changed

cookiecutter.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
"3.12",
2323
"3.13"
2424
],
25+
"package_manager": [
26+
"uv",
27+
"pip"
28+
],
2529
"use_requests": [
2630
"n",
2731
"y"
@@ -43,7 +47,7 @@
4347
"https"
4448
],
4549
"__template_repo": "https://github.com/btr1975/cookiecutter-python-library",
46-
"__template_version": "1.0.17",
50+
"__template_version": "2.0.0",
4751
"_new_lines": "\n",
4852
"_copy_without_render": [
4953
".github"
@@ -74,6 +78,11 @@
7478
"3.12": "3.12",
7579
"3.13": "3.13"
7680
},
81+
"package_manager": {
82+
"__prompt__": "Which pacakge manager for Python will be supported",
83+
"uv": "UV By Astral",
84+
"pip": "PIP (The built in Python Package Installer)"
85+
},
7786
"use_requests": {
7887
"__prompt__": "Will you use the requests library",
7988
"n": "No",

hooks/post_gen_project.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
'{% if cookiecutter.container_runtime == "docker" %}containers/Containerfile{% endif %}',
2121
]
2222

23+
REMOVE_PATHS_UV = [
24+
'{% if cookiecutter.package_manager == "uv" %}requirements.txt{% endif %}',
25+
'{% if cookiecutter.package_manager == "uv" %}requirements-dev.txt{% endif %}',
26+
]
27+
2328

2429
def remove_paths(paths_to_remove: List[str]) -> None:
2530
"""Remove files and directories
@@ -41,3 +46,4 @@ def remove_paths(paths_to_remove: List[str]) -> None:
4146
remove_paths(REMOVE_PATHS_NOT_CLI)
4247
remove_paths(REMOVE_PATHS_PODMAN)
4348
remove_paths(REMOVE_PATHS_DOCKER)
49+
remove_paths(REMOVE_PATHS_UV)

tests/conftest.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ def bake_project_cli_podman_data() -> dict:
1414
"email": "name@example.com",
1515
"git_username": "some-username",
1616
"git_url": "https://github.com/some-username/python-with-cli",
17+
"package_manager": "pip",
18+
}
19+
20+
return options
21+
22+
23+
@pytest.fixture
24+
def bake_project_uv_cli_podman_data() -> dict:
25+
options = {
26+
"git_repo_name": "python-with-cli",
27+
"include_cli": "y",
28+
"email": "name@example.com",
29+
"git_username": "some-username",
30+
"git_url": "https://github.com/some-username/python-with-cli",
31+
"package_manager": "uv",
1732
}
1833

1934
return options
@@ -28,6 +43,22 @@ def bake_project_cli_docker_data() -> dict:
2843
"git_username": "some-username",
2944
"git_url": "https://github.com/some-username/python-with-cli",
3045
"container_runtime": "docker",
46+
"package_manager": "pip",
47+
}
48+
49+
return options
50+
51+
52+
@pytest.fixture
53+
def bake_project_uv_cli_docker_data() -> dict:
54+
options = {
55+
"git_repo_name": "python-with-cli",
56+
"include_cli": "y",
57+
"email": "name@example.com",
58+
"git_username": "some-username",
59+
"git_url": "https://github.com/some-username/python-with-cli",
60+
"container_runtime": "docker",
61+
"package_manager": "uv",
3162
}
3263

3364
return options
@@ -41,6 +72,21 @@ def bake_project_no_cli_podman_data() -> dict:
4172
"email": "name@example.com",
4273
"git_username": "some-username",
4374
"git_url": "https://github.com/some-username/python-no-cli",
75+
"package_manager": "pip",
76+
}
77+
78+
return options
79+
80+
81+
@pytest.fixture
82+
def bake_project_uv_no_cli_podman_data() -> dict:
83+
options = {
84+
"git_repo_name": "python-no-cli",
85+
"include_cli": "n",
86+
"email": "name@example.com",
87+
"git_username": "some-username",
88+
"git_url": "https://github.com/some-username/python-no-cli",
89+
"package_manager": "uv",
4490
}
4591

4692
return options
@@ -55,6 +101,22 @@ def bake_project_no_cli_docker_data() -> dict:
55101
"git_username": "some-username",
56102
"git_url": "https://github.com/some-username/python-no-cli",
57103
"container_runtime": "docker",
104+
"package_manager": "pip",
105+
}
106+
107+
return options
108+
109+
110+
@pytest.fixture
111+
def bake_project_uv_no_cli_docker_data() -> dict:
112+
options = {
113+
"git_repo_name": "python-no-cli",
114+
"include_cli": "n",
115+
"email": "name@example.com",
116+
"git_username": "some-username",
117+
"git_url": "https://github.com/some-username/python-no-cli",
118+
"container_runtime": "docker",
119+
"package_manager": "uv",
58120
}
59121

60122
return options

tests/test_cookies.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ def test_bake_project_no_cli_podman(cookies, bake_project_no_cli_podman_data):
66
assert result.project_path.name == "python-no-cli"
77
assert result.project_path.is_dir()
88
assert result.project_path.joinpath("README.md").is_file()
9+
assert result.project_path.joinpath("requirements.txt").is_file()
10+
assert result.project_path.joinpath("requirements-dev.txt").is_file()
11+
assert result.project_path.joinpath("python_no_cli").is_dir()
12+
assert not result.project_path.joinpath("python_no_cli", "python_no_cli_cli.py").is_file()
13+
assert not result.project_path.joinpath("python_no_cli", "example.py").is_file()
14+
assert result.project_path.joinpath("containers", "Containerfile").is_file()
15+
assert not result.project_path.joinpath("containers", "Dockerfile").is_file()
16+
17+
18+
def test_bake_project_uv_no_cli_podman(cookies, bake_project_uv_no_cli_podman_data):
19+
result = cookies.bake(extra_context=bake_project_uv_no_cli_podman_data)
20+
21+
assert result.exit_code == 0
22+
assert result.exception is None
23+
assert result.project_path.name == "python-no-cli"
24+
assert result.project_path.is_dir()
25+
assert result.project_path.joinpath("README.md").is_file()
26+
assert not result.project_path.joinpath("requirements.txt").is_file()
27+
assert not result.project_path.joinpath("requirements-dev.txt").is_file()
928
assert result.project_path.joinpath("python_no_cli").is_dir()
1029
assert not result.project_path.joinpath("python_no_cli", "python_no_cli_cli.py").is_file()
1130
assert not result.project_path.joinpath("python_no_cli", "example.py").is_file()
@@ -21,6 +40,25 @@ def test_bake_project_no_cli_docker(cookies, bake_project_no_cli_docker_data):
2140
assert result.project_path.name == "python-no-cli"
2241
assert result.project_path.is_dir()
2342
assert result.project_path.joinpath("README.md").is_file()
43+
assert result.project_path.joinpath("requirements.txt").is_file()
44+
assert result.project_path.joinpath("requirements-dev.txt").is_file()
45+
assert result.project_path.joinpath("python_no_cli").is_dir()
46+
assert not result.project_path.joinpath("python_no_cli", "python_no_cli_cli.py").is_file()
47+
assert not result.project_path.joinpath("python_no_cli", "example.py").is_file()
48+
assert not result.project_path.joinpath("containers", "Containerfile").is_file()
49+
assert result.project_path.joinpath("containers", "Dockerfile").is_file()
50+
51+
52+
def test_bake_project_uv_no_cli_docker(cookies, bake_project_uv_no_cli_docker_data):
53+
result = cookies.bake(extra_context=bake_project_uv_no_cli_docker_data)
54+
55+
assert result.exit_code == 0
56+
assert result.exception is None
57+
assert result.project_path.name == "python-no-cli"
58+
assert result.project_path.is_dir()
59+
assert result.project_path.joinpath("README.md").is_file()
60+
assert not result.project_path.joinpath("requirements.txt").is_file()
61+
assert not result.project_path.joinpath("requirements-dev.txt").is_file()
2462
assert result.project_path.joinpath("python_no_cli").is_dir()
2563
assert not result.project_path.joinpath("python_no_cli", "python_no_cli_cli.py").is_file()
2664
assert not result.project_path.joinpath("python_no_cli", "example.py").is_file()
@@ -36,6 +74,25 @@ def test_bake_project_cli_podman(cookies, bake_project_cli_podman_data):
3674
assert result.project_path.name == "python-with-cli"
3775
assert result.project_path.is_dir()
3876
assert result.project_path.joinpath("README.md").is_file()
77+
assert result.project_path.joinpath("requirements.txt").is_file()
78+
assert result.project_path.joinpath("requirements-dev.txt").is_file()
79+
assert result.project_path.joinpath("python_with_cli").is_dir()
80+
assert result.project_path.joinpath("python_with_cli", "python_with_cli_cli.py").is_file()
81+
assert result.project_path.joinpath("python_with_cli", "example.py").is_file()
82+
assert result.project_path.joinpath("containers", "Containerfile").is_file()
83+
assert not result.project_path.joinpath("containers", "Dockerfile").is_file()
84+
85+
86+
def test_bake_project_uv_cli_podman(cookies, bake_project_uv_cli_podman_data):
87+
result = cookies.bake(extra_context=bake_project_uv_cli_podman_data)
88+
89+
assert result.exit_code == 0
90+
assert result.exception is None
91+
assert result.project_path.name == "python-with-cli"
92+
assert result.project_path.is_dir()
93+
assert result.project_path.joinpath("README.md").is_file()
94+
assert not result.project_path.joinpath("requirements.txt").is_file()
95+
assert not result.project_path.joinpath("requirements-dev.txt").is_file()
3996
assert result.project_path.joinpath("python_with_cli").is_dir()
4097
assert result.project_path.joinpath("python_with_cli", "python_with_cli_cli.py").is_file()
4198
assert result.project_path.joinpath("python_with_cli", "example.py").is_file()
@@ -51,6 +108,25 @@ def test_bake_project_cli_docker(cookies, bake_project_cli_docker_data):
51108
assert result.project_path.name == "python-with-cli"
52109
assert result.project_path.is_dir()
53110
assert result.project_path.joinpath("README.md").is_file()
111+
assert result.project_path.joinpath("requirements.txt").is_file()
112+
assert result.project_path.joinpath("requirements-dev.txt").is_file()
113+
assert result.project_path.joinpath("python_with_cli").is_dir()
114+
assert result.project_path.joinpath("python_with_cli", "python_with_cli_cli.py").is_file()
115+
assert result.project_path.joinpath("python_with_cli", "example.py").is_file()
116+
assert not result.project_path.joinpath("containers", "Containerfile").is_file()
117+
assert result.project_path.joinpath("containers", "Dockerfile").is_file()
118+
119+
120+
def test_bake_project_uv_cli_docker(cookies, bake_project_uv_cli_docker_data):
121+
result = cookies.bake(extra_context=bake_project_uv_cli_docker_data)
122+
123+
assert result.exit_code == 0
124+
assert result.exception is None
125+
assert result.project_path.name == "python-with-cli"
126+
assert result.project_path.is_dir()
127+
assert result.project_path.joinpath("README.md").is_file()
128+
assert not result.project_path.joinpath("requirements.txt").is_file()
129+
assert not result.project_path.joinpath("requirements-dev.txt").is_file()
54130
assert result.project_path.joinpath("python_with_cli").is_dir()
55131
assert result.project_path.joinpath("python_with_cli", "python_with_cli_cli.py").is_file()
56132
assert result.project_path.joinpath("python_with_cli", "example.py").is_file()

{{cookiecutter.git_repo_name}}/Makefile

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Makefile for project needs
22
# Author: Ben Trachtenberg
3-
# Version: 1.0.9
3+
# Version: 2.0.0
44
#
55

66
.PHONY: all info build build-container coverage format pylint pytest start-container stop-container remove-container \
7-
gh-pages check-vuln
7+
gh-pages check-vuln pip-export
88

99
info:
1010
@echo "make options"
@@ -22,21 +22,13 @@ info:
2222
@echo " remove-container To remove the container"
2323
{% if cookiecutter.library_documents_location == 'github-pages' %} @echo " gh-pages To create the GitHub pages"{% endif %}
2424

25+
{% if cookiecutter.package_manager == 'pip' %}
26+
2527
all: format pylint coverage check-security check-vuln
2628

2729
build:
2830
@python -m build
2931

30-
{% if cookiecutter.container_runtime == "podman" %}
31-
build-container:
32-
@cd containers && podman build --ssh=default --build-arg=build_branch=main -t {{ cookiecutter.git_repo_name }}:latest -f Containerfile
33-
{% endif %}
34-
35-
{% if cookiecutter.container_runtime == "docker" %}
36-
build-container:
37-
@cd containers && docker build --ssh=default --build-arg=build_branch=main -t {{ cookiecutter.git_repo_name }}:latest -f Dockerfile
38-
{% endif %}
39-
4032
coverage:
4133
@pytest --cov --cov-report=html -vvv
4234

@@ -50,14 +42,59 @@ pylint:
5042
pytest:
5143
@pytest --cov -vvv
5244

45+
check-vuln:
46+
@pip-audit -r requirements.txt
47+
48+
check-security:
49+
@bandit -c pyproject.toml -r .
50+
5351
{% if cookiecutter.library_documents_location == 'github-pages' %}
5452
gh-pages:
5553
@rm -rf ./docs/source/code
5654
@sphinx-apidoc -o ./docs/source/code ./{{cookiecutter.__library_name}}
5755
@sphinx-build ./docs ./docs/gh-pages
5856
{% endif %}
5957

58+
{% elif cookiecutter.package_manager == 'uv' %}
59+
60+
all: format pylint coverage check-security pip-export
61+
62+
build:
63+
@uv build --wheel --sdist
64+
65+
coverage:
66+
@uv run pytest --cov --cov-report=html -vvv
67+
68+
format:
69+
@uv run black {{cookiecutter.__library_name}}/
70+
@uv run black tests/
71+
72+
pylint:
73+
@uv run pylint {{cookiecutter.__library_name}}/
74+
75+
pytest:
76+
@uv run pytest --cov -vvv
77+
78+
check-security:
79+
@uv run bandit -c pyproject.toml -r .
80+
81+
pip-export:
82+
@uv export --no-dev --no-emit-project --no-editable > requirements.txt
83+
@uv export --no-emit-project --no-editable > requirements-dev.txt
84+
85+
{% if cookiecutter.library_documents_location == 'github-pages' %}
86+
gh-pages:
87+
@rm -rf ./docs/source/code
88+
@uv run sphinx-apidoc -o ./docs/source/code ./{{cookiecutter.__library_name}}
89+
@uv run sphinx-build ./docs ./docs/gh-pages
90+
{% endif %}
91+
92+
{% endif %}
93+
6094
{% if cookiecutter.container_runtime == "podman" %}
95+
build-container:
96+
@cd containers && podman build --ssh=default --build-arg=build_branch=main -t {{ cookiecutter.git_repo_name }}:latest -f Containerfile
97+
6198
start-container:
6299
@podman run -itd --name {{ cookiecutter.git_repo_name }} -p 8080:8080 localhost/{{ cookiecutter.git_repo_name }}:latest
63100

@@ -69,6 +106,9 @@ remove-container:
69106
{% endif %}
70107

71108
{% if cookiecutter.container_runtime == "docker" %}
109+
build-container:
110+
@cd containers && docker build --ssh=default --build-arg=build_branch=main -t {{ cookiecutter.git_repo_name }}:latest -f Dockerfile
111+
72112
start-container:
73113
@docker run -itd --name {{ cookiecutter.git_repo_name }} -p 8080:8080 localhost/{{ cookiecutter.git_repo_name }}:latest
74114

@@ -78,9 +118,3 @@ stop-container:
78118
remove-container:
79119
@docker rm {{ cookiecutter.git_repo_name }}
80120
{% endif %}
81-
82-
check-vuln:
83-
@pip-audit -r requirements.txt
84-
85-
check-security:
86-
@bandit -c pyproject.toml -r .

0 commit comments

Comments
 (0)