Tools: Add script to report (high) priority issues per module #120022

Merged
Thomas Dinges merged 3 commits from ThomasDinges/blender:reports_script into main 2024-04-02 15:54:23 +02:00
1 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,126 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2024 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
"""
# This script prints the numbers of open issues per module.
Example usage:
python ./issues_module_listing.py --severity High
"""
import argparse
import dataclasses
from datetime import date
from gitea_utils import gitea_json_issues_search
@dataclasses.dataclass
class ModuleInfo:
name: str
labelid: str
buglist: list[str] = dataclasses.field(default_factory=list)
# Label names and IDs are taken from https://projects.blender.org/blender/blender/labels.
ThomasDinges marked this conversation as resolved Outdated

Worth adding a note about where these values are from - if we need to update the list.

Worth adding a note about where these values are from - if we need to update the list.
modules = {
"Module/Animation & Rigging" : ModuleInfo(name="Animation & Rigging", labelid="268"),
"Module/Core" : ModuleInfo(name="Core", labelid="269"),
"Module/EEVEE & Viewport" : ModuleInfo(name="EEVEE & Viewport", labelid="272"),
"Module/Grease Pencil" : ModuleInfo(name="Grease Pencil", labelid="273"),
"Module/Modeling" : ModuleInfo(name="Modeling", labelid="274"),
"Module/Nodes & Physics" : ModuleInfo(name="Nodes & Physics", labelid="275"),
"Module/Pipeline, Assets & IO" : ModuleInfo(name="Pipeline, Assets & I/O", labelid="276"),
"Module/Platforms, Builds, Test & Devices" : ModuleInfo(name="Platforms, Builds, Test & Devices", labelid="278"),
"Module/Python API" : ModuleInfo(name="Python API", labelid="279"),
"Module/Render & Cycles" : ModuleInfo(name="Render & Cycles", labelid="280"),
"Module/Sculpt, Paint & Texture" : ModuleInfo(name="Sculpt, Paint & Texture", labelid="281"),
"Module/User Interface" : ModuleInfo(name="User Interface", labelid="283"),
"Module/VFX & Video" : ModuleInfo(name="VFX & Video", labelid="284"),
}
base_url = "https://projects.blender.org/blender/blender/issues?q=&type=all&sort=&state=open&labels="
total_url = "https://projects.blender.org/blender/blender/issues?q=&type=all&sort=&state=open&labels=285%2c-297%2c-298%2c-299%2c-301"
severity_labelid = {
"Low": "286",
"Normal": "287",
"High": "285",
"Unbreak Now!": "288"
}
ThomasDinges marked this conversation as resolved
Review

Calling list() is mainly used for converting to a list, for empty lists [] is typically written.

Calling `list()` is mainly used for converting to a list, for empty lists `[]` is typically written.
def compile_list(severity: str) -> None:
label = f"Priority/{severity}"
issues_json = gitea_json_issues_search(
type="issues",
state="open",
labels=label,
verbose=True,
)
uncategorized_reports = []
for issue in issues_json:
html_url = issue["html_url"]
ThomasDinges marked this conversation as resolved
Review

*typo* assignment, also end sentences with full-stops.

\*typo\* `assignment`, also end sentences with full-stops.
number = issue["number"]
# Check reports module assignment and fill in data.
for label_iter in issue["labels"]:
label = label_iter["name"]
if label not in modules:
continue
modules[label].buglist.append(f"[#{number}]({html_url})")
break
else:
uncategorized_reports.append(f"[#{number}]({html_url})")
ThomasDinges marked this conversation as resolved
Review

Having module used twice under different types causes mypy to report type errors (see mypy --strict tools/triage/issues_module_listing.py), renaming it to module_key, module_id or similar resolves.

Having module used twice under different types causes mypy to report type errors (see ` mypy --strict tools/triage/issues_module_listing.py`), renaming it to `module_key`, `module_id` or similar resolves.
uncategorized_reports = (', '.join(uncategorized_reports))
# Print statistics
print(f"Open {severity} Priority bugs as of {date.today()}:\n")
total = 0
for module in modules.values():
total += len(module.buglist)
str_list = (', '.join(module.buglist))
full_url = base_url + severity_labelid[severity] + "%2c" + module.labelid
ThomasDinges marked this conversation as resolved
Review

While personal preference I find the {str(len(module.bug_list))} a bit cryptic, the str() can be removed, assigning a variable buglist_len = len(module.buglist) means this can be written as {buglist_len} which reads better to me - but I'm not that fussed.

While personal preference I find the `{str(len(module.bug_list))}` a bit cryptic, the `str()` can be removed, assigning a variable `buglist_len = len(module.buglist)` means this can be written as `{buglist_len}` which reads better to me - but I'm not _that_ fussed.
buglist_len = len(module.buglist)
if not module.buglist or severity != 'High':
print(f"- [{module.name}]({full_url}): *{buglist_len}*")
else:
print(f"- [{module.name}]({full_url}): *{buglist_len}* _{str_list}_")
ThomasDinges marked this conversation as resolved
Review

can be f"Total: {total}" - since f-strings are used everywhere else here.

can be `f"Total: {total}"` - since f-strings are used everywhere else here.
print()
print(f"[Total]({total_url}): {total}")
print()
print(f"Uncategorized: {uncategorized_reports}")
def main() -> None:
parser = argparse.ArgumentParser(
description="Print statistics on open bug reports per module",
epilog="This script is used to help module teams",
ThomasDinges marked this conversation as resolved Outdated

Adding choices=severity_labelid.keys(), gives a nice error if an invalid choice is passed in. .e.g

issues_module_listing.py: error: argument --severity: invalid choice: 'Unbreak' (choose from 'Low', 'Normal', 'High', 'Unbreak Now!')

... shows up in --help too.

Adding `choices=severity_labelid.keys(),` gives a nice error if an invalid choice is passed in. .e.g ``` issues_module_listing.py: error: argument --severity: invalid choice: 'Unbreak' (choose from 'Low', 'Normal', 'High', 'Unbreak Now!') ``` ... shows up in `--help` too.
)
parser.add_argument(
"--severity",
dest="severity",
default="High",
ThomasDinges marked this conversation as resolved
Review

*picky* prefer trailing comma and newline, makes diffs less noisy when new args are added. Same for ArgumentParser.

\*picky\* prefer trailing comma and newline, makes diffs less noisy when new args are added. Same for `ArgumentParser`.
type=str,
required=False,
choices=severity_labelid.keys(),
help="Severity level of reports",
)
args = parser.parse_args()
compile_list(args.severity)
if __name__ == "__main__":
main()