diff --git a/skimage/metrics/_structural_similarity.py b/skimage/metrics/_structural_similarity.py index ae844d060b4..73848361481 100644 --- a/skimage/metrics/_structural_similarity.py +++ b/skimage/metrics/_structural_similarity.py @@ -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 diff --git a/tools/generate_release_notes.py b/tools/generate_release_notes.py index f42454860b8..4e1b02e3e90 100755 --- a/tools/generate_release_notes.py +++ b/tools/generate_release_notes.py @@ -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() @@ -74,19 +79,22 @@ 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() @@ -94,6 +102,7 @@ def tqdm(i, **kwargs): committers = set() users = dict() # keep track of known usernames + def find_author_info(commit): """Return committer and author of a commit. @@ -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 @@ -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) @@ -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 @@ -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 @@ -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} `_)." + ) -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()