11#!/bin/env python3
22# /// script
3- # requires-python = ">=3.11 "
3+ # requires-python = ">=3.13 "
44# dependencies = [
55# "gitpython>=3.1.46,<3.2.0",
66# "packaging>=25.0,<25.1",
77# ]
88# ///
99
1010import itertools
11- import os
1211import re
12+ import typing as t
13+ from pathlib import Path
1314
1415import tomllib
1516from git import GitCommandError , Repo
17+ from packaging .version import Version
1618from packaging .version import parse as parse_version
1719
1820# Read Towncrier settings
19- with open ("pyproject.toml" , "rb" ) as fp :
21+ with Path ("pyproject.toml" ). open ( "rb" ) as fp :
2022 tc_settings = tomllib .load (fp )["tool" ]["towncrier" ]
2123
2224CHANGELOG_FILE = tc_settings .get ("filename" , "NEWS.rst" )
5153)
5254
5355
54- def get_changelog (repo , branch ) :
56+ def get_changelog (repo : Repo , branch : str ) -> str :
5557 branch_tc_settings = tomllib .loads (repo .git .show (f"{ branch } :pyproject.toml" ))["tool" ][
5658 "towncrier"
5759 ]
5860 branch_changelog_file = branch_tc_settings .get ("filename" , "NEWS.rst" )
5961 return repo .git .show (f"{ branch } :{ branch_changelog_file } " ) + "\n "
6062
6163
62- def _tokenize_changes (splits ) :
64+ def _tokenize_changes (splits : list [ str ]) -> t . Iterator [ list [ Version | str ]] :
6365 assert len (splits ) % 3 == 0
6466 for i in range (len (splits ) // 3 ):
6567 title = splits [3 * i ]
6668 version = parse_version (splits [3 * i + 1 ])
6769 yield [version , title + splits [3 * i + 2 ]]
6870
6971
70- def split_changelog (changelog ) :
72+ def split_changelog (changelog : str ) -> tuple [ str , list [ list [ Version | str ]]] :
7173 preamble , rest = changelog .split (START_STRING , maxsplit = 1 )
7274 split_rest = re .split (TITLE_REGEX , rest )
7375 return preamble + START_STRING + split_rest [0 ], list (_tokenize_changes (split_rest [1 :]))
7476
7577
76- def main ():
77- repo = Repo (os . getcwd ())
78+ def main () -> None :
79+ repo = Repo (Path . cwd ())
7880 remote = repo .remotes [0 ]
7981 branches = [ref for ref in remote .refs if re .match (r"^([0-9]+)\.([0-9]+)$" , ref .remote_head )]
8082 branches .sort (key = lambda ref : parse_version (ref .remote_head ), reverse = True )
8183 branches = [ref .name for ref in branches ]
8284
83- with open (CHANGELOG_FILE , "r" ) as f :
84- main_changelog = f .read ()
85+ main_changelog = Path (CHANGELOG_FILE ).read_text ()
8586 preamble , main_changes = split_changelog (main_changelog )
8687 old_length = len (main_changes )
8788
@@ -92,7 +93,7 @@ def main():
9293 except GitCommandError :
9394 print ("No changelog found on this branch." )
9495 continue
95- dummy , changes = split_changelog (changelog )
96+ _dummy , changes = split_changelog (changelog )
9697 new_changes = sorted (main_changes + changes , key = lambda x : x [0 ], reverse = True )
9798 # Now remove duplicates (retain the first one)
9899 main_changes = [new_changes [0 ]]
@@ -103,10 +104,9 @@ def main():
103104 new_length = len (main_changes )
104105 if old_length < new_length :
105106 print (f"{ new_length - old_length } new versions have been added." )
106- with open (CHANGELOG_FILE , "w" ) as fp :
107+ with Path (CHANGELOG_FILE ). open ( "w" ) as fp :
107108 fp .write (preamble )
108- for change in main_changes :
109- fp .write (change [1 ])
109+ fp .writelines (change [1 ] for change in main_changes )
110110
111111 repo .git .commit ("-m" , "Update Changelog" , CHANGELOG_FILE )
112112
0 commit comments