Avoid unnecessary list conversions; use generators where possible
return list(response.json()["releases"].keys())
1"""Get minimum versions of dependencies from a pyproject.toml file."""23import sys4from collections import defaultdict56if sys.version_info >= (3, 11):7 import tomllib8else:9 # For Python 3.10 and below, which doesnt have stdlib tomllib10 import tomli as tomllib1112import re13from typing import List1415import requests16from packaging.requirements import Requirement17from packaging.specifiers import SpecifierSet18from packaging.version import Version, parse1920MIN_VERSION_LIBS = [21 "langchain-core",22 "langchain",23 "langchain-text-splitters",24 "numpy",25 "SQLAlchemy",26]2728# some libs only get checked on release because of simultaneous changes in29# multiple libs30SKIP_IF_PULL_REQUEST = [31 "langchain-core",32 "langchain-text-splitters",33 "langchain",34]353637def get_pypi_versions(package_name: str) -> List[str]:38 """Fetch all available versions for a package from PyPI.3940 Args:41 package_name: Name of the package4243 Returns:44 List of all available versions4546 Raises:47 requests.exceptions.RequestException: If PyPI API request fails48 KeyError: If package not found or response format unexpected49 """50 pypi_url = f"https://pypi.org/pypi/{package_name}/json"51 response = requests.get(pypi_url, timeout=10.0)52 response.raise_for_status()53 return list(response.json()["releases"].keys())545556def get_minimum_version(package_name: str, spec_string: str) -> str | None:57 """Find the minimum published version that satisfies the given constraints.5859 Args:60 package_name: Name of the package61 spec_string: Version specification string (e.g., ">=0.2.43,<0.4.0,!=0.3.0")6263 Returns:64 Minimum compatible version or None if no compatible version found65 """66 # Rewrite occurrences of ^0.0.z to 0.0.z (can be anywhere in constraint string)67 spec_string = re.sub(r"\^0\.0\.(\d+)", r"0.0.\1", spec_string)68 # Rewrite occurrences of ^0.y.z to >=0.y.z,<0.y+1 (can be anywhere in constraint string)69 for y in range(1, 10):70 spec_string = re.sub(71 rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y + 1}", spec_string72 )73 # Rewrite occurrences of ^x.y.z to >=x.y.z,<x+1.0.0 (can be anywhere in constraint string)74 for x in range(1, 10):75 spec_string = re.sub(76 rf"\^{x}\.(\d+)\.(\d+)", rf">={x}.\1.\2,<{x + 1}", spec_string77 )7879 spec_set = SpecifierSet(spec_string)80 all_versions = get_pypi_versions(package_name)8182 valid_versions = []83 for version_str in all_versions:84 try:85 version = parse(version_str)86 if spec_set.contains(version):87 valid_versions.append(version)88 except ValueError:89 continue9091 return str(min(valid_versions)) if valid_versions else None929394def _check_python_version_from_requirement(95 requirement: Requirement, python_version: str96) -> bool:97 if not requirement.marker:98 return True99 else:100 marker_str = str(requirement.marker)101 if "python_version" in marker_str or "python_full_version" in marker_str:102 python_version_str = "".join(103 char104 for char in marker_str105 if char.isdigit() or char in (".", "<", ">", "=", ",")106 )107 return check_python_version(python_version, python_version_str)108 return True109110111def get_min_version_from_toml(112 toml_path: str,113 versions_for: str,114 python_version: str,115 *,116 include: list | None = None,117):118 # Parse the TOML file119 with open(toml_path, "rb") as file:120 toml_data = tomllib.load(file)121122 dependencies = defaultdict(list)123 for dep in toml_data["project"]["dependencies"]:124 requirement = Requirement(dep)125 dependencies[requirement.name].append(requirement)126127 # Initialize a dictionary to store the minimum versions128 min_versions = {}129130 # Iterate over the libs in MIN_VERSION_LIBS131 for lib in set(MIN_VERSION_LIBS + (include or [])):132 if versions_for == "pull_request" and lib in SKIP_IF_PULL_REQUEST:133 # some libs only get checked on release because of simultaneous134 # changes in multiple libs135 continue136 # Check if the lib is present in the dependencies137 if lib in dependencies:138 if include and lib not in include:139 continue140 requirements = dependencies[lib]141 for requirement in requirements:142 if _check_python_version_from_requirement(requirement, python_version):143 version_string = str(requirement.specifier)144 break145146 # Use parse_version to get the minimum supported version from version_string147 min_version = get_minimum_version(lib, version_string)148149 # Store the minimum version in the min_versions dictionary150 min_versions[lib] = min_version151152 return min_versions153154155def check_python_version(version_string, constraint_string):156 """Check if the given Python version matches the given constraints.157158 Args:159 version_string: A string representing the Python version (e.g. "3.8.5").160 constraint_string: A string representing the package's Python version161 constraints (e.g. ">=3.6, <4.0").162163 Returns:164 True if the version matches the constraints165 """166167 # Rewrite occurrences of ^0.0.z to 0.0.z (can be anywhere in constraint string)168 constraint_string = re.sub(r"\^0\.0\.(\d+)", r"0.0.\1", constraint_string)169 # Rewrite occurrences of ^0.y.z to >=0.y.z,<0.y+1.0 (can be anywhere in constraint string)170 for y in range(1, 10):171 constraint_string = re.sub(172 rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y + 1}.0", constraint_string173 )174 # Rewrite occurrences of ^x.y.z to >=x.y.z,<x+1.0.0 (can be anywhere in constraint string)175 for x in range(1, 10):176 constraint_string = re.sub(177 rf"\^{x}\.0\.(\d+)", rf">={x}.0.\1,<{x + 1}.0.0", constraint_string178 )179180 try:181 version = Version(version_string)182 constraints = SpecifierSet(constraint_string)183 return version in constraints184 except Exception as e:185 print(f"Error: {e}")186 return False187188189if __name__ == "__main__":190 # Get the TOML file path from the command line argument191 toml_file = sys.argv[1]192 versions_for = sys.argv[2]193 python_version = sys.argv[3]194 assert versions_for in ["release", "pull_request"]195196 # Call the function to get the minimum versions197 min_versions = get_min_version_from_toml(toml_file, versions_for, python_version)198199 print(" ".join([f"{lib}=={version}" for lib, version in min_versions.items()]))
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.