diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f8e4031..a41643b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -22,7 +22,7 @@ on: jobs: lint: - name: 'lint & typecheck & test (Python ${{ matrix.python }})' + name: "lint & typecheck & test (Python ${{ matrix.python }}${{ matrix.baseline && ', baseline deps' || '' }}${{ matrix.experimental && ', experimental' || '' }})" runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental }} strategy: @@ -33,24 +33,50 @@ jobs: - '3.11' - '3.12' experimental: [false] + baseline: [false] include: - python: '3.13' + baseline: false experimental: true + - python: '3.10' + baseline: true + experimental: false steps: - uses: actions/checkout@v4 + + - name: Install deps system-wide + if: success() && matrix.baseline + run: | + ./scripts/install-baseline-deps.sh + # give the Poetry environment access to the system-wide deps + # this has to be done before virtualenv creation + export POETRY_VIRTUALENVS_OPTIONS_SYSTEM_SITE_PACKAGES=true + - name: Install Poetry run: pipx install poetry - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} cache: poetry - - name: Install deps + + - name: Install deps in the venv + if: success() && !matrix.baseline run: poetry install --with=dev + - name: Install only the dev tools in the venv + if: success() && matrix.baseline + run: poetry install --only=dev + - name: Lint with ruff run: poetry run ruff check - name: Type-check with mypy + # it is rather cumbersome to work with ancient versions of deps that + # lack type annotations, so just rely on the CI job running with + # non-baseline deps + if: success() && !matrix.baseline run: poetry run mypy - name: Type-check with pyright + # same with pyright + if: success() && !matrix.baseline run: poetry run -- pyright --pythonversion ${{ matrix.python }} - name: Test with pytest run: poetry run pytest diff --git a/poetry.lock b/poetry.lock index 3a96a04..fa1cac0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1033,4 +1033,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "9c530aa0b089259b1388da31f33c6d036dded373eed6f35672466f0e229ee667" +content-hash = "e1e169e55bdc5d8536ba3b1c5fb2dc7b4c6a9fd1d5d8faf42dcad20ee3058b88" diff --git a/pyproject.toml b/pyproject.toml index c9610f0..33641c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,7 +87,7 @@ mypy = "^1.9.0" pyright = "^1.1.389" pytest = "^8.2.2" ruff = "^0.8.1" -typing-extensions = "^4.12.2" +typing-extensions = ">=3.10.0.2" types-cffi = "^1.16.0.20240106" types-pygit2 = "^1.14.0.20240317" diff --git a/ruyi/utils/ar.py b/ruyi/utils/ar.py index 405b720..e2c2119 100644 --- a/ruyi/utils/ar.py +++ b/ruyi/utils/ar.py @@ -8,8 +8,8 @@ class ArpyArchiveWrapper(arpy.Archive, AbstractContextManager["arpy.Archive"]): - """Compatibility context manager shim for arpy.Archive, for working across - arpy 1.x and 2.x.""" + """Compatibility shim for arpy.Archive, for easy interop with both arpy 1.x + and 2.x.""" def __init__( self, @@ -38,3 +38,37 @@ def __exit__( # backport of arpy 2.x __exit__ implementation self.close() + + def infolist(self) -> list[arpy.ArchiveFileHeader]: + if hasattr(super(), "infolist"): + return super().infolist() + + # backport of arpy 2.x infolist() + self.read_all_headers() + return [ + header + for header in self.headers + if header.type + in ( + arpy.HEADER_BSD, + arpy.HEADER_NORMAL, + arpy.HEADER_GNU, + ) + ] + + def open(self, name: bytes | arpy.ArchiveFileHeader) -> arpy.ArchiveFileData: + if hasattr(super(), "open"): + return super().open(name) + + # backport of arpy 2.x open() + if isinstance(name, bytes): + ar_file = self.archived_files.get(name) + if ar_file is None: + raise KeyError("There is no item named %r in the archive" % (name,)) + + return ar_file + + if name not in self.headers: + raise KeyError("Provided header does not match this archive") + + return arpy.ArchiveFileData(ar_obj=self, header=name) diff --git a/scripts/install-baseline-deps.sh b/scripts/install-baseline-deps.sh new file mode 100755 index 0000000..fc11915 --- /dev/null +++ b/scripts/install-baseline-deps.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +main() { + local pkglist=( + # Package versions provided by Ubuntu 22.04 LTS. + python3-arpy # 1.1.1 + python3-certifi # 2020.6.20 + python3-jinja2 # 3.0.3 + python3-packaging # 21.3 + python3-pygit2 # 1.6.1 + python3-yaml # 5.4.1 # https://github.com/yaml/pyyaml/issues/724 + python3-requests # 2.25.1 + python3-rich # 11.2.0 + python3-semver # 2.10.2 + python3-tomli # 1.2.2 + python3-tomlkit # 0.9.2 + python3-typing-extensions # 3.10.0.2 + ) + + export DEBIAN_FRONTEND=noninteractive + export DEBCONF_NONINTERACTIVE_SEEN=true + sudo apt-get update -qqy + sudo apt-get install -y "${pkglist[@]}" +} + +main "$@"