@@ -108,6 +108,42 @@ def verify_dist(args: argparse.Namespace) -> None:
108108 print (f" { name } " )
109109
110110
111+ def changelog_notes (args : argparse .Namespace ) -> None :
112+ changelog_path = pathlib .Path (args .changelog )
113+ lines = changelog_path .read_text (encoding = "utf-8" ).splitlines ()
114+ heading = re .compile (r"^## \[(?P<version>[^\]]+)\](?:\s+-\s+.*)?\s*$" )
115+
116+ start = None
117+ for index , line in enumerate (lines ):
118+ match = heading .match (line )
119+ if match and match .group ("version" ) == args .version :
120+ start = index + 1
121+ break
122+
123+ if start is None :
124+ raise RuntimeError (
125+ f"Could not find changelog section for version { args .version !r} "
126+ )
127+
128+ end = len (lines )
129+ for index in range (start , len (lines )):
130+ if lines [index ].startswith ("## " ):
131+ end = index
132+ break
133+
134+ section_lines = lines [start :end ]
135+ while section_lines and not section_lines [0 ].strip ():
136+ section_lines .pop (0 )
137+ while section_lines and not section_lines [- 1 ].strip ():
138+ section_lines .pop ()
139+
140+ if not section_lines :
141+ raise RuntimeError (f"Changelog section for { args .version !r} is empty" )
142+
143+ notes = "## Changelog\n \n " + "\n " .join (section_lines ) + "\n "
144+ pathlib .Path (args .output ).write_text (notes , encoding = "utf-8" )
145+
146+
111147def main (argv : Sequence [str ] | None = None ) -> None :
112148 parser = argparse .ArgumentParser ()
113149 subparsers = parser .add_subparsers (required = True )
@@ -122,6 +158,12 @@ def main(argv: Sequence[str] | None = None) -> None:
122158 verify_parser .add_argument ("--dist-dir" , default = "dist" )
123159 verify_parser .set_defaults (func = verify_dist )
124160
161+ changelog_parser = subparsers .add_parser ("changelog-notes" )
162+ changelog_parser .add_argument ("--version" , required = True )
163+ changelog_parser .add_argument ("--changelog" , default = "CHANGELOG.md" )
164+ changelog_parser .add_argument ("--output" , required = True )
165+ changelog_parser .set_defaults (func = changelog_notes )
166+
125167 args = parser .parse_args (argv )
126168 args .func (args )
127169
0 commit comments