11import argparse
22import re
3- import shutil
43import subprocess # noqa: S404
54from collections import defaultdict
65from dataclasses import dataclass
1211
1312@dataclass
1413class ConventionalCommit :
15- """A structured representation of a conventional commit.
14+ """
15+ A structured representation of a conventional commit with enhanced metadata processing.
1616
1717 Parameters
1818 ----------
@@ -42,7 +42,8 @@ class ConventionalCommit:
4242 date : datetime
4343
4444 def generate_url (self ) -> str :
45- """Generate a formatted URL for the conference entry.
45+ """
46+ Generate a formatted URL for the conference entry.
4647
4748 Returns
4849 -------
@@ -58,7 +59,8 @@ def generate_url(self) -> str:
5859 return f"https://pythondeadlin.es/conference/{ sanitized } "
5960
6061 def to_markdown (self ) -> str :
61- """Convert the commit to a markdown-formatted string.
62+ """
63+ Convert the commit to a markdown-formatted string.
6264
6365 Returns
6466 -------
@@ -74,52 +76,30 @@ def to_markdown(self) -> str:
7476
7577
7678class GitCommitParser :
77- """Analyzes git repository history for conference-related commits.
79+ """
80+ Analyzes git repository history for conference-related commits with markdown output capabilities.
7881
7982 Parameters
8083 ----------
8184 repo_path : str, optional
8285 Path to the git repository, by default "."
83- prefixes : List[str] | None , optional
86+ prefixes : List[str], optional
8487 List of commit prefixes to search for, by default ["cfp", "conf"]
8588 days : int, optional
8689 Number of days to look back in history, by default None
8790 """
8891
8992 def __init__ (self , repo_path : str = "." , prefixes : list [str ] | None = None , days : int | None = None ):
9093 self .repo_path = repo_path
91- self .git_path = shutil .which ("git" )
9294 self .prefixes = prefixes or ["cfp" , "conf" ]
9395 self .days = days
9496 self ._prefix_pattern = re .compile (rf'^({ "|" .join (map (re .escape , self .prefixes ))} ):\s*(.+)$' , re .IGNORECASE )
95- if not self .git_path :
96- raise RuntimeError ("Git executable not found in PATH" )
9797
9898 def _execute_git_command (self , command : list [str ]) -> str :
9999 """Implementation remains unchanged."""
100- # Validate input commands against allowed list
101- allowed_commands = {
102- "log" ,
103- "show" ,
104- "diff" ,
105- "status" ,
106- "rev-parse" ,
107- "--format" ,
108- "--pretty" ,
109- "--no-merges" ,
110- "--name-only" ,
111- "HEAD" ,
112- "origin" ,
113- "--abbrev-ref" ,
114- # Add other allowed commands as needed
115- }
116-
117- if not all (cmd .split ("=" )[0 ] in allowed_commands for cmd in command ):
118- raise ValueError ("Invalid or unauthorized git command" )
119-
120100 try :
121101 result = subprocess .run (
122- [self . git_path , * command ], # noqa: S603
102+ ["git" , * command ], # noqa: S603, S607
123103 cwd = self .repo_path ,
124104 capture_output = True ,
125105 text = True ,
@@ -174,7 +154,8 @@ def get_conventional_commits(self) -> list[ConventionalCommit]:
174154 return commits
175155
176156 def _generate_link_list (self , commits : list [ConventionalCommit ]) -> str :
177- """Generate a comma-separated list of markdown-formatted links.
157+ """
158+ Generate a comma-separated list of markdown-formatted links.
178159
179160 Parameters
180161 ----------
@@ -202,7 +183,8 @@ def _generate_link_list(self, commits: list[ConventionalCommit]) -> str:
202183 return f"{ ', ' .join (links [:- 1 ])} , and { links [- 1 ]} "
203184
204185 def generate_markdown_report (self ) -> str :
205- """Generate a markdown-formatted report of commits grouped by type.
186+ """
187+ Generate a markdown-formatted report of commits grouped by type.
206188
207189 Returns
208190 -------
@@ -260,7 +242,8 @@ def parse_arguments() -> argparse.Namespace:
260242
261243
262244def main ():
263- """Main execution function with markdown report generation.
245+ """
246+ Main execution function with markdown report generation.
264247
265248 Notes
266249 -----
0 commit comments