Skip to content

Commit 812039e

Browse files
committed
Merge branch 'fix/linter-path-errors'
2 parents 8d30dce + 1ba7b5c commit 812039e

File tree

10 files changed

+104
-94
lines changed

10 files changed

+104
-94
lines changed

avcmt/ai.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# File: avcmt/ai.py
1616
import os
1717
from importlib import import_module
18+
from pathlib import Path
1819

1920
from jinja2 import Environment, FileSystemLoader
2021

@@ -53,7 +54,7 @@ def generate_with_ai(
5354

5455

5556
def render_prompt(group_name, diff_text):
56-
template_dir = os.path.join(os.path.dirname(__file__), "prompt_templates")
57+
template_dir = Path(__file__).parent / "prompt_templates"
5758
env = Environment(loader=FileSystemLoader(template_dir))
5859
template = env.get_template("commit_message.j2")
5960
return template.render(group_name=group_name, diff_text=diff_text)

avcmt/cli.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@
2020
# Status: Ready to use with the new CommitManager.
2121

2222
import argparse
23-
import os
23+
from pathlib import Path
2424

2525
from dotenv import load_dotenv
2626

2727
from .commit import run_commit_group_all
2828
from .utils import get_log_file, setup_logging
2929

30-
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
31-
dotenv_path = os.path.join(PROJECT_ROOT, ".env")
30+
PROJECT_ROOT = Path(__file__).resolve().parent.parent
31+
dotenv_path = PROJECT_ROOT / ".env"
3232

33-
if os.path.exists(dotenv_path):
33+
if dotenv_path.exists():
3434
load_dotenv(dotenv_path)
3535

3636
# --- API KEY CHECK BLOCK REMOVED FROM HERE ---

avcmt/commit.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
# File: avcmt/commit.py
1616
# Revision v8 - Moved cleaning logic to utils.py
1717

18-
import os
1918
import subprocess
2019
from collections import defaultdict
2120
from datetime import datetime
21+
from pathlib import Path
2222
from typing import Any
2323

2424
from avcmt.ai import generate_with_ai, render_prompt
@@ -63,7 +63,7 @@ def __init__(
6363
self.model = model
6464
self.logger = logger or setup_logging("log/commit.log")
6565
self.kwargs = kwargs
66-
self.dry_run_file = os.path.join("log", "commit_messages_dry_run.md")
66+
self.dry_run_file = Path("log") / "commit_messages_dry_run.md"
6767

6868
def _run_git_command(self, command: list[str]) -> str:
6969
"""Helper to run a git command and handle potential errors."""
@@ -94,23 +94,25 @@ def _get_changed_files(self) -> list[str]:
9494
def _group_files_by_directory(files: list[str]) -> dict[str, list[str]]:
9595
grouped = defaultdict(list)
9696
for file_path in files:
97-
parent_dir = os.path.dirname(file_path) or "root"
97+
parent_dir = str(Path(file_path).parent)
98+
if parent_dir == ".":
99+
parent_dir = "root"
98100
grouped[parent_dir].append(file_path)
99101
return grouped
100102

101103
def _get_diff_for_files(self, files: list[str]) -> str:
102104
return self._run_git_command(["git", "--no-pager", "diff", "--staged", *files])
103105

104106
def _write_dry_run_header(self):
105-
os.makedirs(os.path.dirname(self.dry_run_file), exist_ok=True)
106-
with open(self.dry_run_file, "w", encoding="utf-8") as f:
107+
self.dry_run_file.parent.mkdir(parents=True, exist_ok=True)
108+
with self.dry_run_file.open("w", encoding="utf-8") as f:
107109
ts = datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S (%Z)")
108110
f.write("# AI Semantic Release Commit Messages (Dry Run)\n")
109111
f.write(f"_Last generated: {ts}_\n\n")
110112
f.write("Automatically generated by `avcmt --dry-run`\n\n")
111113

112114
def _write_dry_run_entry(self, group_name: str, commit_message: str):
113-
with open(self.dry_run_file, "a", encoding="utf-8") as f:
115+
with self.dry_run_file.open("a", encoding="utf-8") as f:
114116
f.write(
115117
f"## Group: `{group_name}`\n\n```md\n{commit_message}\n```\n\n---\n\n"
116118
)

avcmt/release.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import subprocess
2121
from collections import defaultdict
2222
from datetime import datetime
23+
from pathlib import Path
2324
from typing import Any
2425

2526
import toml
@@ -175,7 +176,7 @@ def _update_version_file(self):
175176
path, key_path = self.config["version_path"].split(":", 1)
176177
keys = key_path.split(".")
177178
try:
178-
with open(path, "r+", encoding="utf-8") as f:
179+
with Path(path).open("r+", encoding="utf-8") as f:
179180
data = toml.load(f)
180181
# Traverse to update the version
181182
temp_data = data
@@ -246,14 +247,14 @@ def _update_changelog(self):
246247
Updates the changelog file by inserting the new formatted section
247248
at the correct position using a precise split method.
248249
"""
249-
path = self.config["changelog_file"]
250+
path = Path(self.config["changelog_file"])
250251
new_section = self._generate_formatted_changelog_section()
251252
marker = "<!-- version list -->"
252253

253254
try:
254255
content = ""
255-
if os.path.exists(path):
256-
with open(path, encoding="utf-8") as f:
256+
if path.exists():
257+
with path.open(encoding="utf-8") as f:
257258
content = f.read()
258259
else:
259260
logger.info(f"Changelog file not found at {path}. Creating a new one.")
@@ -268,7 +269,7 @@ def _update_changelog(self):
268269
)
269270
final_content = f"{new_section}\n{content}"
270271

271-
with open(path, "w", encoding="utf-8") as f:
272+
with path.open("w", encoding="utf-8") as f:
272273
f.write(final_content)
273274
logger.info(f"Updated {path} with version {self.new_version}")
274275
except Exception as e:

avcmt/utils.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,33 @@
1616
# Revision v2 - Added clean_ai_response and simplified extraction logic.
1717

1818
import logging
19-
import os
2019
import re
2120
import time
21+
from pathlib import Path
2222

2323

24-
def get_log_dir():
25-
log_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "log")
26-
os.makedirs(log_dir, exist_ok=True)
24+
def get_log_dir() -> Path:
25+
log_dir = Path(__file__).parent.parent / "log"
26+
log_dir.mkdir(parents=True, exist_ok=True)
2727
return log_dir
2828

2929

30-
def get_log_file():
31-
return os.path.join(get_log_dir(), "commit_group_all.log")
30+
def get_log_file() -> Path:
31+
return get_log_dir() / "commit_group_all.log"
3232

3333

34-
def get_dry_run_file():
35-
return os.path.join(get_log_dir(), "commit_messages_dry_run.md")
34+
def get_dry_run_file() -> Path:
35+
return get_log_dir() / "commit_messages_dry_run.md"
3636

3737

38-
def is_recent_dry_run(file_path, max_age_minutes=10):
38+
def is_recent_dry_run(file_path: Path | str, max_age_minutes=10) -> bool:
3939
"""
4040
Cek apakah file dry-run commit masih dalam rentang waktu tertentu (default 10 menit).
4141
"""
42-
if not os.path.exists(file_path):
42+
path = Path(file_path)
43+
if not path.exists():
4344
return False
44-
mtime = os.path.getmtime(file_path)
45+
mtime = path.stat().st_mtime
4546
return (time.time() - mtime) <= max_age_minutes * 60
4647

4748

@@ -76,15 +77,16 @@ def clean_ai_response(raw_message: str) -> str:
7677
return "\n".join(commit_lines).strip()
7778

7879

79-
def extract_commit_messages_from_md(filepath: str) -> dict[str, str]:
80+
def extract_commit_messages_from_md(filepath: Path | str) -> dict[str, str]:
8081
"""
8182
Mengekstrak pesan commit per grup dari file Markdown dry-run.
8283
Versi ini lebih sederhana karena diasumsikan file sudah bersih.
8384
"""
84-
if not os.path.exists(filepath):
85+
path = Path(filepath)
86+
if not path.exists():
8587
return {}
8688

87-
with open(filepath, encoding="utf-8") as f:
89+
with path.open(encoding="utf-8") as f:
8890
content = f.read()
8991

9092
messages = {}
@@ -98,16 +100,16 @@ def extract_commit_messages_from_md(filepath: str) -> dict[str, str]:
98100
return messages
99101

100102

101-
def setup_logging(log_file="commit_group_all.log"):
103+
def setup_logging(log_file: Path | str = "commit_group_all.log"):
102104
logger = logging.getLogger(__name__)
103105
if not logger.hasHandlers():
104-
log_dir = os.path.dirname(log_file)
105-
if log_dir:
106-
os.makedirs(log_dir, exist_ok=True)
106+
log_path = Path(log_file)
107+
log_path.parent.mkdir(parents=True, exist_ok=True)
108+
107109
logger.setLevel(logging.INFO)
108110
formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s")
109111

110-
fh = logging.FileHandler(log_file, mode="w", encoding="utf-8")
112+
fh = logging.FileHandler(log_path, mode="w", encoding="utf-8")
111113
fh.setFormatter(formatter)
112114
logger.addHandler(fh)
113115

poetry.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ include = [ "avcmt/*",]
1313
[[tool.poetry.packages]]
1414
include = "avcmt"
1515

16-
[tool.ruff]
17-
target-version = "py310"
16+
[tool.avcmt.release]
17+
version_path = "pyproject.toml:tool.poetry.version"
18+
changelog_file = "CHANGELOG.md"
19+
branch = "main"
20+
publish_to_pypi = true
21+
repo_url = "https://github.com/andyvandaric/avcmt-py"
1822

1923
[tool.poetry.urls]
2024
Homepage = "https://avcmt.avandaric.live"
@@ -24,8 +28,6 @@ Documentation = "https://avcmt.avandaric.live/docs"
2428
[tool.poetry.dependencies]
2529
python = "^3.10"
2630
requests = "^2.32"
27-
jinja2 = "^3.1.4"
28-
python-dotenv = "^1.0.1"
2931
rich = "^14.0.0"
3032

3133
[tool.poetry.scripts]
@@ -39,23 +41,19 @@ helper = "scripts.helper:main"
3941
preflight = "scripts.preflight:main"
4042
semrel = "scripts.semrel:main"
4143

44+
[tool.ruff]
45+
target-version = "py310"
46+
4247
[tool.ruff.lint]
4348
preview = true
4449
select = [ "E", "F", "I", "N", "UP", "B", "C90", "SIM", "TID", "PL", "PTH", "NPY", "PD", "PERF", "RUF",]
4550
fixable = [ "ALL",]
46-
ignore = [ "D", "ANN", "COM812", "ISC001", "T201", "S603", "S607", "S404", "PTH", "S701", "B904", "TRY003", "EM102", "E501", "PERF203", "PLR0913", "PLR0917",]
51+
ignore = [ "D", "ANN", "COM812", "ISC001", "T201", "S603", "S607", "S404", "S701", "B904", "TRY003", "EM102", "E501", "PERF203", "PLR0913", "PLR0917",]
4752

4853
[tool.ruff.format]
4954
quote-style = "double"
5055
indent-style = "space"
5156

52-
[tool.avcmt.release]
53-
version_path = "pyproject.toml:tool.poetry.version"
54-
changelog_file = "CHANGELOG.md"
55-
branch = "main"
56-
publish_to_pypi = true
57-
repo_url = "https://github.com/andyvandaric/avcmt-py"
58-
5957
[tool.ruff.lint.per-file-ignores]
6058
"__init__.py" = [ "F401",]
6159

@@ -67,9 +65,9 @@ known-first-party = [ "avcmt",]
6765
changelog_file = "CHANGELOG.md"
6866

6967
[tool.poetry.group.dev.dependencies]
70-
python-dotenv = "^1.1.0"
68+
jinja2 = "^3.1.4"
69+
python-dotenv = "^1.0.1"
7170
ruff = "^0.11.13"
7271
pre-commit = "^4.2.0"
7372
python-semantic-release = "^10.1.0"
74-
rich = "^14.0.0"
7573
toml = "^0.10.2"

0 commit comments

Comments
 (0)