| 23 | |
| 24 | |
| 25 | def parse_pr_body( |
| 26 | pr_id: str, body: str, type_tag: str = "TYPE:", description_tag: str = "DESC:" |
| 27 | ) -> Mapping[str, Sequence[str]]: |
| 28 | headers = [] |
| 29 | descriptions = [] |
| 30 | for line in body.strip().split("\n"): |
| 31 | line = line.strip() |
| 32 | if line.startswith(type_tag): |
| 33 | change_type = line[len(type_tag) :].strip() |
| 34 | try: |
| 35 | headers.append(type_mapping[change_type]) |
| 36 | except KeyError: |
| 37 | logging.warning(f"Unknown history type: '{change_type}' for PR #{pr_id}") |
| 38 | headers.append(type_mapping["UNKNOWN"]) |
| 39 | |
| 40 | elif line.startswith(description_tag): |
| 41 | descriptions.append(line[len(description_tag) :].strip()) |
| 42 | |
| 43 | if len(headers) != len(descriptions): |
| 44 | raise ValueError(f"Mismatched number of history types and descriptions for PR #{pr_id}") |
| 45 | |
| 46 | get_header, get_description = itemgetter(0), itemgetter(1) |
| 47 | header_descriptions = sorted(zip(headers, descriptions), key=get_header) |
| 48 | return { |
| 49 | header: list(map(get_description, group)) |
| 50 | for header, group in it.groupby(header_descriptions, key=get_header) |
| 51 | } |
| 52 | |
| 53 | |
| 54 | def main(): |