Skip to content

Commit d464399

Browse files
committed
fix project init script + gh action
1 parent de4f559 commit d464399

File tree

5 files changed

+133
-32
lines changed

5 files changed

+133
-32
lines changed

.github/workflows/tests.yml

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,30 @@ jobs:
2222
run: |
2323
uv pip compile pyproject.toml -o requirements.txt
2424
uv pip compile pyproject.toml --extra dev -o requirements-dev.txt
25+
uv venv
2526
uv pip sync requirements.txt requirements-dev.txt
2627
27-
- name: Run MyPy
28-
run: uv pip run mypy src
29-
28+
- name: Determine module name
29+
id: module
30+
run: |
31+
if [ -d "src" ]; then
32+
echo "name=src" >> $GITHUB_OUTPUT
33+
else
34+
MODULE_NAME=$(basename $(find . -maxdepth 1 -type d -not -path "*/\.*" -not -path "./tests" -not -path "./scripts" -not -path "./docker" -not -path "." | sort | head -1))
35+
echo "name=$MODULE_NAME" >> $GITHUB_OUTPUT
36+
fi
37+
3038
- name: Run Linter
31-
run: uv pip run ruff check src
39+
run: uv pip run ruff check --fix ${{ steps.module.outputs.name }}
3240

3341
- name: Run Formatter
34-
run: uv pip run ruff format src
42+
run: uv pip run ruff format ${{ steps.module.outputs.name }}
3543

3644
- name: Run Tests
37-
run: uv pip run pytest tests --cov=src --cov-report=term-missing --cov-report=xml
45+
run: uv pip run pytest tests --cov=${{ steps.module.outputs.name }} --cov-report=term-missing --cov-report=xml
46+
47+
- name: Run MyPy
48+
run: uv pip run mypy ${{ steps.module.outputs.name }}
3849

3950
- name: Upload coverage to Codecov
4051
uses: codecov/codecov-action@v3

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ docker/.env
1515
.pytest_cache/*
1616
.ruff_cache/*
1717
.aider*
18+
CLAUDE.md

.pre-commit-config.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
repos:
22
- repo: local
33
hooks:
4-
- id: mypy
5-
name: Run MyPy
6-
entry: make mypy
7-
language: system
8-
always_run: true
9-
pass_filenames: false
104
- id: lint
115
name: Run Linter
126
entry: make lint
@@ -25,3 +19,9 @@ repos:
2519
language: system
2620
always_run: true
2721
pass_filenames: false
22+
- id: mypy
23+
name: Run MyPy
24+
entry: make mypy
25+
language: system
26+
always_run: true
27+
pass_filenames: false

Makefile

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
.PHONY: compile-deps setup clean-pyc clean-test clean-venv clean test mypy lint format check clean-example dev-env refresh-containers rebuild-images build-image push-image
22

3+
# Module name - will be updated by init script
4+
MODULE_NAME := src
5+
36
# Development Setup
47
#################
58
compile-deps: # Compile dependencies from pyproject.toml
@@ -46,18 +49,18 @@ clean: clean-pyc clean-test clean-venv
4649
# Testing and Quality Checks
4750
#########################
4851
test: setup # Run pytest with coverage
49-
uv run -m pytest tests --cov=src --cov-report=term-missing
52+
uv run -m pytest tests --cov=$(MODULE_NAME) --cov-report=term-missing
5053

5154
mypy: setup # Run type checking
52-
uv run -m mypy src
55+
uv run -m mypy $(MODULE_NAME)
5356

54-
lint: setup # Run ruff linter
55-
uv run -m ruff check src
57+
lint: setup # Run ruff linter with auto-fix
58+
uv run -m ruff check --fix $(MODULE_NAME)
5659

5760
format: setup # Run ruff formatter
58-
uv run -m ruff format src
61+
uv run -m ruff format $(MODULE_NAME)
5962

60-
check: setup test mypy lint format # Run all quality checks
63+
check: setup lint format test mypy # Run all quality checks
6164

6265
# Project Management
6366
##################

scripts/init_project.py

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ def main() -> None:
7575
"Author email", get_git_config("email") or "[email protected]"
7676
)
7777

78+
# Update project information
79+
print("📝 Updating project configuration...")
80+
update_pyproject_toml(
81+
project_name,
82+
project_description,
83+
author_name,
84+
author_email
85+
)
86+
7887
# Handle example code
7988
code_choice = prompt_with_default(
8089
"How would you like to handle example code?\n"
@@ -84,36 +93,101 @@ def main() -> None:
8493
"Choose option", "1"
8594
)
8695

96+
# Create module directory with project name (replacing src)
97+
project_module_name = project_name.replace("-", "_").lower()
98+
99+
# Always update the Makefile to use the new module name
100+
print(f"🔧 Updating Makefile to use module name: {project_module_name}")
101+
makefile_path = Path("Makefile")
102+
with open(makefile_path, "r") as f:
103+
makefile_content = f.read()
104+
105+
# Replace module name in Makefile
106+
updated_makefile = makefile_content.replace("MODULE_NAME := src", f"MODULE_NAME := {project_module_name}")
107+
108+
with open(makefile_path, "w") as f:
109+
f.write(updated_makefile)
110+
111+
# Always update pyproject.toml to point to the new module directory
112+
print(f"📦 Updating pyproject.toml for module: {project_module_name}")
113+
pyproject_path = Path("pyproject.toml")
114+
with open(pyproject_path, "rb") as f:
115+
config = tomli.load(f)
116+
117+
# Update packages from src to new module name
118+
if "tool" in config and "hatch" in config["tool"] and "build" in config["tool"]["hatch"] and "targets" in config["tool"]["hatch"]["build"] and "wheel" in config["tool"]["hatch"]["build"]["targets"]:
119+
config["tool"]["hatch"]["build"]["targets"]["wheel"]["packages"] = [project_module_name]
120+
121+
with open(pyproject_path, "wb") as f:
122+
tomli_w.dump(config, f)
123+
124+
# Create the new module directory if it doesn't exist
125+
if not os.path.exists(project_module_name):
126+
print(f"📁 Creating module directory: {project_module_name}")
127+
os.mkdir(project_module_name)
128+
# Create __init__.py
129+
with open(f"{project_module_name}/__init__.py", "w") as f:
130+
f.write(f'"""Main package for {project_name}."""\n')
131+
132+
# Copy src content to new module directory if src exists
133+
if os.path.exists("src") and project_module_name != "src":
134+
print(f"📦 Copying content from src to {project_module_name}...")
135+
for item in os.listdir("src"):
136+
src_path = os.path.join("src", item)
137+
dest_path = os.path.join(project_module_name, item)
138+
139+
if os.path.isfile(src_path):
140+
with open(src_path, "r") as src_file:
141+
content = src_file.read()
142+
with open(dest_path, "w") as dest_file:
143+
dest_file.write(content)
144+
145+
# Remove the old src directory after copying
146+
print("🗑️ Removing old src directory...")
147+
run_command("rm -rf src")
148+
87149
if code_choice == "2":
88150
print("📝 Creating minimal placeholder test...")
89-
# Create minimal src module
90-
with open("src/example.py", "w") as f:
151+
# Create minimal module
152+
with open(f"{project_module_name}/example.py", "w") as f:
91153
f.write("""def add(a: int, b: int) -> int:
92154
\"\"\"Add two numbers.\"\"\"
93155
return a + b
94156
""")
95157

96158
# Create minimal test
97159
with open("tests/test_example.py", "w") as f:
98-
f.write("""from src.example import add
160+
f.write(f"""from {project_module_name}.example import add
99161
100162
def test_add():
101163
assert add(1, 2) == 3
102164
""")
103165
elif code_choice == "3":
104166
print("🧹 Removing all example code...")
105167
run_command("make clean-example")
168+
# Create __init__.py in tests
169+
with open("tests/__init__.py", "w") as f:
170+
f.write("")
106171
else:
107-
print("📚 Keeping example code for reference...")
172+
print("📚 Updating example code imports for new module name...")
173+
# Update example.py to use new module name
174+
if os.path.exists("src/example.py"):
175+
with open("src/example.py", "r") as f:
176+
example_content = f.read()
177+
# Save it to new module directory
178+
with open(f"{project_module_name}/example.py", "w") as f:
179+
f.write(example_content)
180+
181+
# Update test imports
182+
if os.path.exists("tests/test_example.py"):
183+
with open("tests/test_example.py", "r") as f:
184+
test_content = f.read()
185+
updated_test = test_content.replace("from src.", f"from {project_module_name}.")
186+
with open("tests/test_example.py", "w") as f:
187+
f.write(updated_test)
108188

109-
# Update pyproject.toml
110-
print("📝 Updating project configuration...")
111-
update_pyproject_toml(
112-
project_name,
113-
project_description,
114-
author_name,
115-
author_email
116-
)
189+
# Update already happened above, fix the duplicate
190+
# The configuration has already been updated above
117191

118192
# Get current directory name and handle renaming
119193
current_dir = os.path.basename(os.getcwd())
@@ -124,6 +198,18 @@ def test_add():
124198
if os.path.exists(new_dir):
125199
print(f"⚠️ Directory {project_name} already exists. Keeping current directory name.")
126200
else:
201+
# Update source code directory references in Makefile
202+
makefile_path = Path("Makefile")
203+
with open(makefile_path, "r") as f:
204+
makefile_content = f.read()
205+
206+
# Replace any hardcoded references to python-collab-template in the Makefile
207+
updated_makefile = makefile_content.replace("python-collab-template", project_name)
208+
209+
with open(makefile_path, "w") as f:
210+
f.write(updated_makefile)
211+
212+
# Now rename the directory
127213
os.chdir(parent_dir)
128214
os.rename(current_dir, project_name)
129215
os.chdir(project_name)
@@ -155,9 +241,9 @@ def test_add():
155241
else:
156242
print("⏩ Skipping pre-commit hooks setup")
157243

158-
# Initial commit
244+
# Initial commit without running pre-commit hooks
159245
run_command("git add .")
160-
run_command('git commit -m "feat: Initial project setup"')
246+
run_command('git commit -m "feat: Initial project setup" --no-verify')
161247

162248
print("✨ Project initialized successfully!")
163249
print("""

0 commit comments

Comments
 (0)