From 0bddc7b9bd21f85b21c5461b3aab6e5087afeda2 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 12 Jan 2023 17:03:08 -0500 Subject: [PATCH 1/4] Clean up GitHub statistics script This clears up the flake8 exception, and corrects the title and trailing whitespace that I always need to clean up when committing the file. --- .flake8 | 1 - tools/github_stats.py | 241 ++++++++++++++++++++++++------------------ 2 files changed, 137 insertions(+), 105 deletions(-) diff --git a/.flake8 b/.flake8 index 490ea57d9891..1041b27b8be2 100644 --- a/.flake8 +++ b/.flake8 @@ -36,7 +36,6 @@ exclude = doc/tutorials # External files. tools/gh_api.py - tools/github_stats.py .tox .eggs diff --git a/tools/github_stats.py b/tools/github_stats.py index f6e190324194..b5263eebad7a 100755 --- a/tools/github_stats.py +++ b/tools/github_stats.py @@ -1,13 +1,13 @@ #!/usr/bin/env python """Simple tools to query github.com and gather stats about issues. -To generate a report for IPython 2.0, run: +To generate a report for Matplotlib 3.0.0, run: - python github_stats.py --milestone 2.0 --since-tag rel-1.0.0 + python github_stats.py --milestone 3.0.0 --since-tag v2.0.0 """ -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Imports -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- import sys @@ -19,33 +19,72 @@ get_paged_request, make_auth_header, get_pull_request, is_pull_request, get_milestone_id, get_issues_list, get_authors, ) -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Globals -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- ISO8601 = "%Y-%m-%dT%H:%M:%SZ" PER_PAGE = 100 -#----------------------------------------------------------------------------- +REPORT_TEMPLATE = """\ +.. _github-stats: + +{title} +{title_underline} + +GitHub statistics for {since_day} (tag: {tag}) - {today} + +These lists are automatically generated, and may be incomplete or contain duplicates. + +We closed {n_issues} issues and merged {n_pulls} pull requests. +{milestone} +The following {nauthors} authors contributed {ncommits} commits. + +{unique_authors} +{links} + +Previous GitHub statistics +-------------------------- + +.. toctree:: + :maxdepth: 1 + :glob: + :reversed: + + prev_whats_new/github_stats_*""" +MILESTONE_TEMPLATE = ( + 'The full list can be seen `on GitHub ' + '`__\n') +LINKS_TEMPLATE = """ +GitHub issues and pull requests: + +Pull Requests ({n_pulls}): + +{pull_request_report} + +Issues ({n_issues}): + +{issue_report} +""" + +# ----------------------------------------------------------------------------- # Functions -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + def round_hour(dt): - return dt.replace(minute=0,second=0,microsecond=0) + return dt.replace(minute=0, second=0, microsecond=0) + def _parse_datetime(s): """Parse dates in the format returned by the GitHub API.""" - if s: - return datetime.strptime(s, ISO8601) - else: - return datetime.fromtimestamp(0) + return datetime.strptime(s, ISO8601) if s else datetime.fromtimestamp(0) + def issues2dict(issues): """Convert a list of issues to a dict, keyed by issue number.""" - idict = {} - for i in issues: - idict[i['number']] = i - return idict + return {i['number']: i for i in issues} + def split_pulls(all_issues, project="matplotlib/matplotlib"): """Split a list of closed issues into non-PR Issues and Pull Requests.""" @@ -60,9 +99,12 @@ def split_pulls(all_issues, project="matplotlib/matplotlib"): return issues, pulls -def issues_closed_since(period=timedelta(days=365), project="matplotlib/matplotlib", pulls=False): - """Get all issues closed since a particular point in time. period - can either be a datetime object, or a timedelta object. In the +def issues_closed_since(period=timedelta(days=365), + project='matplotlib/matplotlib', pulls=False): + """ + Get all issues closed since a particular point in time. + + *period* can either be a datetime object, or a timedelta object. In the latter case, it is used as a time before the present. """ @@ -72,60 +114,73 @@ def issues_closed_since(period=timedelta(days=365), project="matplotlib/matplotl since = round_hour(datetime.utcnow() - period) else: since = period - url = "https://api.github.com/repos/%s/%s?state=closed&sort=updated&since=%s&per_page=%i" % (project, which, since.strftime(ISO8601), PER_PAGE) + url = ( + f'https://api.github.com/repos/{project}/{which}' + f'?state=closed' + f'&sort=updated' + f'&since={since.strftime(ISO8601)}' + f'&per_page={PER_PAGE}') allclosed = get_paged_request(url, headers=make_auth_header()) - filtered = [ i for i in allclosed if _parse_datetime(i['closed_at']) > since ] + filtered = (i for i in allclosed + if _parse_datetime(i['closed_at']) > since) if pulls: - filtered = [ i for i in filtered if _parse_datetime(i['merged_at']) > since ] + filtered = (i for i in filtered + if _parse_datetime(i['merged_at']) > since) # filter out PRs not against main (backports) - filtered = [ i for i in filtered if i['base']['ref'] == 'main' ] + filtered = (i for i in filtered if i['base']['ref'] == 'main') else: - filtered = [ i for i in filtered if not is_pull_request(i) ] + filtered = (i for i in filtered if not is_pull_request(i)) - return filtered + return list(filtered) def sorted_by_field(issues, field='closed_at', reverse=False): """Return a list of issues sorted by closing date date.""" - return sorted(issues, key = lambda i:i[field], reverse=reverse) + return sorted(issues, key=lambda i: i[field], reverse=reverse) def report(issues, show_urls=False): """Summary report about a list of issues, printing number and title.""" + lines = [] if show_urls: for i in issues: role = 'ghpull' if 'merged_at' in i else 'ghissue' - print('* :%s:`%d`: %s' % (role, i['number'], - i['title'].replace('`', '``'))) + number = i['number'] + title = i['title'].replace('`', '``').strip() + lines.append(f'* :{role}:`{number}`: {title}') else: for i in issues: - print('* %d: %s' % (i['number'], i['title'].replace('`', '``'))) + number = i['number'] + title = i['title'].replace('`', '``').strip() + lines.append('* {number}: {title}') + return '\n'.join(lines) -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Main script -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- if __name__ == "__main__": # Whether to add reST urls for all issues in printout. show_urls = True parser = ArgumentParser() - parser.add_argument('--since-tag', type=str, - help="The git tag to use for the starting point (typically the last major release)." - ) - parser.add_argument('--milestone', type=str, - help="The GitHub milestone to use for filtering issues [optional]." - ) - parser.add_argument('--days', type=int, - help="The number of days of data to summarize (use this or --since-tag)." - ) - parser.add_argument('--project', type=str, default="matplotlib/matplotlib", - help="The project to summarize." - ) - parser.add_argument('--links', action='store_true', default=False, - help="Include links to all closed Issues and PRs in the output." - ) + parser.add_argument( + '--since-tag', type=str, + help='The git tag to use for the starting point ' + '(typically the last major release).') + parser.add_argument( + '--milestone', type=str, + help='The GitHub milestone to use for filtering issues [optional].') + parser.add_argument( + '--days', type=int, + help='The number of days of data to summarize (use this or --since-tag).') + parser.add_argument( + '--project', type=str, default='matplotlib/matplotlib', + help='The project to summarize.') + parser.add_argument( + '--links', action='store_true', default=False, + help='Include links to all closed Issues and PRs in the output.') opts = parser.parse_args() tag = opts.since_tag @@ -135,9 +190,10 @@ def report(issues, show_urls=False): since = datetime.utcnow() - timedelta(days=opts.days) else: if not tag: - tag = check_output(['git', 'describe', '--abbrev=0']).strip().decode('utf8') + tag = check_output(['git', 'describe', '--abbrev=0'], + encoding='utf8').strip() cmd = ['git', 'log', '-1', '--format=%ai', tag] - tagday, tz = check_output(cmd).strip().decode('utf8').rsplit(' ', 1) + tagday, tz = check_output(cmd, encoding='utf8').strip().rsplit(' ', 1) since = datetime.strptime(tagday, "%Y-%m-%d %H:%M:%S") h = int(tz[1:3]) m = int(tz[3:]) @@ -152,21 +208,19 @@ def report(issues, show_urls=False): milestone = opts.milestone project = opts.project - print("fetching GitHub stats since %s (tag: %s, milestone: %s)" % (since, tag, milestone), file=sys.stderr) + print(f'fetching GitHub stats since {since} (tag: {tag}, milestone: {milestone})', + file=sys.stderr) if milestone: milestone_id = get_milestone_id(project=project, milestone=milestone, - auth=True) - issues_and_pulls = get_issues_list(project=project, - milestone=milestone_id, - state='closed', - auth=True, - ) + auth=True) + issues_and_pulls = get_issues_list(project=project, milestone=milestone_id, + state='closed', auth=True) issues, pulls = split_pulls(issues_and_pulls, project=project) else: issues = issues_closed_since(since, project=project, pulls=False) pulls = issues_closed_since(since, project=project, pulls=True) - # For regular reports, it's nice to show them in reverse chronological order + # For regular reports, it's nice to show them in reverse chronological order. issues = sorted_by_field(issues, reverse=True) pulls = sorted_by_field(pulls, reverse=True) @@ -175,71 +229,50 @@ def report(issues, show_urls=False): since_day = since.strftime("%Y/%m/%d") today = datetime.today() - # Print summary report we can directly include into release notes. - print('.. _github-stats:') - print() - title = 'GitHub statistics ' + today.strftime('(%b %d, %Y)') - print(title) - print('=' * len(title)) - - print() - print("GitHub statistics for %s (tag: %s) - %s" % (since_day, tag, today.strftime("%Y/%m/%d"), )) - print() - print("These lists are automatically generated, and may be incomplete or contain duplicates.") - print() + title = (f'GitHub statistics for {milestone.lstrip("v")} ' + f'{today.strftime("(%b %d, %Y)")}') ncommits = 0 all_authors = [] if tag: # print git info, in addition to GitHub info: - since_tag = tag+'..' + since_tag = f'{tag}..' cmd = ['git', 'log', '--oneline', since_tag] ncommits += len(check_output(cmd).splitlines()) - author_cmd = ['git', 'log', '--use-mailmap', "--format=* %aN", since_tag] - all_authors.extend(check_output(author_cmd).decode('utf-8', 'replace').splitlines()) + author_cmd = ['git', 'log', '--use-mailmap', '--format=* %aN', since_tag] + all_authors.extend( + check_output(author_cmd, encoding='utf-8', errors='replace').splitlines()) pr_authors = [] for pr in pulls: pr_authors.extend(get_authors(pr)) ncommits = len(pr_authors) + ncommits - len(pulls) author_cmd = ['git', 'check-mailmap'] + pr_authors - with_email = check_output(author_cmd).decode('utf-8', 'replace').splitlines() + with_email = check_output(author_cmd, + encoding='utf-8', errors='replace').splitlines() all_authors.extend(['* ' + a.split(' <')[0] for a in with_email]) unique_authors = sorted(set(all_authors), key=lambda s: s.lower()) - print("We closed %d issues and merged %d pull requests." % (n_issues, n_pulls)) if milestone: - print("The full list can be seen `on GitHub `__" - % (project, milestone_id) - ) - - print() - print("The following %i authors contributed %i commits." % (len(unique_authors), ncommits)) - print() - print('\n'.join(unique_authors)) + milestone_str = MILESTONE_TEMPLATE.format(project=project, + milestone_id=milestone_id) + else: + milestone_str = '' if opts.links: - print() - print("GitHub issues and pull requests:") - print() - print('Pull Requests (%d):\n' % n_pulls) - report(pulls, show_urls) - print() - print('Issues (%d):\n' % n_issues) - report(issues, show_urls) - print() - print() - print("""\ -Previous GitHub statistics --------------------------- - - -.. toctree:: - :maxdepth: 1 - :glob: - :reversed: - - prev_whats_new/github_stats_* + links = LINKS_TEMPLATE.format(n_pulls=n_pulls, + pull_request_report=report(pulls, show_urls), + n_issues=n_issues, + issue_report=report(issues, show_urls)) + else: + links = '' -""") + # Print summary report we can directly include into release notes. + print(REPORT_TEMPLATE.format(title=title, title_underline='=' * len(title), + since_day=since_day, tag=tag, + today=today.strftime('%Y/%m/%d'), + n_issues=n_issues, n_pulls=n_pulls, + milestone=milestone_str, + nauthors=len(unique_authors), ncommits=ncommits, + unique_authors='\n'.join(unique_authors), links=links)) From cf6f76d1e70611e322722f10e1a0ad35cffeaac1 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 17 Jan 2023 20:05:33 -0500 Subject: [PATCH 2/4] Fix extra line in Zenodo cache script Every run of the script adds an extra newline at the end. --- tools/cache_zenodo_svg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py index 4f441d960197..f5bd4a7ecf1a 100644 --- a/tools/cache_zenodo_svg.py +++ b/tools/cache_zenodo_svg.py @@ -125,7 +125,7 @@ def _get_xdg_cache_dir(): target = None if ln.strip() == ".. END OF AUTOGENERATED": target = footer - target.append(ln) + target.append(ln.rstrip()) with open(citing, "w") as fout: fout.write("\n".join(header)) From 9d5837faf1e889adf41078d79d9227bda78af9b0 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 18 Jan 2023 05:10:24 -0500 Subject: [PATCH 3/4] Update release guide for current practices --- doc/devel/release_guide.rst | 240 +++++++++++++++--------------------- 1 file changed, 98 insertions(+), 142 deletions(-) diff --git a/doc/devel/release_guide.rst b/doc/devel/release_guide.rst index 3f49631d00d8..3f4b17d15231 100644 --- a/doc/devel/release_guide.rst +++ b/doc/devel/release_guide.rst @@ -35,45 +35,41 @@ In addition the following test should be run and manually inspected:: python tools/memleak.py agg 1000 agg.pdf -In addition the following should be run and manually inspected, but -is currently broken:: - - pushd examples/tests/ - python backend_driver_sgskip.py - popd - - .. _release_ghstats: GitHub statistics ================= +We automatically extract GitHub issue, PRs, and authors from GitHub via the API. To +prepare this list: -We automatically extract GitHub issue, PRs, and authors from GitHub via the -API. Copy the current :file:`doc/users/github_stats.rst` to -:file:`doc/users/prev_whats_new/github_stats_X.Y.Z.rst`, changing the link -target at the top of the file, and removing the "Previous GitHub Stats" section -at the end. +1. Archive the existing GitHub statistics page. -For example, when updating from v3.2.0 to v3.2.1:: + a. Copy the current :file:`doc/users/github_stats.rst` to + :file:`doc/users/prev_whats_new/github_stats_{X}.{Y}.{Z}.rst`. + b. Change the link target at the top of the file. + c. Remove the "Previous GitHub Stats" section at the end. - cp doc/users/github_stats.rst doc/users/prev_whats_new/github_stats_3.2.0.rst - $EDITOR doc/users/prev_whats_new/github_stats_3.2.0.rst - # Change contents as noted above. - git add doc/users/prev_whats_new/github_stats_3.2.0.rst + For example, when updating from v3.2.0 to v3.2.1:: -Then re-generate the updated stats:: + cp doc/users/github_stats.rst doc/users/prev_whats_new/github_stats_3.2.0.rst + $EDITOR doc/users/prev_whats_new/github_stats_3.2.0.rst + # Change contents as noted above. + git add doc/users/prev_whats_new/github_stats_3.2.0.rst - python tools/github_stats.py --since-tag v3.2.0 --milestone=v3.2.1 --project 'matplotlib/matplotlib' --links > doc/users/github_stats.rst +2. Re-generate the updated stats:: -Review and commit changes. Some issue/PR titles may not be valid reST (the -most common issue is ``*`` which is interpreted as unclosed markup). + python tools/github_stats.py --since-tag v3.2.0 --milestone=v3.2.1 \ + --project 'matplotlib/matplotlib' --links > doc/users/github_stats.rst + +3. Review and commit changes. Some issue/PR titles may not be valid reST (the most + common issue is ``*`` which is interpreted as unclosed markup). .. note:: - Make sure you authenticate against the GitHub API. If you - do not you will get blocked by GitHub for going over the API rate - limits. You can authenticate in one of two ways: + Make sure you authenticate against the GitHub API. If you do not, you will get + blocked by GitHub for going over the API rate limits. You can authenticate in one of + two ways: * using the ``keyring`` package; ``pip install keyring`` and then when running the stats script, you will be prompted for user name and password, @@ -97,9 +93,16 @@ are going to tag on and delete the doc branch on GitHub. Update supported versions in Security Policy -------------------------------------------- -When making major or minor releases, update the supported versions in the -Security Policy in :file:`SECURITY.md`. Commonly, this may be one or two -previous minor releases, but is dependent on release managers. +When making major or minor releases, update the supported versions in the Security +Policy in :file:`SECURITY.md`. + +For minor version release update the table in :file:`SECURITY.md` to specify that the +two most recent minor releases in the current major version series are supported. + +For a major version release update the table in :file:`SECURITY.md` to specify that the +last minor version in the previous major version series is still supported. Dropping +support for the last version of a major version series will be handled on an ad-hoc +basis. Update release notes -------------------- @@ -110,9 +113,9 @@ What's new *Only needed for major and minor releases. Bugfix releases should not have new features.* -Merge the contents of all the files in :file:`doc/users/next_whats_new/` -into a single file :file:`doc/users/prev_whats_new/whats_new_X.Y.0.rst` -and delete the individual files. +Merge the contents of all the files in :file:`doc/users/next_whats_new/` into a single +file :file:`doc/users/prev_whats_new/whats_new_{X}.{Y}.0.rst` and delete the individual +files. API changes ~~~~~~~~~~~ @@ -120,9 +123,9 @@ API changes *Primarily needed for major and minor releases. We may sometimes have API changes in bugfix releases.* -Merge the contents of all the files in :file:`doc/api/next_api_changes/` -into a single file :file:`doc/api/prev_api_changes/api_changes_X.Y.Z.rst` -and delete the individual files. +Merge the contents of all the files in :file:`doc/api/next_api_changes/` into a single +file :file:`doc/api/prev_api_changes/api_changes_{X}.{Y}.{Z}.rst` and delete the +individual files. Release notes TOC ~~~~~~~~~~~~~~~~~ @@ -152,69 +155,52 @@ Update :file:`doc/users/release_notes.rst`: Update version switcher ~~~~~~~~~~~~~~~~~~~~~~~ -Update ``doc/_static/switcher.json``. If a minor release, ``X.Y.Z``, create -a new entry ``version: X.Y.(Z-1)``, and change the name of stable -``name: stable/X.Y.Z``. If a major release, ``X.Y.0``, change the name -of ``name: devel/X.(Y+1)`` and ``name: stable/X.Y.0`` as well as adding -a new version for the previous stable. +Update ``doc/_static/switcher.json``: + +- If a bugfix release, :samp:`{X}.{Y}.{Z}`, no changes are needed. +- If a major release, :samp:`{X}.{Y}.0`, change the name of :samp:`name: {X}.{Y+1} + (dev)` and :samp:`name: {X}.{Y} (stable)` as well as adding a new version for the + previous stable (:samp:`name: {X}.{Y-1}`). Verify that docs build ---------------------- -Finally, make sure that the docs build cleanly :: +Finally, make sure that the docs build cleanly:: make -Cdoc O=-j$(nproc) html latexpdf -After the docs are built, check that all of the links, internal and external, -are still valid. We use ``linkchecker`` for this, which has not been ported to -Python3 yet. You will need to create a Python2 environment with -``requests==2.9.0`` and linkchecker :: +After the docs are built, check that all of the links, internal and external, are still +valid. We use ``linkchecker`` for this:: - conda create -p /tmp/lnkchk python=2 requests==2.9.0 - source activate /tmp/lnkchk pip install linkchecker pushd doc/build/html linkchecker index.html --check-extern popd -Address any issues which may arise. The internal links are checked on Circle -CI, this should only flag failed external links. - - -Update supported versions in SECURITY.md ----------------------------------------- - -For minor version release update the table in :file:`SECURITY.md` to specify -that the 2 most recent minor releases in the current major version series are -supported. +Address any issues which may arise. The internal links are checked on Circle CI, so this +should only flag failed external links. -For a major version release update the table in :file:`SECURITY.md` to specify -that the last minor version in the previous major version series is still -supported. Dropping support for the last version of a major version series -will be handled on an ad-hoc basis. .. _release_tag: Create release commit and tag ============================= -To create the tag, first create an empty commit with a very terse set of the release notes -in the commit message :: +To create the tag, first create an empty commit with a very terse set of the release +notes in the commit message:: git commit --allow-empty -and then create a signed, annotated tag with the same text in the body -message :: +and then create a signed, annotated tag with the same text in the body message:: git tag -a -s v2.0.0 -which will prompt you for your GPG key password and an annotation. For pre -releases it is important to follow :pep:`440` so that the build artifacts will -sort correctly in PyPI. +which will prompt you for your GPG key password and an annotation. For pre-releases it +is important to follow :pep:`440` so that the build artifacts will sort correctly in +PyPI. -To prevent issues with any down-stream builders which download the -tarball from GitHub it is important to move all branches away from the commit -with the tag [#]_:: +To prevent issues with any down-stream builders which download the tarball from GitHub +it is important to move all branches away from the commit with the tag [#]_:: git commit --allow-empty @@ -233,11 +219,11 @@ Congratulations, the scariest part is done! based on the git tag, when users install from the tarball. However, if there is a branch pointed at the tagged commit, then the branch name will also be included in the tarball. - When the branch eventually moves, anyone how checked the hash + When the branch eventually moves, anyone who checked the hash of the tarball before the branch moved will have an incorrect hash. - To generate the file that GitHub does use :: + To generate the file that GitHub does use:: git archive v2.0.0 -o matplotlib-2.0.0.tar.gz --prefix=matplotlib-2.0.0/ @@ -260,28 +246,22 @@ On this branch un-comment the globs from :ref:`release_chkdocs`. And then :: git push DANGER v2.0.x - - .. _release_DOI: Release management / DOI ======================== -Via the `GitHub UI -`__, turn the newly -pushed tag into a release. If this is a pre-release remember to mark -it as such. - -For final releases, also get the DOI from `zenodo -`__ (which will automatically produce one once -the tag is pushed). Add the doi post-fix and version to the dictionary in -:file:`tools/cache_zenodo_svg.py` and run the script. +Via the `GitHub UI `__, turn the +newly pushed tag into a release. If this is a pre-release remember to mark it as such. +For final releases, also get the DOI from `Zenodo `__ (which will +automatically produce one once the tag is pushed). Add the DOI post-fix and version to +the dictionary in :file:`tools/cache_zenodo_svg.py` and run the script. -This will download the new svg to the :file:`_static` directory in the -docs and edit :file:`doc/citing.rst`. Commit the new svg, the change -to :file:`tools/cache_zenodo_svg.py`, and the changes to -:file:`doc/citing.rst` to the VER-doc branch and push to GitHub. :: +This will download the new SVG to :file:`doc/_static/zenodo_cache/{postfix}.svg` and +edit :file:`doc/citing.rst`. Commit the new SVG, the change to +:file:`tools/cache_zenodo_svg.py`, and the changes to :file:`doc/citing.rst` to the +VER-doc branch and push to GitHub. :: git checkout v2.0.0-doc $EDITOR tools/cache_zenodo_svg.py @@ -290,43 +270,26 @@ to :file:`tools/cache_zenodo_svg.py`, and the changes to git commit -a git push DANGER v2.0.0-doc:v2.0.0-doc + .. _release_bld_bin: Building binaries ================= -We distribute macOS, Windows, and many Linux wheels as well as a source tarball -via PyPI. Most builders should trigger automatically once the tag is pushed to -GitHub: - -* Windows, macOS and manylinux wheels are built on GitHub Actions. Builds are - triggered by the GitHub Action defined in - :file:`.github/workflows/cibuildwheel.yml`, and wheels will be available as - artifacts of the build. -* Alternative Windows wheels are built by Christoph Gohlke automatically and - will be `available at his site - `__ once built. +We distribute macOS, Windows, and many Linux wheels as well as a source tarball via +PyPI. Most builders should trigger automatically once the tag is pushed to GitHub: + +* Windows, macOS and manylinux wheels are built on GitHub Actions. Builds are triggered + by the GitHub Action defined in :file:`.github/workflows/cibuildwheel.yml`, and wheels + will be available as artifacts of the build. * The auto-tick bot should open a pull request into the `conda-forge feedstock - `__. Review and merge - (if you have the power to). + `__. Review and merge (if you + have the power to). .. warning:: - Because this is automated, it is extremely important to bump all branches - away from the tag as discussed in :ref:`release_tag`. - -If this is a final release the following downstream packagers should be contacted: - -- Debian -- Fedora -- Arch -- Gentoo -- Macports -- Homebrew -- Continuum -- Enthought - -This can be done ahead of collecting all of the binaries and uploading to pypi. + Because this is automated, it is extremely important to bump all branches away from + the tag as discussed in :ref:`release_tag`. .. _release_upload_bin: @@ -334,19 +297,19 @@ This can be done ahead of collecting all of the binaries and uploading to pypi. Make distribution and upload to PyPI ==================================== -Once you have collected all of the wheels (expect this to take about a -day), generate the tarball :: +Once you have collected all of the wheels (expect this to take a few hours), generate +the tarball:: git checkout v2.0.0 git clean -xfd - python setup.py sdist + python -m build --sdist -and copy all of the wheels into :file:`dist` directory. First, check -that the dist files are OK :: +and copy all of the wheels into :file:`dist` directory. First, check that the dist files +are OK:: twine check dist/* -and then use ``twine`` to upload all of the files to pypi :: +and then use ``twine`` to upload all of the files to PyPI :: twine upload -s dist/matplotlib*tar.gz twine upload dist/*whl @@ -368,34 +331,31 @@ build the docs from the ``ver-doc`` branch. An easy way to arrange this is:: git clean -xfd make -Cdoc O="-t release -j$(nproc)" html latexpdf LATEXMKOPTS="-silent -f" -which will build both the html and pdf version of the documentation. - +which will build both the HTML and PDF version of the documentation. The built documentation exists in the `matplotlib.github.com `__ repository. Pushing changes to main automatically updates the website. -The documentation is organized by version. At the root of the tree is always -the documentation for the latest stable release. Under that, there are -directories containing the documentation for older versions. The documentation -for current main is built on Circle CI and pushed to the `devdocs -`__ repository. These are available at +The documentation is organized in subdirectories by version. The latest stable release +is symlinked from the :file:`stable` directory. The documentation for current main is +built on Circle CI and pushed to the `devdocs +`__ repository. These are available at `matplotlib.org/devdocs `__. Assuming you have this repository checked out in the same directory as matplotlib :: cd ../matplotlib.github.com - mkdir 2.0.0 - rsync -a ../matplotlib/doc/build/html/* 2.0.0 + cp -a ../matplotlib/doc/build/html 2.0.0 + rm 2.0.0/.buildinfo cp ../matplotlib/doc/build/latex/Matplotlib.pdf 2.0.0 which will copy the built docs over. If this is a final release, link the ``stable`` subdirectory to the newest version:: - rsync -a 2.0.0/* ./ rm stable - ln -s 2.0.0/ stable + ln -s 2.0.0 stable You will need to manually edit :file:`versions.html` to show the last 3 tagged versions. You will also need to edit :file:`sitemap.xml` to include @@ -407,10 +367,10 @@ the newly released version. Now commit and push everything to GitHub :: Congratulations you have now done the third scariest part! -If you have access, clear the Cloudflare caches. +If you have access, clear the CloudFlare caches. -It typically takes about 5-10 minutes for GitHub to process the push -and update the live web page (remember to clear your browser cache). +It typically takes about 5-10 minutes for the website to process the push and update the +live web page (remember to clear your browser cache). Announcing @@ -423,13 +383,9 @@ version of the release notes along with acknowledgments should be sent to - matplotlib-devel@python.org - matplotlib-announce@python.org -For final releases announcements should also be sent to the -numpy/scipy/scikit-image mailing lists. - -In addition, announcements should be made on social networks (twitter -via the ``@matplotlib`` account, any other via personal accounts). -`NumFOCUS `__ should be contacted for -inclusion in their newsletter. +In addition, announcements should be made on social networks (e.g., Twitter via the +``@matplotlib`` account, any other via personal accounts). `NumFOCUS +`__ should be contacted for inclusion in their newsletter. Conda packages From 06cf2f3962d4a01246df35ade5472f8ba6a5413d Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 26 Jan 2023 17:50:42 -0600 Subject: [PATCH 4/4] STY: start docstring on second line --- tools/github_stats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/github_stats.py b/tools/github_stats.py index b5263eebad7a..bffa1c296954 100755 --- a/tools/github_stats.py +++ b/tools/github_stats.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -"""Simple tools to query github.com and gather stats about issues. +""" +Simple tools to query github.com and gather stats about issues. To generate a report for Matplotlib 3.0.0, run: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy