Skip to content

Commit cee19d8

Browse files
committed
Process files from a list, or just README.md or README
Cache based on uv changes Remove unnecessary verbosity from Junie guidelines
1 parent d51b8c2 commit cee19d8

12 files changed

Lines changed: 275 additions & 280 deletions

File tree

.github/workflows/pre-commit.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
with:
2020
cache: pip
2121
python-version-file: .python-version
22+
cache-dependency-path: uv.lock
2223
- uses: andrewaylett/pre-commit-action@c42755522779836e1cb55c8c3d1fa3b4f69167d4 # v4
2324
- name: Install the latest version of uv
2425
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v6

.junie/guidelines.md

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,50 +26,6 @@ The project uses pytest for testing. To run all tests:
2626
uv run pytest
2727
```
2828

29-
To run a specific test file:
30-
31-
```bash
32-
uv run pytest tests/test_file.py
33-
```
34-
35-
To run tests with verbose output:
36-
37-
```bash
38-
uv run pytest -v
39-
```
40-
41-
### Adding New Tests
42-
43-
1. Create a new test file in the `tests/` directory with a name starting with `test_`.
44-
2. Import pytest and the modules you want to test.
45-
3. Write test functions with names starting with `test_`.
46-
47-
#### Example Test with Cog
48-
49-
Here's an example of a test that uses cog to generate code:
50-
51-
```python
52-
"""Example test file to demonstrate testing with cog."""
53-
54-
import pytest
55-
56-
def example_function_with_cog():
57-
"""Example function with cog-generated content."""
58-
# [[[cog
59-
# import cog
60-
# numbers = [1, 2, 3, 4, 5]
61-
# cog.outl(" result = sum([" + ", ".join(str(n) for n in numbers) + "])")
62-
# ]]]
63-
result = sum([1, 2, 3, 4, 5])
64-
# [[[end]]]
65-
return result
66-
67-
def test_example_function_with_cog():
68-
"""Test that the example function returns the expected value."""
69-
result = example_function_with_cog()
70-
assert result == 15
71-
```
72-
7329
## Additional Development Information
7430

7531
### How Cog Works

.pre-commit-config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,7 @@ repos:
4747
rev: 0.7.16
4848
hooks:
4949
- id: uv-lock
50+
#- repo: https://github.com/andrewaylett/pre-commit-hooks
51+
# rev: v0.1.0
52+
# hooks:
53+
# - id: cog

README.md

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,41 @@
11
# Runs Cog as a pre-commit hook
22

3-
Rather than adding a local pre-commit hook to each of your repositories:
4-
5-
```yaml
3+
Add this repo to your `.pre-commit-config.yaml`:
4+
5+
<!-- [[[cog
6+
result = sp.run(
7+
["git", "describe", "--tags"],
8+
capture_output=True,
9+
text=True,
10+
check=True
11+
)
12+
version = result.stdout.strip().split('-')[0]
13+
cog.outl(f"""```yaml
614
repos:
7-
- repo: local
15+
- repo: https://github.com/andrewaylett/pre-commit-hooks
16+
rev: {version}
817
hooks:
9-
- # https://github.com/nedbat/cog/issues/21#issuecomment-1919626992
10-
id: cog
11-
name: cog (regenerate files)
12-
language: python
13-
additional_dependencies:
14-
- cogapp
15-
entry: bash -c 'git grep -lzF "[[[""cog" | xargs -0 cog -r -c -p "import subprocess as sp, re, os, sys, pathlib as pl, cog" "$@"'
16-
pass_filenames: false
17-
always_run: true
18-
```
19-
20-
We can use this repo to do the same thing:
21-
18+
- id: cog
19+
```""")
20+
]]] -->
2221
```yaml
2322
repos:
2423
- repo: https://github.com/andrewaylett/pre-commit-hooks
24+
rev: v0.1.0
2525
hooks:
2626
- id: cog
2727
```
28+
<!-- [[[end]]] -->
2829
2930
## Development
3031
3132
### Running Tests
3233
3334
This project uses pytest for testing. To run the tests:
3435
35-
1. Install development dependencies:
36-
```bash
37-
uv pip install -e ".[dev]"
38-
```
39-
40-
2. Run the tests:
41-
```bash
42-
uv run pytest
43-
```
36+
```bash
37+
uv run pytest
38+
```
4439

4540
The test suite includes:
4641
- Tests for the pre-commit hook functionality

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[project]
2-
name = "pre-commit-hooks"
2+
name = "andrewaylett-pre-commit-hooks"
33
version = "0.1.0"
44
description = "Andrew's pre-commit hooks"
55
readme = "README.md"
@@ -9,7 +9,6 @@ authors = [
99
requires-python = ">=3.13"
1010
dependencies = [
1111
"cogapp>=3.5.1",
12-
"python-ripgrep>=0.0.8",
1312
]
1413

1514
[dependency-groups]
@@ -42,7 +41,7 @@ testpaths = ["tests"]
4241
python_files = "test_*.py"
4342

4443
[project.scripts]
45-
pre-commit-cog = "pre_commit_hooks.cog:main"
44+
pre-commit-cog = "andrewaylett_pre_commit_hooks.cog:main"
4645

4746
[build-system]
4847
requires = ["hatchling"]
File renamed without changes.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import os
2+
import sys
3+
4+
from cogapp import Cog
5+
6+
7+
def find_cog_files() -> set[str]:
8+
"""Find files to process with cog.
9+
10+
Looks for the first file that exists of `.cogfiles`, `README.md` or `README`.
11+
- If `.cogfiles` exists, use it as a list of files to check
12+
- If a README file exists, process just that file
13+
- If neither exists, exit with an error
14+
"""
15+
try:
16+
# Check for .cogfiles first
17+
if os.path.exists(".cogfiles"):
18+
print("Using .cogfiles to determine which files to process")
19+
with open(".cogfiles") as f:
20+
# Read the file list, strip whitespace, and filter out empty lines
21+
files = {line.strip() for line in f if line.strip()}
22+
if not files:
23+
print("Error: .cogfiles exists but is empty", file=sys.stderr)
24+
sys.exit(1)
25+
return files
26+
27+
# Check for README.md next
28+
elif os.path.exists("README.md"):
29+
print("Processing README.md")
30+
return {"README.md"}
31+
32+
# Check for README last
33+
elif os.path.exists("README"):
34+
print("Processing README")
35+
return {"README"}
36+
37+
# If none of the files exist, exit with an error
38+
else:
39+
print(
40+
"Error: Could not find .cogfiles, README.md, or README", file=sys.stderr
41+
)
42+
sys.exit(1)
43+
44+
except Exception as e:
45+
print(f"Error finding cog files: {e}", file=sys.stderr)
46+
sys.exit(1)
47+
48+
49+
def run_cog_on_files(files: set[str]) -> bool:
50+
"""Run cog on the specified files.
51+
52+
Returns True if all files were processed successfully, False otherwise.
53+
"""
54+
if not files:
55+
print("No files with cog markers found.")
56+
return True
57+
58+
print(f"Running cog on {len(files)} files...")
59+
success = True
60+
61+
# Create a Cog instance with the appropriate options
62+
cog_instance = Cog()
63+
64+
# Set options equivalent to command-line flags
65+
cog_instance.options.replace = True # -r: replace in-place
66+
cog_instance.options.checksum = True # -c: checksum
67+
cog_instance.options.verbosity = 3
68+
69+
# Add imports to globals (equivalent to -p option)
70+
cog_instance.options.defines = {
71+
"subprocess": __import__("subprocess"),
72+
"sp": __import__("subprocess"),
73+
"re": __import__("re"),
74+
"os": __import__("os"),
75+
"sys": __import__("sys"),
76+
"pathlib": __import__("pathlib"),
77+
"pl": __import__("pathlib"),
78+
"cog": __import__("cogapp.cogapp"),
79+
}
80+
81+
for file in files:
82+
try:
83+
# Process the content using process_string
84+
cog_instance.process_one_file(file)
85+
86+
except Exception as e:
87+
print(f"Error processing {file}: {e}", file=sys.stderr)
88+
success = False
89+
90+
return success
91+
92+
93+
def main() -> None:
94+
"""Find files with cog markers and run cog on them."""
95+
files = find_cog_files()
96+
success = run_cog_on_files(files)
97+
98+
if not success:
99+
sys.exit(1)

src/pre_commit_hooks/cog.py

Lines changed: 0 additions & 89 deletions
This file was deleted.

tests/test_cog_file.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ def cog_content():
2222
2323
def example_function():
2424
"""Example function with cog-generated content."""
25-
# [[[cog
25+
# [ [ [cog
2626
# import cog
2727
# cog.outl(" print('This content was generated by cog!')")
2828
# ]]]
2929
# Content will be generated here
3030
# [[[end]]]
3131
3232
return "Hello, world!"
33-
'''
33+
'''.replace("[ [ [", "[[[")
3434

3535

3636
@pytest.fixture

0 commit comments

Comments
 (0)