1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#!/usr/bin/env python3
import re
import sys
import click
import pyperclip
from colorama import Fore, init
# Initialize colorama for color support in terminal
init(autoreset=True)
# Regular expression pattern to match the required lines
PATTERN = re.compile(r"^\*\s*(.*?)\s+by\s+@[\w-]+\s+in\s+https://github\.com/[\w-]+/[\w-]+/pull/(\d+)")
def read_changes_file(filename):
try:
with open(filename) as f:
return f.readlines()
except FileNotFoundError:
print(f"Error: {filename} file not found.")
sys.exit(1)
def read_from_clipboard():
text = pyperclip.paste()
return text.splitlines()
def process_line(line):
line = line.strip()
# Skip lines containing '[pre-commit.ci]'
if "[pre-commit.ci]" in line:
return None
# Skip lines starting with '## What's Changed'
if line.startswith("## What's Changed"):
return None
# Stop processing if '## New Contributors' is encountered
if line.startswith("## New Contributors"):
return "STOP_PROCESSING"
# Skip lines that don't start with '* '
if not line.startswith("* "):
return None
match = PATTERN.match(line)
if match:
description, pr_number = match.groups()
return f"- {description} (#{pr_number})"
return None
@click.command()
@click.option(
"--source",
"-s",
type=click.Path(exists=True),
help="Source file to read from. If not provided, reads from clipboard.",
)
@click.option(
"--dest",
"-d",
type=click.File("w"),
default="-",
help="Destination file to write to. Defaults to standard output.",
)
@click.option(
"--clipboard",
"-c",
is_flag=True,
help="Read input from clipboard explicitly.",
)
def main(source, dest, clipboard):
# Determine the source of input
if clipboard or (not source and not sys.stdin.isatty()):
# Read from clipboard
lines = read_from_clipboard()
elif source:
# Read from specified file
lines = read_changes_file(source)
else:
# Default: read from clipboard
lines = read_from_clipboard()
output_lines = []
for line in lines:
output_line = process_line(line)
if output_line == "STOP_PROCESSING":
break
if output_line:
output_lines.append(output_line)
output_text = "\n".join(output_lines)
# Prepare the header
version = "x.y.z"
underline = "=" * len(version)
header = f"""
.. _version-{version}:
{version}
{underline}
:release-date: <YYYY-MM-DD>
:release-by: <FULL NAME>
What's Changed
~~~~~~~~~~~~~~
"""
# Combine header and output
final_output = header + output_text
# Write output to destination
if dest.name == "<stdout>":
print(Fore.GREEN + "Copy the following text to Changelog.rst:")
print(Fore.YELLOW + header)
print(Fore.CYAN + output_text)
else:
dest.write(final_output + "\n")
dest.close()
if __name__ == "__main__":
main()
|