summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--doc/conf.py12
-rw-r--r--howto.txt16
-rw-r--r--igor.py126
4 files changed, 100 insertions, 60 deletions
diff --git a/Makefile b/Makefile
index 7778a144..9184ab77 100644
--- a/Makefile
+++ b/Makefile
@@ -146,6 +146,9 @@ sample_html_beta: _sample_cog_html ## Generate sample HTML report for a beta rel
REPO_OWNER = nedbat/coveragepy
+edit_for_release: ## Edit sources to insert release facts.
+ python igor.py edit_for_release
+
kit: ## Make the source distribution.
python -m build
@@ -181,6 +184,9 @@ update_stable: ## Set the stable branch to the latest release.
git branch -f stable $$(python setup.py --version)
git push origin stable
+bump_version: ## Edit sources to bump the version after a release.
+ python igor.py bump_version
+
##@ Documentation
diff --git a/doc/conf.py b/doc/conf.py
index c9599e0e..38b8f0fe 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -57,18 +57,20 @@ master_doc = 'index'
# General information about the project.
project = 'Coverage.py'
-copyright = '2009\N{EN DASH}2022, Ned Batchelder' # CHANGEME # pylint: disable=redefined-builtin
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
-#
-# The short X.Y.Z version. # CHANGEME
+
+# @@@ editable
+copyright = "2009–2022, Ned Batchelder" # pylint: disable=redefined-builtin
+# The short X.Y.Z version.
version = "6.5.0"
-# The full version, including alpha/beta/rc tags. # CHANGEME
+# The full version, including alpha/beta/rc tags.
release = "6.5.0"
-# The date of release, in "monthname day, year" format. # CHANGEME
+# The date of release, in "monthname day, year" format.
release_date = "September 29, 2022"
+# @@@ end
rst_epilog = """
.. |release_date| replace:: {release_date}
diff --git a/howto.txt b/howto.txt
index ec0bd9e7..32707eee 100644
--- a/howto.txt
+++ b/howto.txt
@@ -7,10 +7,10 @@
version_info = (4, 0, 2, "candidate", 1)
version_info = (4, 0, 2, "final", 0)
- Supported Python version numbers. Search for "PYVERSIONS".
-- Copyright date in NOTICE.txt
+- Update source files with release facts:
+ $ make edit_for_release
- run `python igor.py cheats` to get useful snippets for next steps.
-- Update CHANGES.rst, including release date.
- - don't forget the jump target
+- Look over CHANGES.rst
- Update README.rst
- "New in x.y:"
- Python versions supported
@@ -18,8 +18,6 @@
- Python versions in doc/index.rst
- IF PRE-RELEASE:
- Version of latest stable release in doc/index.rst
- - Version, release, release_date and copyright date in doc/conf.py
- - Look for CHANGEME comments
- Make sure the docs are cogged:
$ make prebuild
- Don't forget the man page: doc/python-coverage.1.txt
@@ -61,14 +59,8 @@
$ make clean github_releases
- Visit the fixed issues on GitHub and mention the version it was fixed in.
$ make comment_on_fixes
- - "This is now released as part of [coverage 5.2](https://pypi.org/project/coverage/5.2)."
- Bump version:
- - coverage/version.py
- - increment version number
- - IF NOT PRE-RELEASE:
- - set to alpha-0 if just released.
- - CHANGES.rst
- - add an "Unreleased" section to the top.
+ $ make bump_version
$ git push
- Update readthedocs
- @ https://readthedocs.org/projects/coverage/versions/
diff --git a/igor.py b/igor.py
index 10c82cb4..6f1bd997 100644
--- a/igor.py
+++ b/igor.py
@@ -15,10 +15,12 @@ import glob
import inspect
import os
import platform
+import re
import subprocess
import sys
import sysconfig
import textwrap
+import types
import warnings
import zipfile
@@ -380,56 +382,94 @@ def do_quietly(command):
return proc.returncode
+def get_release_facts():
+ """Return an object with facts about the current release."""
+ import coverage
+ facts = types.SimpleNamespace()
+ facts.ver = coverage.__version__
+ facts.vi = coverage.version_info
+ facts.shortver = f"{facts.vi[0]}.{facts.vi[1]}.{facts.vi[2]}"
+ facts.anchor = facts.shortver.replace(".", "-")
+ if facts.vi[3] != "final":
+ facts.anchor += f"{facts.vi[3][0]}{facts.vi[4]}"
+ facts.next_vi = (facts.vi[0], facts.vi[1], facts.vi[2]+1, "alpha", 0)
+ facts.now = datetime.datetime.now()
+ facts.branch = subprocess.getoutput("git rev-parse --abbrev-ref @")
+ return facts
+
+
+def update_file(fname, pattern, replacement):
+ """Update the contents of a file, replacing pattern with replacement."""
+ with open(fname) as fobj:
+ old_text = fobj.read()
+
+ new_text = re.sub(pattern, replacement, old_text, count=1)
+
+ if new_text != old_text:
+ print(f"Updating {fname}")
+ with open(fname, "w") as fobj:
+ fobj.write(new_text)
+
+UNRELEASED = "Unreleased\n----------"
+
+def do_edit_for_release():
+ """Edit a few files in preparation for a release."""
+ facts = get_release_facts()
+
+ # NOTICE.txt
+ update_file("NOTICE.txt", r"Copyright 2004.*? Ned", f"Copyright 2004-{facts.now:%Y} Ned")
+
+ # CHANGES.rst
+ title = f"Version {facts.ver} — {facts.now:%Y-%m-%d}"
+ rule = "-" * len(title)
+ new_head = f".. _changes_{facts.anchor}:\n\n{title}\n{rule}"
+
+ update_file("CHANGES.rst", re.escape(UNRELEASED), new_head)
+
+ # doc/conf.py
+ new_conf = textwrap.dedent(f"""\
+ # @@@ editable
+ copyright = "2009\N{EN DASH}{facts.now:%Y}, Ned Batchelder" # pylint: disable=redefined-builtin
+ # The short X.Y.Z version.
+ version = "{facts.shortver}"
+ # The full version, including alpha/beta/rc tags.
+ release = "{facts.ver}"
+ # The date of release, in "monthname day, year" format.
+ release_date = "{facts.now:%B %-d, %Y}"
+ # @@@ end
+ """)
+ update_file("doc/conf.py", r"(?s)# @@@ editable\n.*# @@@ end\n", new_conf)
+
+
+def do_bump_version():
+ """Edit a few files right after a release to bump the version."""
+ facts = get_release_facts()
+
+ # CHANGES.rst
+ update_file(
+ "CHANGES.rst",
+ r"(?m)^\.\. _changes_",
+ f"{UNRELEASED}\n\nNothing yet.\n\n\n.. _changes_",
+ )
+
+ # coverage/version.py
+ next_version = f"version_info = {facts.next_vi}".replace("'", '"')
+ update_file("coverage/version.py", r"(?m)^version_info = .*$", next_version)
+
+
def do_cheats():
"""Show a cheatsheet of useful things during releasing."""
- import coverage
- ver = coverage.__version__
- vi = coverage.version_info
- shortver = f"{vi[0]}.{vi[1]}.{vi[2]}"
- anchor = shortver.replace(".", "-")
- if vi[3] != "final":
- anchor += f"{vi[3][0]}{vi[4]}"
- now = datetime.datetime.now()
- branch = subprocess.getoutput("git rev-parse --abbrev-ref @")
- print(f"Coverage version is {ver}")
-
- print(f"pip install git+https://github.com/nedbat/coveragepy@{branch}")
- print(f"https://coverage.readthedocs.io/en/{ver}/changes.html#changes-{anchor}")
-
- print("\n## for CHANGES.rst before release:")
- print(f".. _changes_{anchor}:")
- print()
- head = f"Version {ver} — {now:%Y-%m-%d}"
- print(head)
- print("-" * len(head))
-
- print("\n## For doc/conf.py before release:")
- print("\n".join([
- '# The short X.Y.Z version. # CHANGEME',
- f'version = "{shortver}"',
- '# The full version, including alpha/beta/rc tags. # CHANGEME',
- f'release = "{ver}"',
- '# The date of release, in "monthname day, year" format. # CHANGEME',
- f'release_date = "{now:%B %-d, %Y}"',
- ]))
+ facts = get_release_facts()
+ print(f"Coverage version is {facts.ver}")
+
+ print(f"pip install git+https://github.com/nedbat/coveragepy@{facts.branch}")
+ print(f"https://coverage.readthedocs.io/en/{facts.ver}/changes.html#changes-{facts.anchor}")
print(
"\n## For GitHub commenting:\n" +
"This is now released as part of " +
- f"[coverage {ver}](https://pypi.org/project/coverage/{ver})."
+ f"[coverage {facts.ver}](https://pypi.org/project/coverage/{facts.ver})."
)
- print("\n## For version.py next:")
- next_vi = (vi[0], vi[1], vi[2]+1, "alpha", 0)
- print(f"version_info = {next_vi}".replace("'", '"'))
- print("\n## For CHANGES.rst after release:")
- print(textwrap.dedent("""\
- Unreleased
- ----------
-
- Nothing yet.
-
-
- """))
def do_help():