|  | 
| 7 | 7 | import json | 
| 8 | 8 | from typing import Optional, Dict, Any, List, Union | 
| 9 | 9 | from datetime import datetime, timedelta | 
|  | 10 | +from collections import defaultdict | 
| 10 | 11 | 
 | 
| 11 | 12 | from git_py_stats.git_operations import run_git_command | 
| 12 | 13 | 
 | 
| @@ -305,6 +306,94 @@ def changelogs(config: Dict[str, Union[str, int]], author: Optional[str] = None) | 
| 305 | 306 |         next_date = date  # Update next_date for the next iteration | 
| 306 | 307 | 
 | 
| 307 | 308 | 
 | 
|  | 309 | +def commits_calendar_by_author(config: Dict[str, Union[str, int]], author: Optional[str]) -> None: | 
|  | 310 | +    """ | 
|  | 311 | +    Displays a calendar of commits by author | 
|  | 312 | +
 | 
|  | 313 | +    Args: | 
|  | 314 | +        config: Dict[str, Union[str, int]]: Config dictionary holding env vars. | 
|  | 315 | +        author: Optional[str]: The author's name to filter commits by. | 
|  | 316 | +
 | 
|  | 317 | +    Returns: | 
|  | 318 | +        None | 
|  | 319 | +    """ | 
|  | 320 | + | 
|  | 321 | +    # Initialize variables similar to the Bash version | 
|  | 322 | +    author_option = f"--author={author}" if author else "" | 
|  | 323 | + | 
|  | 324 | +    # Grab the config options from our config.py. | 
|  | 325 | +    # config.py should give fallbacks for these, but for sanity, | 
|  | 326 | +    # lets also provide some defaults just in case. | 
|  | 327 | +    merges = config.get("merges", "--no-merges") | 
|  | 328 | +    since = config.get("since", "") | 
|  | 329 | +    until = config.get("until", "") | 
|  | 330 | +    log_options = config.get("log_options", "") | 
|  | 331 | +    pathspec = config.get("pathspec", "") | 
|  | 332 | + | 
|  | 333 | +    # Original git command: | 
|  | 334 | +    # git -c log.showSignature=false log --use-mailmap $_merges \ | 
|  | 335 | +    #    --date=iso --author="$author" "$_since" "$_until" $_log_options \ | 
|  | 336 | +    #    --pretty='%ad' $_pathspec | 
|  | 337 | +    cmd = [ | 
|  | 338 | +        "git", | 
|  | 339 | +        "-c", | 
|  | 340 | +        "log.showSignature=false", | 
|  | 341 | +        "log", | 
|  | 342 | +        "--use-mailmap", | 
|  | 343 | +        "--date=iso", | 
|  | 344 | +        f"--author={author}", | 
|  | 345 | +        "--pretty=%ad", | 
|  | 346 | +    ] | 
|  | 347 | + | 
|  | 348 | +    if author_option: | 
|  | 349 | +        cmd.append(author_option) | 
|  | 350 | + | 
|  | 351 | +    cmd.extend([since, until, log_options, merges, pathspec]) | 
|  | 352 | + | 
|  | 353 | +    # Remove any empty space from the cmd | 
|  | 354 | +    cmd = [arg for arg in cmd if arg] | 
|  | 355 | + | 
|  | 356 | +    print(f"Commit Activity Calendar for '{author}'") | 
|  | 357 | + | 
|  | 358 | +    # Get commit dates | 
|  | 359 | +    output = run_git_command(cmd) | 
|  | 360 | +    if not output: | 
|  | 361 | +        print("No commits found.") | 
|  | 362 | +        return | 
|  | 363 | + | 
|  | 364 | +    print("\n      Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec") | 
|  | 365 | + | 
|  | 366 | +    count = defaultdict(lambda: defaultdict(int)) | 
|  | 367 | +    for line in output.strip().split("\n"): | 
|  | 368 | +        try: | 
|  | 369 | +            date_str = line.strip().split(" ")[0] | 
|  | 370 | +            date_obj = datetime.strptime(date_str, "%Y-%m-%d") | 
|  | 371 | +            weekday = date_obj.isoweekday()  # 1=Mon, ..., 7=Sun | 
|  | 372 | +            month = date_obj.month | 
|  | 373 | +            count[weekday][month] += 1 | 
|  | 374 | +        except ValueError: | 
|  | 375 | +            continue | 
|  | 376 | + | 
|  | 377 | +    # Print the calendar | 
|  | 378 | +    weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] | 
|  | 379 | +    for d in range(1, 8): | 
|  | 380 | +        row = f"{weekdays[d-1]:<5} " | 
|  | 381 | +        for m in range(1, 13): | 
|  | 382 | +            c = count[d][m] | 
|  | 383 | +            if c == 0: | 
|  | 384 | +                out = "..." | 
|  | 385 | +            elif c <= 9: | 
|  | 386 | +                out = "░░░" | 
|  | 387 | +            elif c <= 19: | 
|  | 388 | +                out = "▒▒▒" | 
|  | 389 | +            else: | 
|  | 390 | +                out = "▓▓▓" | 
|  | 391 | +            row += out + (" " if m < 12 else "") | 
|  | 392 | +        print(row) | 
|  | 393 | + | 
|  | 394 | +    print("\nLegend: ... = 0   ░░░ = 1–9   ▒▒▒ = 10–19   ▓▓▓ = 20+ commits") | 
|  | 395 | + | 
|  | 396 | + | 
| 308 | 397 | def my_daily_status(config: Dict[str, Union[str, int]]) -> None: | 
| 309 | 398 |     """ | 
| 310 | 399 |     Displays the user's commits from the last day. | 
|  | 
0 commit comments