diff --git a/ports/py-pydantic-core/portfile.cmake b/ports/py-pydantic-core/portfile.cmake index 669b2d5e..66f2d52e 100644 --- a/ports/py-pydantic-core/portfile.cmake +++ b/ports/py-pydantic-core/portfile.cmake @@ -1,8 +1,9 @@ +# PINNED_BY pydantic vcpkg_from_pythonhosted( OUT_SOURCE_PATH SOURCE_PATH PACKAGE_NAME pydantic_core VERSION ${VERSION} - SHA512 8ae66cc48b6d8912b70061f27dbbfbe2b8327628ce6c24c143197900921974a5f2fe8d163c8608526b6befe0332887eb2111313e72aaccb4eea04c230260c8ce + SHA512 7af13f280d74ab0ded8e9299820930b0257502017f6a688d7d598e72351e127e178db11aeab987decaf95ca8619e151f244392ad9638ea184625728dcbb7cfff ) if(VCPKG_TARGET_IS_WINDOWS) diff --git a/ports/py-pydantic-core/vcpkg.json b/ports/py-pydantic-core/vcpkg.json index 69c7bc39..29b969f5 100644 --- a/ports/py-pydantic-core/vcpkg.json +++ b/ports/py-pydantic-core/vcpkg.json @@ -1,6 +1,6 @@ { "name": "py-pydantic-core", - "version": "2.49.0", + "version": "2.46.5", "description": "Data validation using Python type hints.", "homepage": "https://github.com/pydantic/pydantic", "dependencies": [ diff --git a/ports/py-pydantic/portfile.cmake b/ports/py-pydantic/portfile.cmake index 5c36acca..784455da 100644 --- a/ports/py-pydantic/portfile.cmake +++ b/ports/py-pydantic/portfile.cmake @@ -9,5 +9,6 @@ vcpkg_from_pythonhosted( vcpkg_python_build_and_install_wheel(SOURCE_PATH "${SOURCE_PATH}") vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") +vcpkg_python_test_import(MODULE "pydantic") set(VCPKG_POLICY_EMPTY_INCLUDE_FOLDER enabled) diff --git a/ports/py-pydantic/vcpkg.json b/ports/py-pydantic/vcpkg.json index b83749ba..1fc07f43 100644 --- a/ports/py-pydantic/vcpkg.json +++ b/ports/py-pydantic/vcpkg.json @@ -1,6 +1,7 @@ { "name": "py-pydantic", "version": "2.13.5", + "port-version": 1, "description": "Data validation using Python type hints.", "homepage": "https://github.com/pydantic/pydantic", "dependencies": [ diff --git a/scripts/update-ports.py b/scripts/update-ports.py index d06f2ee5..19fc4498 100644 --- a/scripts/update-ports.py +++ b/scripts/update-ports.py @@ -18,6 +18,42 @@ def calculate_sha512(file_path): return sha512.hexdigest() +def normalize_package_name(name): + """Normalize a PyPI package name (PEP 503).""" + return re.sub(r"[-_.]+", "-", name).lower() + + +def get_pinned_version(pinning_package, package_name): + """Return the exact version of package_name required by the latest release of pinning_package. + + Some packages require a companion package at an exact version (pydantic + requires pydantic-core==X), while the companion may publish newer releases + meant for pre-releases of the pinning package. The companion port declares + the PyPI package pinning it, so it is not updated past that pin: + + # PINNED_BY pydantic + + Returns None if the pinning package cannot be queried or has no such pin. + """ + response = requests.get(f"https://pypi.org/pypi/{pinning_package}/json") + if response.status_code != 200: + return None + + requires_dist = response.json().get("info", {}).get("requires_dist") or [] + for requirement in requires_dist: + requirement, _, marker = requirement.partition(";") + # Optional dependencies do not constrain the installed version + if "extra" in marker: + continue + match = re.fullmatch( + r"\s*([A-Za-z0-9._-]+)\s*\(?\s*==\s*([^\s,()]+)\s*\)?\s*", requirement + ) + if match and normalize_package_name(match.group(1)) == normalize_package_name(package_name): + return match.group(2) + + return None + + def update_pypi_ports(): updated = [] failed = [] @@ -65,6 +101,20 @@ def update_pypi_ports(): # Query the PyPI API for the latest package info pypi_url = f"https://pypi.org/pypi/{package_name}/json" + + # A pinned port follows the version required by the + # package pinning it rather than its latest release + pinned_by_match = re.search(r"#\s*PINNED_BY\s+(\S+)", portfile_content) + if pinned_by_match: + pinned_by = pinned_by_match.group(1) + pinned_version = get_pinned_version(pinned_by, package_name) + if not pinned_version: + print(f" Failed to find the {package_name} version pinned by {pinned_by}") + failed.append(f"{dir_name} (no pin found in {pinned_by})") + continue + print(f" Using version {pinned_version} pinned by {pinned_by}") + pypi_url = f"https://pypi.org/pypi/{package_name}/{pinned_version}/json" + response = requests.get(pypi_url) if response.status_code != 200: diff --git a/versions/baseline.json b/versions/baseline.json index 846fc473..13486a20 100644 --- a/versions/baseline.json +++ b/versions/baseline.json @@ -318,10 +318,10 @@ }, "py-pydantic": { "baseline": "2.13.5", - "port-version": 0 + "port-version": 1 }, "py-pydantic-core": { - "baseline": "2.49.0", + "baseline": "2.46.5", "port-version": 0 }, "py-pyogrio": { diff --git a/versions/p-/py-pydantic-core.json b/versions/p-/py-pydantic-core.json index e124a582..c21dcb9d 100644 --- a/versions/p-/py-pydantic-core.json +++ b/versions/p-/py-pydantic-core.json @@ -1,5 +1,10 @@ { "versions": [ + { + "git-tree": "9052f9650d1d73a90b25a0ece71f00690abb496e", + "version": "2.46.5", + "port-version": 0 + }, { "git-tree": "f3d9044b37de369ab7c111b115083e737f1deab6", "version": "2.49.0", diff --git a/versions/p-/py-pydantic.json b/versions/p-/py-pydantic.json index 1c7dec04..6f892a17 100644 --- a/versions/p-/py-pydantic.json +++ b/versions/p-/py-pydantic.json @@ -1,5 +1,10 @@ { "versions": [ + { + "git-tree": "90b1e24a3eb05709c6715f02abe9756e573599b8", + "version": "2.13.5", + "port-version": 1 + }, { "git-tree": "280d2e3564d40f5bcbcecec53cf7f4c58713e8ff", "version": "2.13.5",