diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1882757 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: CI + +on: + workflow_dispatch: + push: + branches: + - main + tags: + - 'v*' + pull_request: + branches: + - main + +jobs: + + lint: + name: Linting + timeout-minutes: 5 + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v5 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.13' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ruff + - name: Ruff lint + run: | + ruff check --output-format=github . + - name: Ruff format + run: | + ruff format --check . + diff --git a/_version.py b/_version.py index b3d9fff..28e4a76 100644 --- a/_version.py +++ b/_version.py @@ -1,5 +1,5 @@ """ -_version.py v1.3 +_version.py v1.4 Simple version string management, using a hard-coded version string for simplicity and compatibility, while adding git info at runtime. @@ -14,11 +14,12 @@ * On a new release, you just update the __version__. """ +# ruff: noqa: RUF100, S310, PLR2004, D400, D415, S603, BLE001 + import logging import subprocess from pathlib import Path - # This is the base version number, to be bumped before each release. # The build system detects this definition when building a distribution. __version__ = "0.0.0" @@ -35,17 +36,15 @@ repo_dir = repo_dir if repo_dir.joinpath(".git").exists() else None -def get_version(): +def get_version() -> str: """Get the version string.""" if repo_dir: return get_extended_version() - else: - return __version__ + return __version__ -def get_extended_version(): +def get_extended_version() -> str: """Get an extended version string with information from git.""" - release, post, labels = get_version_info_from_git() # Sample first 3 parts of __version__ @@ -55,9 +54,9 @@ def get_extended_version(): if not release: release = base_release elif release != base_release: - logger.warning( + warning( f"{project_name} version from git ({release})" - + f" and __version__ ({base_release}) don't match." + f" and __version__ ({base_release}) don't match." ) # Build the total version @@ -72,14 +71,14 @@ def get_extended_version(): return version -def get_version_info_from_git(): - """Get (release, post, labels) from Git. +def get_version_info_from_git() -> str: + """ + Get (release, post, labels) from Git. With `release` the version number from the latest tag, `post` the number of commits since that tag, and `labels` a tuple with the git-hash and optionally a dirty flag. """ - # Call out to Git command = [ "git", @@ -91,9 +90,11 @@ def get_version_info_from_git(): "--first-parent", ] try: - p = subprocess.run(command, cwd=repo_dir, capture_output=True) + p = subprocess.run( + command, check=False, cwd=repo_dir, capture_output=True + ) except Exception as e: - logger.warning(f"Could not get {project_name} version: {e}") + warning(f"Could not get {project_name} version: {e}") p = None # Parse the result into parts @@ -103,7 +104,7 @@ def get_version_info_from_git(): output = p.stdout.decode(errors="ignore") if p.returncode: stderr = p.stderr.decode(errors="ignore") - logger.warning( + warning( f"Could not get {project_name} version.\n\nstdout: " + output + "\n\nstderr: " @@ -121,16 +122,23 @@ def get_version_info_from_git(): return release, post, labels -def _to_tuple(v): - """Convert __version__ to version_info tuple.""" +def version_to_tuple(v: str) -> tuple: v = __version__.split("+")[0] # remove hash return tuple(int(i) if i.isnumeric() else i for i in v.split(".")) +def prnt(m: str) -> None: + sys.stdout.write(m + "\n") + + +def warning(m: str) -> None: + logger.warning(m) + + # Apply the versioning base_version = __version__ __version__ = get_version() -version_info = _to_tuple(__version__) +version_info = version_to_tuple(__version__) # The CLI part @@ -150,27 +158,25 @@ def _to_tuple(v): import urllib.request _, *args = sys.argv + this_file = Path(__file__) - if not args: - print(f"{project_name} v{__version__}") - - elif args[0] == "version": - print(f"{project_name} v{__version__}") + if not args or args[0] == "version": + prnt(f"{project_name} v{__version__}") elif args[0] == "bump": if len(args) != 2: sys.exit("Expected a version number to bump to.") new_version = args[1].lstrip("v") # allow '1.2.3' and 'v1.2.3' - if not new_version.count(".") == 2: + if new_version.count(".") != 2: sys.exit("Expected two dots in new version string.") if not all(s.isnumeric() for s in new_version.split(".")): sys.exit("Expected only numbers in new version string.") - with open(__file__, "rb") as f: + with this_file.open("rb") as f: text = ref_text = f.read().decode() text = text.replace(base_version, new_version, 1) - with open(__file__, "wb") as f: + with this_file.open("wb") as f: f.write(text.encode()) - print(f"Bumped version from '{base_version}' to '{new_version}'.") + prnt(f"Bumped version from '{base_version}' to '{new_version}'.") elif args[0] == "update": u = "https://raw.githubusercontent.com/pygfx/_version/main/_version.py" @@ -178,13 +184,13 @@ def _to_tuple(v): text = ref_text = f.read().decode() text = text.replace("0.0.0", base_version, 1) text = text.replace("PROJECT_NAME", project_name, 1) - with open(__file__, "wb") as f: + with this_file.open("wb") as f: f.write(text.encode()) - print("Updated to the latest _version.py.") + prnt("Updated to the latest _version.py.") elif args[0].lstrip("-") in ["h", "help"]: - print(CLI_USAGE) + prnt(CLI_USAGE) else: - print(f"Unknown command for _version.py: {args[0]!r}") - print("Use ``python _version.py help`` to see a list of options.") + prnt(f"Unknown command for _version.py: {args[0]!r}") + prnt("Use ``python _version.py help`` to see a list of options.") diff --git a/pyproject.toml b/pyproject.toml index a9587a2..3eedf38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,4 +2,7 @@ line-length = 80 [tool.ruff.lint] -select = ["F", "E", "W", "N", "B", "RUF", "TC"] +# Run all the rules, we turn some rules off in the file itself. +select = ["ALL"] +# Ignore rules that are conflicting, and would otherwise produce a warning with 'ruff format' +ignore = ["D203", "D212", "COM812"]