diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index befd5af..4c6267e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,9 @@ on: permissions: contents: read +env: + FORCE_COLOR: 1 + jobs: # Always build & lint package. build-package: @@ -47,6 +50,7 @@ jobs: - name: Publish to Test PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: + attestations: true repository-url: https://test.pypi.org/legacy/ # Publish to PyPI on GitHub Releases. @@ -78,3 +82,5 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + with: + attestations: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 388811d..276a00b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,6 +2,9 @@ name: Test on: [push, pull_request, workflow_dispatch] +permissions: + contents: read + env: FORCE_COLOR: 1 @@ -11,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 009c104..353ced5 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,6 @@ ENV/ # pytest .pytest_cache/ + +# hatch-vcs +src/*/_version.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a8986c4..c076739 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,26 +2,39 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: + - id: check-added-large-files - id: check-case-conflict - id: check-merge-conflict - id: check-toml - id: check-yaml - id: debug-statements - id: end-of-file-fixer + - id: forbid-submodules - id: trailing-whitespace + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.29.2 + hooks: + - id: check-dependabot + - id: check-github-workflows + + - repo: https://github.com/rhysd/actionlint + rev: v1.7.2 + hooks: + - id: actionlint + - repo: https://github.com/tox-dev/pyproject-fmt - rev: 2.1.3 + rev: 2.2.4 hooks: - id: pyproject-fmt - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.18 + rev: v0.20.2 hooks: - id: validate-pyproject - repo: https://github.com/tox-dev/tox-ini-fmt - rev: 1.3.1 + rev: 1.4.1 hooks: - id: tox-ini-fmt diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a7e7bf..1409fc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,19 @@ # Changelog -## 1.2.2 +## 1.3.1 - Add the `-i/--issue` and `-s/--section` options to the `add` command. This lets you pre-fill the `gh-issue` and `section` fields in the template. + Added by @picnixz in https://github.com/python/blurb/pull/16. + +## 1.3.0 + +* Add support for Python 3.13 by @hugovk in https://github.com/python/blurb/pull/26 +* Drop support for Python 3.8 by @hugovk in https://github.com/python/blurb/pull/27 +* Generate digital attestations for PyPI (PEP 740) by @hugovk in https://github.com/python/blurb/pull/28 +* Allow running blurb test from blurb-* directories by @hroncok in https://github.com/python/blurb/pull/24 +* Add `version` subcommand by @hugovk in https://github.com/python/blurb/pull/29 +* Generate `__version__` at build to avoid slow `importlib.metadata` import by @hugovk in https://github.com/python/blurb/pull/30 ## 1.2.1 diff --git a/README.md b/README.md index 9045c2c..eea1f46 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,6 @@ and automatically uses the correct file paths. You can install **blurb** from PyPI using `pip`. Alternatively, simply add `blurb` to a directory on your path. -**blurb**'s only dependency is Python 3.8+. - ## Files used by blurb diff --git a/pyproject.toml b/pyproject.toml index 0843f61..713dfb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,12 +15,11 @@ maintainers = [ authors = [ { name = "Larry Hastings", email = "larry@hastings.org" }, ] -requires-python = ">=3.8" +requires-python = ">=3.9" classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -43,6 +42,9 @@ scripts.blurb = "blurb.blurb:main" [tool.hatch] version.source = "vcs" +[tool.hatch.build.hooks.vcs] +version-file = "src/blurb/_version.py" + [tool.hatch.version.raw-options] local_scheme = "no-local-version" diff --git a/src/blurb/__init__.py b/src/blurb/__init__.py index 63dfcac..8dee4bf 100644 --- a/src/blurb/__init__.py +++ b/src/blurb/__init__.py @@ -1,3 +1 @@ -import importlib.metadata - -__version__ = importlib.metadata.version(__name__) +from ._version import __version__ diff --git a/src/blurb/blurb.py b/src/blurb/blurb.py index c893dc2..285311a 100755 --- a/src/blurb/blurb.py +++ b/src/blurb/blurb.py @@ -645,7 +645,7 @@ def save_next(self): tests_run = 0 class TestParserPasses(unittest.TestCase): - directory = "blurb/tests/pass" + directory = "tests/pass" def filename_test(self, filename): b = Blurbs() @@ -670,7 +670,7 @@ def test_files(self): class TestParserFailures(TestParserPasses): - directory = "blurb/tests/fail" + directory = "tests/fail" def filename_test(self, filename): b = Blurbs() @@ -745,6 +745,13 @@ def get_subcommand(subcommand): +@subcommand +def version(): + """Print blurb version.""" + print("blurb version", __version__) + + + @subcommand def help(subcommand=None): """ @@ -826,8 +833,19 @@ def help(subcommand=None): print(doc) sys.exit(0) -# Make "blurb --help" work. +# Make "blurb --help/--version/-V" work. subcommands["--help"] = help +subcommands["--version"] = version +subcommands["-V"] = version + + +def _find_blurb_dir(): + if os.path.isdir("blurb"): + return "blurb" + for path in glob.iglob("blurb-*"): + if os.path.isdir(path): + return path + return None @subcommand @@ -838,12 +856,13 @@ def test(*args): # unittest.main doesn't work because this isn't a module # so we'll do it ourselves - while not os.path.isdir("blurb"): + while (blurb_dir := _find_blurb_dir()) is None: old_dir = os.getcwd() os.chdir("..") if old_dir == os.getcwd(): # we reached the root and never found it! sys.exit("Error: Couldn't find the root of your blurb repo!") + os.chdir(blurb_dir) print("-" * 79) @@ -1379,7 +1398,7 @@ def main(): fn = get_subcommand(subcommand) # hack - if fn in (test, help): + if fn in (help, test, version): sys.exit(fn(*args)) try: diff --git a/tests/test_blurb.py b/tests/test_blurb.py index 7cbdef6..7a2c499 100644 --- a/tests/test_blurb.py +++ b/tests/test_blurb.py @@ -186,3 +186,12 @@ def test_extract_next_filename(news_entry, expected_path, fs): # Assert assert path == expected_path + + +def test_version(capfd): + # Act + blurb.version() + + # Assert + captured = capfd.readouterr() + assert captured.out.startswith("blurb version ") diff --git a/tox.ini b/tox.ini index 793f226..fa69718 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ requires = tox>=4.2 env_list = - py{313, 312, 311, 310, 39, 38} + py{313, 312, 311, 310, 39} [testenv] extras = @@ -19,5 +19,7 @@ commands = {posargs} blurb test blurb help + blurb --version {envpython} -I -m blurb test {envpython} -I -m blurb help + {envpython} -I -m blurb version