Skip to content

Commit 918ddc0

Browse files
authored
chore: vendor get-pip, enable network isolation (#26101)
Verification build: https://dev.azure.com/monacotools/Monaco/_build/results?buildId=462156&view=results Fixes #26064
1 parent ea473c0 commit 918ddc0

10 files changed

Lines changed: 28049 additions & 62 deletions

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ cucumber-report.json
2424
port.txt
2525
precommit.hook
2626
python_files/lib/**
27-
python_files/get-pip.py
2827
debug_coverage*/**
2928
languageServer/**
3029
languageServer.*/**

.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ out/test/**
6363
out/testMultiRootWkspc/**
6464
precommit.hook
6565
python_files/**/*.pyc
66+
python_files/download_get_pip.py
6667
python_files/lib/**/*.egg-info/**
6768
python_files/lib/jedilsp/bin/**
6869
python_files/lib/python/bin/**

build/azure-pipeline.pre-release.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ extends:
8787
architecture: 'x64'
8888
displayName: Select Python version
8989

90+
- task: PipAuthenticate@1
91+
inputs:
92+
artifactFeeds: 'Monaco/vscode'
93+
displayName: Authenticate to vscode feed
94+
9095
- script: python -m pip install -U pip
9196
displayName: Upgrade pip
9297

@@ -97,7 +102,7 @@ extends:
97102
displayName: Install NPM dependencies
98103

99104
- script: nox --session install_python_libs
100-
displayName: Install Jedi, get-pip, etc
105+
displayName: Install Python extension dependencies
101106

102107
- script: python ./build/update_package_file.py
103108
displayName: Update telemetry in package.json

build/azure-pipeline.stable.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ extends:
8181
architecture: 'x64'
8282
displayName: Select Python version
8383

84+
- task: PipAuthenticate@1
85+
inputs:
86+
artifactFeeds: 'Monaco/vscode'
87+
displayName: Authenticate to vscode feed
88+
8489
- script: python -m pip install -U pip
8590
displayName: Upgrade pip
8691

@@ -91,7 +96,7 @@ extends:
9196
displayName: Install NPM dependencies
9297

9398
- script: nox --session install_python_libs
94-
displayName: Install Jedi, get-pip, etc
99+
displayName: Install Python extension dependencies
95100

96101
- script: python ./build/update_package_file.py
97102
displayName: Update telemetry in package.json

build/build-install-requirements.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.

cgmanifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Component": {
55
"Other": {
66
"Name": "get-pip",
7-
"Version": "21.3.1",
7+
"Version": "26.2.1",
88
"DownloadUrl": "https://github.com/pypa/get-pip"
99
},
1010
"Type": "other"

noxfile.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,6 @@ def install_python_libs(session: nox.Session):
5555
session.install("packaging")
5656
session.install("debugpy")
5757

58-
# Download get-pip script
59-
session.run(
60-
"python",
61-
"./python_files/download_get_pip.py",
62-
env={"PYTHONPATH": "./python_files/lib/temp"},
63-
)
64-
6558
if pathlib.Path("./python_files/lib/temp").exists():
6659
shutil.rmtree("./python_files/lib/temp")
6760

python_files/download_get_pip.py

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,75 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33

4+
# This file is now a standalone Python script that
5+
# updates the vendored get-pip.py and cgmanifest.json
6+
# to the latest pip release.
7+
8+
import argparse
49
import json
510
import pathlib
6-
import urllib.request as url_lib
7-
8-
from packaging.version import parse as version_parser
11+
import urllib.request
12+
from typing import Optional
913

1014
EXTENSION_ROOT = pathlib.Path(__file__).parent.parent
11-
GET_PIP_DEST = EXTENSION_ROOT / "python_files"
12-
PIP_PACKAGE = "pip"
13-
PIP_VERSION = "latest" # Can be "latest", or specific version "23.1.2"
14-
15-
16-
def _get_package_data():
17-
json_uri = f"https://pypi.org/pypi/{PIP_PACKAGE}/json"
18-
# Response format: https://warehouse.readthedocs.io/api-reference/json/#project
19-
# Release metadata format: https://github.com/pypa/interoperability-peps/blob/master/pep-0426-core-metadata.rst
20-
with url_lib.urlopen(json_uri) as response:
21-
return json.loads(response.read())
22-
23-
24-
def _download_and_save(root, version):
25-
root = pathlib.Path.cwd() if root is None or root == "." else pathlib.Path(root)
26-
url = f"https://raw.githubusercontent.com/pypa/get-pip/{version}/public/get-pip.py"
27-
print(url)
28-
with url_lib.urlopen(url) as response:
29-
data = response.read()
30-
get_pip_file = root / "get-pip.py"
31-
get_pip_file.write_bytes(data)
32-
33-
34-
def main(root):
35-
data = _get_package_data()
36-
37-
if PIP_VERSION == "latest":
38-
# Pick latest 5 versions to try and get-pip
39-
sorted_versions = sorted(data["releases"].keys(), key=version_parser, reverse=True)[:5]
40-
downloaded = False
41-
while sorted_versions:
42-
use_version = sorted_versions.pop(0)
43-
try:
44-
print(f"Trying version: get-pip == {use_version}")
45-
_download_and_save(root, use_version)
46-
downloaded = True
47-
break
48-
except Exception as e:
49-
print(f"Failed to download get-pip == {use_version}: {e}")
50-
print(f"NExt attempt(s) with versions: {sorted_versions}")
51-
if not downloaded:
52-
raise Exception("Failed to download get-pip.py")
53-
else:
54-
use_version = PIP_VERSION
55-
_download_and_save(root, use_version)
15+
GET_PIP_DEST = EXTENSION_ROOT / "python_files" / "get-pip.py"
16+
CGMANIFEST_PATH = EXTENSION_ROOT / "cgmanifest.json"
17+
PIP_METADATA_URL = "https://pypi.org/pypi/pip/json"
18+
GET_PIP_URL = "https://raw.githubusercontent.com/pypa/get-pip/{version}/public/get-pip.py"
19+
20+
21+
def _get_latest_version() -> str:
22+
with urllib.request.urlopen(PIP_METADATA_URL) as response:
23+
metadata = json.load(response)
24+
25+
version = metadata.get("info", {}).get("version")
26+
if not isinstance(version, str) or not version:
27+
raise ValueError(f"PyPI metadata from {PIP_METADATA_URL} did not contain a version")
28+
return version
29+
30+
31+
def _download_get_pip(version: str) -> bytes:
32+
url = GET_PIP_URL.format(version=version)
33+
print(f"Downloading {url}")
34+
with urllib.request.urlopen(url) as response:
35+
get_pip = response.read()
36+
37+
expected_version = f"pip (version {version})".encode()
38+
if expected_version not in get_pip[:1024]:
39+
raise ValueError(f"Downloaded get-pip.py did not contain pip {version}")
40+
return get_pip
41+
42+
43+
def _update_cgmanifest(version: str) -> str:
44+
manifest = json.loads(CGMANIFEST_PATH.read_text(encoding="utf-8"))
45+
for registration in manifest["Registrations"]:
46+
component = registration.get("Component", {}).get("Other", {})
47+
if component.get("Name") == "get-pip":
48+
component["Version"] = version
49+
return f"{json.dumps(manifest, indent=4)}\n"
50+
51+
raise ValueError(f"get-pip registration was not found in {CGMANIFEST_PATH}")
52+
53+
54+
def refresh_get_pip(version: Optional[str] = None) -> None:
55+
version = version or _get_latest_version()
56+
get_pip = _download_get_pip(version)
57+
cgmanifest = _update_cgmanifest(version)
58+
59+
GET_PIP_DEST.write_bytes(get_pip)
60+
CGMANIFEST_PATH.write_text(cgmanifest, encoding="utf-8")
61+
print(f"Updated {GET_PIP_DEST} and {CGMANIFEST_PATH} to get-pip {version}")
62+
63+
64+
def main() -> None:
65+
parser = argparse.ArgumentParser(description="Refresh the vendored get-pip.py")
66+
parser.add_argument(
67+
"--version",
68+
help="pip release to vendor; defaults to the latest release on PyPI",
69+
)
70+
args = parser.parse_args()
71+
refresh_get_pip(args.version)
5672

5773

5874
if __name__ == "__main__":
59-
main(GET_PIP_DEST)
75+
main()

0 commit comments

Comments
 (0)