Skip to content

Commit

Permalink
feat: bundle pyright inside wheel
Browse files Browse the repository at this point in the history
See original RobertCraigie#300
  • Loading branch information
cswartzvi committed Dec 16, 2024
1 parent 3c44bae commit 9a48dec
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 6 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ jobs:
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
python-version: "3.12"

- name: Install dependencies
run: |
python -m pip install -r dev-requirements.txt
- name: Download pyright dist
run: |
python scripts/download_pyright.py
- name: Get version
run: |
echo "NEW_VERSION=$(python .github/scripts/get_version.py --compare)" >> $GITHUB_ENV
Expand Down
27 changes: 25 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
matrix:
os: [ubuntu-latest, macos-12, windows-latest]
node: [14, 16]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.12']

steps:
- uses: actions/checkout@v3
Expand All @@ -45,6 +45,10 @@ jobs:
python -m pip install --upgrade pip
pip install -r dev-requirements.txt
- name: Download pyright dist
run: |
python scripts/download_pyright.py
- uses: actions/cache@v2
with:
path: ~/.cache/pip
Expand Down Expand Up @@ -119,6 +123,15 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Download pyright dist
run: |
python scripts/download_pyright.py
- name: Docker Build
uses: docker/build-push-action@v3
# https://github.com/docker/build-push-action/#inputs
Expand All @@ -136,6 +149,16 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Download pyright dist
run: |
python scripts/download_pyright.py
- name: Docker Build
# Use --% to allow double hyphen
# Caching not currently working since we don't use buildx yet, windows
Expand Down Expand Up @@ -173,4 +196,4 @@ jobs:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
jobs: ${{ toJSON(needs) }}
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ include = [
"tests",
]
exclude = [
"src/pyright/_mureq.py"
"src/pyright/_mureq.py",
"src/pyright/dist",
]
pythonVersion = "3.9"

Expand Down
68 changes: 68 additions & 0 deletions scripts/download_pyright.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import io
import sys
import json
import shutil
import tarfile
from pathlib import Path

import pyright
from pyright import _mureq, __pyright_version__

DIST_DIR = Path(pyright.__file__).parent / 'dist'


def _should_download() -> bool:
if '--force' in sys.argv:
return True

pkg_path = DIST_DIR / 'package.json'
if not pkg_path.exists():
return True

pkg_json = json.loads(pkg_path.read_text())
if pkg_json['version'] == __pyright_version__:
print(
f'skipping download as the current pyright version ({__pyright_version__}) is already downloaded. use --force to override'
)
return False

return True


def download_tarball(*, version: str) -> None:
if not _should_download():
return

if DIST_DIR.exists():
shutil.rmtree(DIST_DIR)

rsp = _mureq.get(f'https://registry.npmjs.org/pyright/{version}')
rsp.raise_for_status()

info = rsp.json()
tar_url = info['dist']['tarball']
print(f'downloading tar from {tar_url}')

rsp = _mureq.get(tar_url)
rsp.raise_for_status()

with tarfile.open(fileobj=io.BytesIO(rsp.body)) as tar:
members = tar.getmembers()

# npm tarballs will always output one `package/` directory which is
# not necessary for our case, so we strip out the `package/` prefix
for member in members:
if member.path.startswith('package/'):
member.path = member.path.replace('package/', '', 1)
else:
raise RuntimeError(f'expected tar member path to start with `package/` but got {member.path}')

tar.extractall(path=DIST_DIR, members=members)


def main() -> None:
download_tarball(version=__pyright_version__)


if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
include=['pyright', 'pyright.*'],
),
package_dir={'': 'src'},
package_data={'': ['py.typed']},
package_data={'': ['py.typed', 'dist/**']},
python_requires='>=3.7',
include_package_data=True,
zip_safe=False,
Expand Down
6 changes: 6 additions & 0 deletions src/pyright/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ def install_pyright(args: tuple[object, ...], *, quiet: bool | None) -> Path:
+ 'Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`\n'
)

if version == __pyright_version__:
bundled_path = Path(__file__).parent.joinpath('dist')
if bundled_path.exists():
log.debug('using bundled pyright at %s', bundled_path)
return bundled_path

cache_dir = ROOT_CACHE_DIR / version
cache_dir.mkdir(exist_ok=True, parents=True)

Expand Down
8 changes: 7 additions & 1 deletion tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

import pyright
from pyright import __pyright_version__
from tests.utils import assert_matches
from tests.utils import assert_matches, is_relative_to
from pyright.utils import maybe_decode
from pyright._utils import install_pyright

if TYPE_CHECKING:
from _pytest.monkeypatch import MonkeyPatch
Expand Down Expand Up @@ -238,3 +239,8 @@ def test_package_json_in_parent_dir(tmp_path: Path, monkeypatch: MonkeyPatch) ->
check=True,
)
assert proc.returncode == 0


def test_install_pyright_uses_bundled_by_default() -> None:
install_path = install_pyright(tuple(), quiet=None)
assert is_relative_to(install_path, Path(pyright.__file__).parent)
14 changes: 14 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from __future__ import annotations

import re
from os import PathLike
from pathlib import Path
from typing_extensions import TypeAlias

StrPath: TypeAlias = 'str | PathLike[str]'


def assert_matches(pattern: re.Pattern[str], contents: str) -> re.Match[str]:
Expand All @@ -9,3 +14,12 @@ def assert_matches(pattern: re.Pattern[str], contents: str) -> re.Match[str]:
raise ValueError(f'Pattern, {pattern}, did not match input: {contents}')

return match


def is_relative_to(path: StrPath, to: StrPath) -> bool:
"""Backport of Path.is_relative_to for Python < 3.9"""
try:
Path(path).relative_to(to)
return True
except ValueError:
return False

0 comments on commit 9a48dec

Please sign in to comment.