Skip to content

Instantly share code, notes, and snippets.

@traversaro
Last active March 19, 2025 22:11
Show Gist options
  • Select an option

  • Save traversaro/9b7c340c4fee8a812142455023775e22 to your computer and use it in GitHub Desktop.

Select an option

Save traversaro/9b7c340c4fee8a812142455023775e22 to your computer and use it in GitHub Desktop.
Packages in conda-forge osx-arm64 built with rattler-build 0.38.0
#!/usr/bin/env python3
import requests
import datetime
import io
import conda_package_handling.api as cpha
import tempfile
import os
import subprocess
import json
import tempfile
import shutil
import requests
import zipfile
import io
import yaml
import tarfile
import zstandard as zstd
def get_rattler_build_version(url):
# Download the .conda package
response = requests.get(url)
response.raise_for_status()
# Open the downloaded content as a zip file
with zipfile.ZipFile(io.BytesIO(response.content)) as conda_zip:
# Locate the inner file that starts with "info-" and ends with ".tar.zst"
info_file_name = next((name for name in conda_zip.namelist()
if name.startswith("info-") and name.endswith(".tar.zst")), None)
if not info_file_name:
print("Could not find the info tar.zst file in the .conda package.")
return None
# Read the inner tar.zst file bytes
inner_bytes = conda_zip.read(info_file_name)
# Decompress the zstandard compressed tar archive
dctx = zstd.ZstdDecompressor()
decompressed_bytes = dctx.decompress(inner_bytes)
# Open the decompressed bytes as a tar archive
with tarfile.open(fileobj=io.BytesIO(decompressed_bytes)) as tar:
# Define the path to the rendered_recipe.yaml file inside the tar archive
yaml_path = "info/recipe/rendered_recipe.yaml"
try:
yaml_member = tar.getmember(yaml_path)
except KeyError:
print("rendered_recipe.yaml not found inside the info tar archive.")
return None
# Extract and read the YAML file
f = tar.extractfile(yaml_member)
if f is None:
print("Failed to extract the YAML file.")
return None
yaml_content = f.read()
recipe = yaml.safe_load(yaml_content)
# Extract rattler-build info from the recipe data
system_tools = recipe.get("system_tools", {})
rattler_version = system_tools.get("rattler-build")
if rattler_version:
print(f"Package built by rattler-build, version: {rattler_version}")
else:
print("Package was not built by rattler-build.")
return rattler_version
def fetch_repodata(url):
"""Download and return the JSON repodata from the given URL."""
response = requests.get(url)
response.raise_for_status()
return response.json()
def extract_conda_package(conda_file_path, extract_dir):
"""Extract a .conda package using the cph command-line tool."""
try:
subprocess.run(['cph', 'extract', conda_file_path, '--dest', extract_dir], check=True)
except subprocess.CalledProcessError as e:
print(f"Error extracting {conda_file_path}: {e}")
return None
return extract_dir
def read_index_json(extracted_dir):
"""Read and return the contents of info/index.json from the extracted package."""
index_json_path = os.path.join(extracted_dir, 'info', 'index.json')
try:
with open(index_json_path, 'r') as f:
return json.load(f)
except Exception as e:
print(f"Error reading {index_json_path}: {e}")
return None
def filter_packages(repodata, start_date, end_date, target_rattler_version):
"""Filter package entries by timestamp and rattler-build version."""
filtered = []
base_url = "https://conda.anaconda.org/conda-forge/osx-arm64/"
# repodata['packages'] is a dict of package filename -> package metadata
for section in ("packages", "packages.conda"):
for pkg_filename, pkg_data in repodata.get(section, {}).items():
ts = pkg_data.get("timestamp")
if not ts:
continue
# repodata timestamp is typically in milliseconds since epoch
pkg_date = datetime.datetime.fromtimestamp(ts / 1000)
# Filter by date range (March 2025)
if start_date <= pkg_date <= end_date:
print(f"{pkg_filename} was built on {pkg_date}")
pkg_url = base_url + pkg_filename
if (pkg_filename.endswith(".conda") and
get_rattler_build_version(pkg_url) == target_rattler_version):
filtered.append(pkg_filename)
return filtered
def main():
# URL to conda-forge repodata for osx-arm64 (adjust if using a label/channel)
repodata_url = "https://conda.anaconda.org/conda-forge/osx-arm64/repodata.json"
# Define date range for March 2025
start_date = datetime.datetime(2025, 3, 4)
end_date = datetime.datetime(2025, 3, 12, 23, 59, 59)
target_rattler_version = "0.38.0"
try:
repodata = fetch_repodata(repodata_url)
except Exception as e:
print("Error fetching repodata:", e)
return
packages = filter_packages(repodata, start_date, end_date, target_rattler_version)
print("Packages matching criteria:")
print(packages)
if __name__ == "__main__":
main()
['amrex-25.3-mpi_mpich_h77a6ea5_0.conda', 'amrex-25.3-mpi_mpich_hc112c7c_0.conda', 'amrex-25.3-mpi_openmpi_h049e466_0.conda', 'amrex-25.3-mpi_openmpi_h64915e6_0.conda', 'amrex-25.3-nompi_h9df74e3_100.conda', 'amrex-25.3-nompi_hc27d7cd_100.conda', 'aws-c-event-stream-0.5.3-hf3b3161_0.conda', 'aws-c-event-stream-0.5.4-hf3b3161_0.conda', 'aws-c-http-0.9.3-hc7e6e09_0.conda', 'aws-c-http-0.9.4-hc7e6e09_0.conda', 'aws-c-mqtt-0.12.2-h1883759_0.conda', 'aws-c-s3-0.7.12-he341b12_0.conda', 'aws-crt-cpp-0.31.0-hbb63a78_0.conda', 'awscrt-0.23.10-py310h2fbff3f_1.conda', 'awscrt-0.23.10-py311h8e833b8_1.conda', 'awscrt-0.23.10-py312h454e317_1.conda', 'awscrt-0.23.10-py313h4e1e23c_1.conda', 'awscrt-0.23.10-py39hdad6790_1.conda', 'awscrt-0.24.1-py310h2fbff3f_0.conda', 'awscrt-0.24.1-py311h8e833b8_0.conda', 'awscrt-0.24.1-py312h454e317_0.conda', 'awscrt-0.24.1-py313h4e1e23c_0.conda', 'awscrt-0.24.1-py39hdad6790_0.conda', 'boost-histogram-1.5.1-py310h321d730_1.conda', 'boost-histogram-1.5.1-py311h2534089_1.conda', 'boost-histogram-1.5.1-py312hba21e8a_1.conda', 'boost-histogram-1.5.1-py313hf4d12cc_1.conda', 'boost-histogram-1.5.1-py39h0faa675_1.conda', 'ccache-4.11-h5a0df06_0.conda', 'cms-combine-10.1.0-py310habb7989_1.conda', 'cms-combine-10.1.0-py310hf87c6c6_1.conda', 'cms-combine-10.1.0-py311h002854b_1.conda', 'cms-combine-10.1.0-py311h3edeed3_1.conda', 'cms-combine-10.1.0-py312h356712b_1.conda', 'cms-combine-10.1.0-py312hf68060f_1.conda', 'cms-combine-10.1.0-py39h71ca3d0_1.conda', 'cms-combine-10.1.0-py39hf8f5fa0_1.conda', 'evcxr-0.19.0-h8dba533_0.conda', 'fastfetch-2.38.0-hfd2a157_1.conda', 'git-cliff-2.8.0-h195ea4e_1.conda', 'git-cliff-2.8.0-h195ea4e_10.conda', 'gitlab-ci-ls-1.0.3-h5613be0_0.conda', 'gvproxy-0.8.4-h48c0fde_0.conda', 'gz-cmake4-4.1.1-h1f76e1c_1.conda', 'gz-math8-8.1.1-h504f5e0_1.conda', 'gz-math8-python-8.1.1-py310hcccc800_1.conda', 'gz-math8-python-8.1.1-py311h1f39ce9_1.conda', 'gz-math8-python-8.1.1-py312ha17915d_1.conda', 'gz-math8-python-8.1.1-py313he9d2158_1.conda', 'gz-math8-python-8.1.1-py39hd3b2708_1.conda', 'harper-0.25.0-hd4c9240_0.conda', 'harper-0.25.1-hd4c9240_0.conda', 'jj-0.27.0-h7e3ab09_0.conda', 'libamd-3.3.3-ss7101_h9ae0bfd.conda', 'libbtf-2.3.2-ss7101_h43daff1.conda', 'libcamd-3.3.3-ss7101_h43daff1.conda', 'libccolamd-3.3.4-ss7101_h43daff1.conda', 'libcholmod-5.3.1-ss7101_h1689c6d.conda', 'libcolamd-3.3.4-ss7101_h43daff1.conda', 'libcxsparse-4.4.1-ss7101_hbb8d750.conda', 'libgz-cmake4-4.1.1-ha1acc90_1.conda', 'libgz-math8-8.1.1-ha1acc90_1.conda', 'libklu-2.3.5-ss7101_hb1ebd8a.conda', 'libldl-3.3.2-ss7101_h43daff1.conda', 'libparu-1.0.0-ss7101_ha5fd277.conda', 'librbio-4.3.4-ss7101_h43daff1.conda', 'libspex-3.2.3-ss7101_h95f1bed.conda', 'libspqr-4.3.4-ss7101_hb47b22a.conda', 'libsuitesparseconfig-7.10.1-ss7101_h4a8fc20.conda', 'libumfpack-6.3.5-ss7101_hd04a58b.conda', 'marimo-0.11.16-py310hf15e2f2_0.conda', 'marimo-0.11.16-py311hbad07cd_0.conda', 'marimo-0.11.16-py312hc85ae00_0.conda', 'marimo-0.11.16-py313h9a4da87_0.conda', 'marimo-0.11.16-py39h6e92e67_0.conda', 'marimo-0.11.17-py310hf15e2f2_0.conda', 'marimo-0.11.17-py311hbad07cd_0.conda', 'marimo-0.11.17-py312hc85ae00_0.conda', 'marimo-0.11.17-py313h9a4da87_0.conda', 'marimo-0.11.17-py39h6e92e67_0.conda', 'marimo-0.11.18-py310hf15e2f2_0.conda', 'marimo-0.11.18-py311hbad07cd_0.conda', 'marimo-0.11.18-py312hc85ae00_0.conda', 'marimo-0.11.18-py313h9a4da87_0.conda', 'marimo-0.11.18-py39h6e92e67_0.conda', 'mdbook-0.4.46-h8dba533_0.conda', 'mdbook-0.4.47-h8dba533_0.conda', 'mdsf-0.7.0-h8dba533_0.conda', 'mdsf-0.8.0-h8dba533_0.conda', 'mdsf-0.8.1-h8dba533_0.conda', 'nativefiledialog-extended-1.2.1-h4167660_1.conda', 'newrelic-10.7.0-py310h8f1641c_1.conda', 'newrelic-10.7.0-py311hd460543_1.conda', 'newrelic-10.7.0-py312hd525726_1.conda', 'newrelic-10.7.0-py313h4019975_1.conda', 'newrelic-10.7.0-py39h6cd770d_1.conda', 'newrelic-10.7.0-py39h9e83b10_0.conda', 'nh3-0.2.21-py39h52c9f89_1.conda', 'openjph-0.21.2-h28d5c5b_0.conda', 'oxlint-0.15.14-h8dba533_0.conda', 'petsc4py-3.22.4-np20py310h0b04470_0.conda', 'petsc4py-3.22.4-np20py310h47c35b5_0.conda', 'petsc4py-3.22.4-np20py310hcc7a3e2_0.conda', 'petsc4py-3.22.4-np20py310hdef029b_0.conda', 'petsc4py-3.22.4-np20py311h205d8ee_0.conda', 'petsc4py-3.22.4-np20py311h982014a_0.conda', 'petsc4py-3.22.4-np20py311hc7b3bc5_0.conda', 'petsc4py-3.22.4-np20py311hee98211_0.conda', 'petsc4py-3.22.4-np20py312h084981a_0.conda', 'petsc4py-3.22.4-np20py312h4d474df_0.conda', 'petsc4py-3.22.4-np20py312h97bb1b2_0.conda', 'petsc4py-3.22.4-np20py312hedd763a_0.conda', 'petsc4py-3.22.4-np20py39h66650ce_0.conda', 'petsc4py-3.22.4-np20py39h6faf10e_0.conda', 'petsc4py-3.22.4-np20py39hb49342b_0.conda', 'petsc4py-3.22.4-np20py39hb981c98_0.conda', 'petsc4py-3.22.4-np2py313h03d4cd5_0.conda', 'petsc4py-3.22.4-np2py313h08eee09_0.conda', 'petsc4py-3.22.4-np2py313h2f7c7fa_0.conda', 'petsc4py-3.22.4-np2py313h58f2e10_0.conda', 'pineappl-0.8.7-py310h31b3829_1.conda', 'pineappl-0.8.7-py310h31b3829_2.conda', 'pineappl-0.8.7-py310h57a9e18_2.conda', 'pineappl-0.8.7-py310h57a9e18_3.conda', 'pineappl-0.8.7-py311h45595e4_2.conda', 'pineappl-0.8.7-py311h45595e4_3.conda', 'pineappl-0.8.7-py311hc9d6b66_1.conda', 'pineappl-0.8.7-py311hc9d6b66_2.conda', 'pineappl-0.8.7-py312h017cb5e_2.conda', 'pineappl-0.8.7-py312h017cb5e_3.conda', 'pineappl-0.8.7-py312hd60eec9_1.conda', 'pineappl-0.8.7-py312hd60eec9_2.conda', 'pineappl-0.8.7-py313hb5fa170_2.conda', 'pineappl-0.8.7-py313hbd37bf2_2.conda', 'pineappl-0.8.7-py313hbd37bf2_3.conda', 'pineappl-0.8.7-py39hbdf163d_2.conda', 'pineappl-0.8.7-py39hbdf163d_3.conda', 'pineappl-0.8.7-py39he565553_1.conda', 'pineappl-0.8.7-py39he565553_2.conda', 'plantuml-1.2025.2-h13a936c_0.conda', 'pueue-4.0.0-h8dba533_0.conda', 'pyamrex-25.3-mpi_mpich_py310h307ec3e_0.conda', 'pyamrex-25.3-mpi_mpich_py310h98b1457_0.conda', 'pyamrex-25.3-mpi_mpich_py311hcab16da_0.conda', 'pyamrex-25.3-mpi_mpich_py311he6f28d7_0.conda', 'pyamrex-25.3-mpi_mpich_py312h2e81676_0.conda', 'pyamrex-25.3-mpi_mpich_py312h5334891_0.conda', 'pyamrex-25.3-mpi_mpich_py313h7dee059_0.conda', 'pyamrex-25.3-mpi_mpich_py313hc861fed_0.conda', 'pyamrex-25.3-mpi_mpich_py39h2d8770b_0.conda', 'pyamrex-25.3-mpi_mpich_py39he422e0e_0.conda', 'pyamrex-25.3-mpi_openmpi_py310h0822119_0.conda', 'pyamrex-25.3-mpi_openmpi_py310hdf6f53b_0.conda', 'pyamrex-25.3-mpi_openmpi_py311h28fc5f3_0.conda', 'pyamrex-25.3-mpi_openmpi_py311h9030587_0.conda', 'pyamrex-25.3-mpi_openmpi_py312ha1066aa_0.conda', 'pyamrex-25.3-mpi_openmpi_py312ha33993f_0.conda', 'pyamrex-25.3-mpi_openmpi_py313h06c8920_0.conda', 'pyamrex-25.3-mpi_openmpi_py313h92f0bd3_0.conda', 'pyamrex-25.3-mpi_openmpi_py39h353b8cc_0.conda', 'pyamrex-25.3-mpi_openmpi_py39h78aa263_0.conda', 'pyamrex-25.3-nompi_py310h12dad16_100.conda', 'pyamrex-25.3-nompi_py310h5448558_100.conda', 'pyamrex-25.3-nompi_py311h0985f7d_100.conda', 'pyamrex-25.3-nompi_py311h8bf2d73_100.conda', 'pyamrex-25.3-nompi_py312h92609e4_100.conda', 'pyamrex-25.3-nompi_py312hcea527c_100.conda', 'pyamrex-25.3-nompi_py313h39f606d_100.conda', 'pyamrex-25.3-nompi_py313h720ba72_100.conda', 'pyamrex-25.3-nompi_py39h3cf8286_100.conda', 'pyamrex-25.3-nompi_py39h3ddfeb6_100.conda', 'pygsti-0.9.13-np122py310h806266b_1.conda', 'pygsti-0.9.13-np122py39h886fec7_1.conda', 'pygsti-0.9.13-np123py311hd946c57_1.conda', 'pygsti-0.9.13-np126py312h04c2794_1.conda', 'pygsti-0.9.13-np20py310h51fdda9_2.conda', 'pygsti-0.9.13-np20py310h51fdda9_3.conda', 'pygsti-0.9.13-np20py311h7e49079_2.conda', 'pygsti-0.9.13-np20py311h7e49079_3.conda', 'pygsti-0.9.13-np20py312h7ca56ae_2.conda', 'pygsti-0.9.13-np20py312h7ca56ae_3.conda', 'pygsti-0.9.13-np20py39h5ebe062_2.conda', 'pygsti-0.9.13-np20py39h5ebe062_3.conda', 'pygsti-0.9.13-np2py313he581748_3.conda', 'rattler-build-0.39.0-h8dba533_0.conda', 'rattler-index-0.22.0-h94be654_0.conda', 'skim-0.16.1-h8dba533_0.conda', 'suitesparse-7.10.1-ss7101_hc9d5dbc.conda', 'suitesparse-mongoose-3.3.4-ss7101_hbb2d708.conda', 'superfile-1.2.0.0-h87715bd_0.conda', 'tach-0.27.2-py39h52c9f89_1.conda', 'tach-0.27.3-py39h52c9f89_0.conda', 'tach-0.28.0-py39h52c9f89_0.conda', 'television-0.10.7-h8dba533_0.conda', 'tinyxml2-10.0.0-ha1acc90_1.conda', 'tinyxml2-10.1.0-ha1acc90_0.conda', 'tinyxml2-10.1.0-ha1acc90_1.conda', 'urdfdom-4.0.1-h1874252_1.conda', 'warpx-25.3-np20py310h4eefa84_0.conda', 'warpx-25.3-np20py311h7971139_0.conda', 'warpx-25.3-np20py312h777c520_0.conda', 'warpx-25.3-np20py39h3bb2b8a_0.conda', 'warpx-25.3-np2py313h0af3f1c_0.conda', 'xgrammar-0.1.15-py310ha4d6d2c_0.conda', 'xgrammar-0.1.15-py311h4be82bb_0.conda', 'xgrammar-0.1.15-py312hd6dbf26_0.conda', 'xgrammar-0.1.15-py313h3d03e78_0.conda', 'xgrammar-0.1.15-py39h332b8fa_0.conda']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment