Skip to content

Commit

Permalink
Add PR links to release notes generating script (#6917)
Browse files Browse the repository at this point in the history
* Add PR links to release notes generating script

* Use default dicts

* Autoformat w/ black
  • Loading branch information
jarrodmillman authored May 8, 2023
1 parent 6f59d7e commit 2f9b82c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 61 deletions.
2 changes: 1 addition & 1 deletion skimage/metrics/_structural_similarity.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def structural_similarity(im1, im2,
data_range = dmax - dmin
if np.issubdtype(im1.dtype, np.integer) and (im1.dtype != np.uint8):
warn("Setting data_range based on im1.dtype. " +
("data_range = %.0f. " % data_range) +
f"data_range = {data_range:.0f}. " +
"Please specify data_range explicitly to avoid mistakes.", stacklevel=2)

ndim = im1.ndim
Expand Down
136 changes: 76 additions & 60 deletions tools/generate_release_notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,45 @@
import os
import argparse
from datetime import datetime
from collections import OrderedDict
from warnings import warn

from github import Github

try:
from tqdm import tqdm
except ImportError:
warn('tqdm not installed. This script takes approximately 5 minutes '
'to run. To view live progressbars, please install tqdm. '
'Otherwise, be patient.')
warn(
"tqdm not installed. This script takes approximately 5 minutes "
"to run. To view live progressbars, please install tqdm. "
"Otherwise, be patient."
)

def tqdm(i, **kwargs):
return i


GH_USER = 'scikit-image'
GH_REPO = 'scikit-image'
GH_TOKEN = os.environ.get('GH_TOKEN')
GH_USER = "scikit-image"
GH_REPO = "scikit-image"
GH_TOKEN = os.environ.get("GH_TOKEN")
if GH_TOKEN is None:
raise RuntimeError(
"It is necessary that the environment variable `GH_TOKEN` "
"be set to avoid running into problems with rate limiting. "
"One can be acquired at https://github.com/settings/tokens.\n\n"
"You do not need to select any permission boxes while generating "
"the token.")
"the token."
)

g = Github(GH_TOKEN)
repository = g.get_repo(f'{GH_USER}/{GH_REPO}')
repository = g.get_repo(f"{GH_USER}/{GH_REPO}")


parser = argparse.ArgumentParser(usage=__doc__)
parser.add_argument('from_commit', help='The starting tag.')
parser.add_argument('to_commit', help='The head branch.')
parser.add_argument('--version', help="Version you're about to release.",
default='0.15.0')
parser.add_argument("from_commit", help="The starting tag.")
parser.add_argument("to_commit", help="The head branch.")
parser.add_argument(
"--version", help="Version you're about to release.", default="0.15.0"
)

args = parser.parse_args()

Expand All @@ -74,26 +79,30 @@ def tqdm(i, **kwargs):
previous_tag = tag
break
else:
raise RuntimeError(f'Desired tag ({args.from_commit}) not found')
raise RuntimeError(f"Desired tag ({args.from_commit}) not found")

# For some reason, go get the github commit from the commit to get
# the correct date
github_commit = previous_tag.commit.commit
previous_tag_date = datetime.strptime(github_commit.last_modified,
'%a, %d %b %Y %H:%M:%S %Z')
github_commit = previous_tag.commit.commit
previous_tag_date = datetime.strptime(
github_commit.last_modified, "%a, %d %b %Y %H:%M:%S %Z"
)


all_commits = list(tqdm(repository.get_commits(sha=args.to_commit,
since=previous_tag_date),
desc=f'Getting all commits between {args.from_commit} '
f'and {args.to_commit}'))
all_commits = list(
tqdm(
repository.get_commits(sha=args.to_commit, since=previous_tag_date),
desc=f"Getting all commits between {args.from_commit} " f"and {args.to_commit}",
)
)
all_hashes = {c.sha for c in all_commits}

authors = set()
reviewers = set()
committers = set()
users = dict() # keep track of known usernames


def find_author_info(commit):
"""Return committer and author of a commit.
Expand All @@ -112,9 +121,9 @@ def find_author_info(commit):
committer = None
if commit.committer is not None:
committer = commit.committer.name or commit.committer.login
git_author = commit.raw_data['commit']['author']['name']
git_author = commit.raw_data["commit"]["author"]["name"]
if commit.author is not None:
author = commit.author.name or commit.author.login + f' ({git_author})'
author = commit.author.name or commit.author.login + f" ({git_author})"
else:
# Users that deleted their accounts will appear as None
author = git_author
Expand All @@ -127,7 +136,8 @@ def add_to_users(users, new_user):
else:
users[new_user.login] = new_user.name

for commit in tqdm(all_commits, desc='Getting committers and authors'):

for commit in tqdm(all_commits, desc="Getting committers and authors"):
committer, author = find_author_info(commit)
if committer is not None:
committers.add(committer)
Expand All @@ -140,23 +150,27 @@ def add_to_users(users, new_user):
authors.add(author)

# this gets found as a committer
committers.discard('GitHub Web Flow')
authors.discard('Azure Pipelines Bot')
committers.discard("GitHub Web Flow")
authors.discard("Azure Pipelines Bot")

highlights = OrderedDict()
highlights = {}

highlights['New Feature'] = {}
highlights['Improvement'] = {}
highlights['Bugfix'] = {}
highlights['API Change'] = {}
highlights['Deprecations'] = {}
highlights['Build Tool'] = {}
highlights["New Feature"] = {}
highlights["Improvement"] = {}
highlights["Bugfix"] = {}
highlights["API Change"] = {}
highlights["Deprecations"] = {}
highlights["Build Tool"] = {}
other_pull_requests = {}

for pull in tqdm(g.search_issues(f'repo:{GH_USER}/{GH_REPO} '
f'merged:>{previous_tag_date.isoformat()} '
'sort:created-asc'),
desc='Pull Requests...'):
for pull in tqdm(
g.search_issues(
f"repo:{GH_USER}/{GH_REPO} "
f"merged:>{previous_tag_date.isoformat()} "
"sort:created-asc"
),
desc="Pull Requests...",
):
pr = repository.get_pull(pull.number)
if pr.merge_commit_sha in all_hashes:
summary = pull.title
Expand All @@ -165,36 +179,35 @@ def add_to_users(users, new_user):
users[review.user.login] = review.user.name
reviewers.add(users[review.user.login])
for key, key_dict in highlights.items():
pr_title_prefix = (key + ': ').lower()
pr_title_prefix = (key + ": ").lower()
if summary.lower().startswith(pr_title_prefix):
key_dict[pull.number] = {
'summary': summary[len(pr_title_prefix):]
}
key_dict[pull.number] = {"summary": summary[len(pr_title_prefix) :]}
break
else:
other_pull_requests[pull.number] = {
'summary': summary
}
other_pull_requests[pull.number] = {"summary": summary}


# add Other PRs to the ordered dict to make doc generation easier.
highlights['Other Pull Request'] = other_pull_requests
highlights["Other Pull Request"] = other_pull_requests


# Now generate the release notes
announcement_title = f'Announcement: scikit-image {args.version}'
announcement_title = f"Announcement: scikit-image {args.version}"
print(announcement_title)
print('=' * len(announcement_title))
print("=" * len(announcement_title))

print(f'''
print(
f"""
We're happy to announce the release of scikit-image v{args.version}!
scikit-image is an image processing toolbox for SciPy that includes algorithms
for segmentation, geometric transformations, color space manipulation,
analysis, filtering, morphology, feature detection, and more.
''')
"""
)

print("""
print(
"""
For more information, examples, and documentation, please visit our website:
https://scikit-image.org
Expand All @@ -206,27 +219,30 @@ def add_to_users(users, new_user):
if not pull_request_dicts:
continue
print(f'{section}s\n{"*" * (len(section)+1)}')
for number, pull_request_info in pull_request_dicts.items():
print(f'- {pull_request_info["summary"]} (#{number})')

for pr_num, pr_info in pull_request_dicts.items():
print(
f"- {pr_info['summary']}\n (`#{pr_num} <https://github.com/scikit-image/scikit-image/pull/{pr_num}>`_)."
)

contributors = OrderedDict()
contributors = {}

contributors['authors'] = authors
contributors["authors"] = authors
# contributors['committers'] = committers
contributors['reviewers'] = reviewers
contributors["reviewers"] = reviewers

for section_name, contributor_set in contributors.items():
print()
committer_str = (f'{len(contributor_set)} {section_name} added to this '
'release [alphabetical by first name or login]')
committer_str = (
f"{len(contributor_set)} {section_name} added to this "
"release [alphabetical by first name or login]"
)
print(committer_str)
print('-' * len(committer_str))
print("-" * len(committer_str))

# Remove None from contributor set if it's in there.
if None in contributor_set:
contributor_set.remove(None)

for c in sorted(contributor_set, key=str.lower):
print(f'- {c}')
print(f"- {c}")
print()

0 comments on commit 2f9b82c

Please sign in to comment.