Buckets:

glennmatlin's picture
download
raw
5.34 kB
from __future__ import annotations
import os
import sys
import json
import logging
import subprocess
from typing import Any
from pathlib import Path
from . import node, _mureq as mureq
from .utils import env_to_bool, get_cache_dir, get_latest_version
from ._version import __version__, __pyright_version__
ROOT_CACHE_DIR = get_cache_dir() / 'pyright-python'
DEFAULT_PACKAGE_JSON: dict[str, Any] = {
'name': 'pyright-binaries',
'version': '1.0.0',
'private': True,
'description': 'Cache directory created by Pyright Python to store downloads of the NPM package',
'main': 'node_modules/pyright/index.js',
'author': 'RobertCraigie',
'license': 'Apache-2.0',
}
log: logging.Logger = logging.getLogger(__name__)
def install_pyright(args: tuple[object, ...], *, quiet: bool | None) -> Path:
"""Internal helper function to install the Pyright npm package to a cache.
This returns the path to the installed package.
This accepts a single argument which corresponds to the arguments given to the CLI / langserver
which are used to determine whether or not certain warnings / logs will be printed.
"""
version = _get_configured_pyright_version()
if version == 'latest':
version = node.latest('pyright')
else:
if _should_warn_version(args=args, quiet=quiet):
print(
f'WARNING: there is a new pyright version available (v{version} -> v{get_latest_version()}).\n'
+ 'Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`\n'
)
if version == __pyright_version__ and env_to_bool('PYRIGHT_PYTHON_USE_BUNDLED_PYRIGHT', default=True):
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)
pkg_dir = cache_dir / 'node_modules' / 'pyright'
package_json = cache_dir / 'package.json'
current_version = node.get_pkg_version(pkg_dir / 'package.json')
if current_version is None or current_version != version:
# We need to create a dummy `package.json` file so that `npm` doesn't try
# and search for it elsewhere.
#
# If it finds a different `package.json` file then the `pyright` package
# will be installed there instead of our cache directory.
if not package_json.exists():
package_json.write_text(json.dumps(DEFAULT_PACKAGE_JSON, indent=2))
silent = '--outputjson' in args
node.run(
'npm',
'install',
f'pyright@{version}',
cwd=str(cache_dir),
check=True,
stdout=subprocess.PIPE if silent else sys.stdout,
stderr=subprocess.PIPE if silent else sys.stderr,
)
return pkg_dir
def _get_configured_pyright_version() -> str:
force_version = os.environ.get('PYRIGHT_PYTHON_FORCE_VERSION')
if force_version:
return force_version
pylance_version = os.environ.get('PYRIGHT_PYTHON_PYLANCE_VERSION')
if pylance_version:
return _get_pylance_pyright_version(pylance_version)
return __pyright_version__
def _get_pylance_pyright_version(pylance_version: str) -> str:
url = f'https://raw.githubusercontent.com/microsoft/pylance-release/main/releases/{pylance_version}.json'
try:
response = mureq.get(url, timeout=1)
response.raise_for_status()
data = response.json()
log.debug(f'Pylance release data: {data}')
version = data['pyrightVersion']
log.debug(f'Pylance {pylance_version} uses pyright version {version}')
return version
except Exception as exc:
log.debug(f'Failed to download release metadata for Pylance {pylance_version} from {url}: {type(exc)} - {exc}')
raise
def _should_warn_version(
*,
args: tuple[object, ...],
quiet: bool | None,
) -> bool:
if quiet:
# This flag is set by the language server as the output must always be machine parseable
return False
if '--outputjson' in args:
# If this flag is set then the output must be machine parseable
return False
if env_to_bool('PYRIGHT_PYTHON_IGNORE_WARNINGS', default=False):
return False
# Don't warn about the pyright version if a Pylance version is specified, since the latest
# Pylance release may not include the latest pyright release yet.
if os.environ.get('PYRIGHT_PYTHON_PYLANCE_VERSION'):
return False
force_version = os.environ.get('PYRIGHT_PYTHON_FORCE_VERSION')
if force_version and force_version != __pyright_version__:
return True
# NOTE: there is an edge case here where a new pyright version has been released
# but we haven't made a new pyright-python release yet and the user has set
# PYRIGHT_PYTHON_FORCE_VERSION to the new pyright version.
# This should rarely happen as we make new releases very frequently after
# pyright does. Also in order to correctly compare versions we would need an additional
# dependency. As such this is an acceptable bug.
latest = get_latest_version()
return latest is not None and latest != __version__

Xet Storage Details

Size:
5.34 kB
·
Xet hash:
d703d48c25bb5371abf72a713379c3c85dd50937716cfc233abf149200bfc484

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.