Skip to content

Commit eb3c82c

Browse files
committed
Constants refactor
1 parent 147ab25 commit eb3c82c

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

ddev/src/ddev/cli/meta/scripts/update_python.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@
1717
from ddev.cli.application import Application
1818
from ddev.validation.tracker import ValidationTracker
1919

20+
# Python.org URLs
21+
PYTHON_FTP_URL = "https://www.python.org/ftp/python/"
22+
PYTHON_MACOS_PKG_URL_TEMPLATE = "https://www.python.org/ftp/python/{version}/python-{version}-macos11.pkg"
23+
PYTHON_SBOM_LINUX_URL_TEMPLATE = "https://www.python.org/ftp/python/{version}/Python-{version}.tgz.spdx.json"
24+
PYTHON_SBOM_WINDOWS_URL_TEMPLATE = "https://www.python.org/ftp/python/{version}/python-{version}-amd64.exe.spdx.json"
25+
26+
# Regex patterns for Dockerfile updates
27+
# Linux: ENV PYTHON3_VERSION=3.13.7 (no quotes, matches version at end of line)
28+
LINUX_VERSION_PATTERN = re.compile(r'(ENV PYTHON3_VERSION=)(\d+\.\d+\.\d+)$', re.MULTILINE)
29+
# Windows: ENV PYTHON_VERSION="3.13.7" (with quotes)
30+
WINDOWS_VERSION_PATTERN = re.compile(r'(ENV PYTHON_VERSION=")(\d+\.\d+\.\d+)(")', re.MULTILINE)
31+
32+
# SHA256 patterns must match the Python-specific ones:
33+
# Linux: SHA256 that comes after VERSION="${PYTHON3_VERSION}"
34+
LINUX_SHA_PATTERN = re.compile(r'VERSION="\$\{PYTHON3_VERSION\}"[^\n]*\n[^\n]*SHA256="([0-9a-f]+)"', re.MULTILINE)
35+
# Windows: -Hash in the same RUN block with python-$Env:PYTHON_VERSION-amd64.exe
36+
WINDOWS_SHA_PATTERN = re.compile(
37+
r'python-\$Env:PYTHON_VERSION-amd64\.exe[^\n]*\n[^\n]*-Hash\s+\'([0-9a-f]+)\'', re.MULTILINE
38+
)
39+
2040

2141
@click.command('update-python-version', short_help='Upgrade the Python version used in the repository.')
2242
@click.pass_obj
@@ -125,19 +145,6 @@ def update_dockerfiles_python_version(
125145
tracker.error(('Dockerfiles',), message=f'Missing SHA256 hash entry: {error}')
126146
return
127147

128-
# Linux: ENV PYTHON3_VERSION=3.13.7 (no quotes, matches version at end of line)
129-
# Windows: ENV PYTHON_VERSION="3.13.7" (with quotes)
130-
linux_version_pattern = re.compile(r'(ENV PYTHON3_VERSION=)(\d+\.\d+\.\d+)$', re.MULTILINE)
131-
windows_version_pattern = re.compile(r'(ENV PYTHON_VERSION=")(\d+\.\d+\.\d+)(")', re.MULTILINE)
132-
133-
# SHA256 patterns must match the Python-specific ones:
134-
# Linux: SHA256 that comes after VERSION="${PYTHON3_VERSION}"
135-
# Windows: -Hash in the same RUN block with python-$Env:PYTHON_VERSION-amd64.exe
136-
linux_sha_pattern = re.compile(r'VERSION="\$\{PYTHON3_VERSION\}"[^\n]*\n[^\n]*SHA256="([0-9a-f]+)"', re.MULTILINE)
137-
windows_sha_pattern = re.compile(
138-
r'python-\$Env:PYTHON_VERSION-amd64\.exe[^\n]*\n[^\n]*-Hash\s+\'([0-9a-f]+)\'', re.MULTILINE
139-
)
140-
141148
for dockerfile in dockerfiles:
142149
if not dockerfile.exists():
143150
tracker.error((dockerfile.name,), message=f'File not found: {dockerfile}')
@@ -150,8 +157,8 @@ def update_dockerfiles_python_version(
150157
continue
151158

152159
is_windows = 'windows-x86_64' in dockerfile.parts
153-
version_pattern = windows_version_pattern if is_windows else linux_version_pattern
154-
sha_pattern = windows_sha_pattern if is_windows else linux_sha_pattern
160+
version_pattern = WINDOWS_VERSION_PATTERN if is_windows else LINUX_VERSION_PATTERN
161+
sha_pattern = WINDOWS_SHA_PATTERN if is_windows else LINUX_SHA_PATTERN
155162
target_sha = windows_sha if is_windows else linux_sha
156163

157164
def replace_version(match: re.Match[str], _is_windows=is_windows) -> str:
@@ -211,7 +218,7 @@ def update_macos_python_version(app: Application, new_version: str, tracker: Val
211218
tracker.error(('macOS workflow',), message='Could not find PYTHON3_DOWNLOAD_URL')
212219
return
213220

214-
new_url = f'https://www.python.org/ftp/python/{new_version}/python-{new_version}-macos11.pkg'
221+
new_url = PYTHON_MACOS_PKG_URL_TEMPLATE.format(version=new_version)
215222
indent = target_line[: target_line.index('PYTHON3_DOWNLOAD_URL')]
216223
new_line = f'{indent}PYTHON3_DOWNLOAD_URL: "{new_url}"'
217224

@@ -270,11 +277,9 @@ def get_latest_python_version(app: Application, major_minor: str) -> str | None:
270277
Returns:
271278
Latest version string (e.g., "3.13.1") or None if not found
272279
"""
273-
url = "https://www.python.org/ftp/python/"
274-
275280
try:
276281
# Explicitly verify SSL/TLS certificate
277-
response = requests.get(url, timeout=30, verify=True)
282+
response = requests.get(PYTHON_FTP_URL, timeout=30, verify=True)
278283
response.raise_for_status()
279284
except requests.RequestException as e:
280285
app.display_error(f"Error fetching Python versions: {e}")
@@ -328,18 +333,13 @@ def get_python_sha256_hashes(app: Application, version: str) -> dict[str, str]:
328333
if not validate_version_string(version):
329334
raise ValueError(f"Invalid version format: {version}")
330335

331-
# Steps:
332-
# 1. Construct SBOM URLs for the files we need:
333-
# - Linux source tarball:
334-
# https://www.python.org/ftp/python/{version}/Python-{version}.tgz.spdx.json
335-
# - Windows AMD64 installer:
336-
# https://www.python.org/ftp/python/{version}/python-{version}-amd64.exe.spdx.json
337-
SBOM_URLS = [
338-
f"https://www.python.org/ftp/python/{version}/Python-{version}.tgz.spdx.json",
339-
f"https://www.python.org/ftp/python/{version}/python-{version}-amd64.exe.spdx.json",
336+
# Construct SBOM URLs for the files we need
337+
sbom_urls = [
338+
PYTHON_SBOM_LINUX_URL_TEMPLATE.format(version=version),
339+
PYTHON_SBOM_WINDOWS_URL_TEMPLATE.format(version=version),
340340
]
341341

342-
# 2. Download and parse each SBOM JSON file
342+
# Download and parse each SBOM JSON file
343343
async def get_sbom_data(client, url):
344344
try:
345345
# Explicitly verify SSL/TLS certificates
@@ -362,7 +362,7 @@ async def fetch_sbom_data(urls):
362362
async with httpx.AsyncClient(verify=True) as client:
363363
return await asyncio.gather(*(get_sbom_data(client, url) for url in urls))
364364

365-
sbom_packages = asyncio.run(fetch_sbom_data(SBOM_URLS))
365+
sbom_packages = asyncio.run(fetch_sbom_data(sbom_urls))
366366

367367
# Find the CPython package in the SBOM packages
368368
linux_cpython_package = next((package for package in sbom_packages[0] if package.get('name') == "CPython"), None)

0 commit comments

Comments
 (0)