diff --git a/.github/workflows/test_local.yaml b/.github/workflows/test_local.yaml index 8eab028..e907234 100644 --- a/.github/workflows/test_local.yaml +++ b/.github/workflows/test_local.yaml @@ -30,8 +30,12 @@ permissions: jobs: test: - name: "Test" - runs-on: ubuntu-latest + name: "${{ matrix.runner }}" + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + runner: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -43,6 +47,11 @@ jobs: with: pixi-version: v0.72.0 + - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 + if: runner.os == 'Linux' + - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + if: runner.os == 'Linux' + - name: Test run: | pixi run --locked test diff --git a/.rat-apache b/.rat-apache index b409631..c7b06f2 100644 --- a/.rat-apache +++ b/.rat-apache @@ -15,3 +15,5 @@ .github/workflows/dev_issues.yaml adbc_drivers_dev/templates/dev_issues.yaml adbc_drivers_dev/title_check.py +tests/make/rustdummy/Cargo.toml +tests/make/rustdummy/src/lib.rs diff --git a/.rat-excludes b/.rat-excludes index 6ffe940..d874049 100644 --- a/.rat-excludes +++ b/.rat-excludes @@ -16,3 +16,4 @@ go.sum pixi.lock schema/generate-schema.json +tests/make/rustdummy/Cargo.lock diff --git a/adbc_drivers_dev/generate.py b/adbc_drivers_dev/generate.py index e9eea55..b4fbc09 100644 --- a/adbc_drivers_dev/generate.py +++ b/adbc_drivers_dev/generate.py @@ -362,7 +362,7 @@ def lang_boolean(cls, value: typing.Any) -> typing.Any: } @pydantic.computed_field - def azure(self) -> int: + def azure(self) -> bool: return any( config.azure for lang in self.lang.values() diff --git a/adbc_drivers_dev/make.py b/adbc_drivers_dev/make.py index e33e174..e8e8444 100644 --- a/adbc_drivers_dev/make.py +++ b/adbc_drivers_dev/make.py @@ -24,11 +24,14 @@ import shlex import subprocess import sys +import tomllib from pathlib import Path import doit import packaging.version +from . import make_checks, make_config + HOST_PLATFORM_NAMES = { "Darwin": "macos", "Linux": "linux", @@ -60,7 +63,6 @@ DOIT_CONFIG = { "default_tasks": ["build"], } -SMUGGLE_VARS = {"CGO_CFLAGS", "CGO_LDFLAGS", "GOWORK", "PROTOC"} def to_bool(value: str | bool) -> bool: @@ -80,13 +82,6 @@ def is_verbose() -> bool: return to_bool(get_var("VERBOSE", "False")) -def append_flags(env: dict[str, str], var: str, flags: str) -> None: - if var in env: - env[var] += " " + flags - else: - env[var] = flags - - def normalize_arch(value: str) -> str: try: return ARCH_ALIASES[value.lower()] @@ -145,7 +140,18 @@ def check_output(*args, **kwargs) -> str: def info(*args, **kwargs): - print("!", *args, **kwargs, file=sys.stderr) + print("?", *args, **kwargs, file=sys.stderr) + + +def _find_repo_root(driver_root: Path) -> Path: + repo_root = driver_root + git_marker = repo_root / ".git" + while not (git_marker.is_dir() or git_marker.is_file()): + if repo_root.parent == repo_root: + raise ValueError(f"{driver_root} is not in a git repository") + repo_root = repo_root.parent + git_marker = repo_root / ".git" + return repo_root def detect_version( @@ -153,11 +159,7 @@ def detect_version( *, strict: bool = False, ) -> str: - repo_root = driver_root - while not (repo_root / ".git").is_dir(): - if repo_root.parent == repo_root: - raise ValueError(f"{driver_root} is not in a git repository") - repo_root = repo_root.parent + repo_root = _find_repo_root(driver_root) prefix = str(driver_root.relative_to(repo_root)) if prefix == ".": @@ -309,432 +311,38 @@ def should_use_docker() -> bool: return to_bool(get_var("CI", False)) and platform.system() == "Linux" -def docker_platform() -> str: - return f"{target_platform()}/{target_architecture()}" - - -def docker_env(repo_root: Path) -> dict[str, str]: - return { - "SOURCE_ROOT": str(repo_root), - "DOCKER_DEFAULT_PLATFORM": docker_platform(), - } - - -def maybe_build_docker( - *, - repo_root: Path, - driver_root: Path, - env: dict[str, str], - args: list[str], - container: str, -) -> None: - if not should_use_docker(): - check_call(args, cwd=driver_root, env=env) - return - - env = env.copy() - env["SOURCE_ROOT"] = str(repo_root) - env["ARCH"] = target_architecture() - env["DOCKER_DEFAULT_PLATFORM"] = docker_platform() - - volumes = get_var("ADDITIONAL_VOLUMES", "") - if volumes: - volumes = volumes.split(",") - - # Some env vars need to be explicitly propagated into Docker - smuggle_env = "" - for var in SMUGGLE_VARS: - if var in env: - smuggle_env += f'{var}="{shlex.quote(env[var])}" ' - elif var in os.environ: - smuggle_env += f'{var}="{shlex.quote(os.environ[var])}" ' - - command = [ - "docker", - "compose", - "run", - "--rm", - "--user", - str(os.getuid()), - ] - - for volume in volumes: - command.extend(["-v", volume]) - - command.extend( - [ - container, - "--", - "bash", - "-c", - f"cd /source/{driver_root.relative_to(repo_root)} && env {smuggle_env} {' '.join(shlex.quote(arg) for arg in args)}", - ] - ) - check_call(command, cwd=Path(__file__).parent, env=env) - - -def read_linux_symbols(binary: Path) -> list[str]: - return check_output( - [ - "nm", - "--demangle", - "--dynamic", - str(binary), - ] - ).splitlines() - - -def read_linux_symbols_in_docker(repo_root: Path, binary: Path) -> list[str]: - rel_binary = binary.resolve().relative_to(repo_root.resolve()) - return check_output( - [ - "docker", - "compose", - "run", - "--rm", - "manylinux", - "nm", - "--demangle", - "--dynamic", - f"/source/{rel_binary.as_posix()}", - ], - cwd=Path(__file__).parent, - env=docker_env(repo_root), - ).splitlines() - - -def build_go( - repo_root: Path, - driver_root: Path, - driver: str, - target: str, -) -> None: +def _load_build_context() -> tuple[ + make_config.MakeEnv, make_config.MakeConfig, make_config.MakePlan +]: strict = to_bool(get_var("RELEASE", "false")) + driver_root = Path(".").resolve().absolute() + repo_root = _find_repo_root(driver_root) version = detect_version(driver_root, strict=strict) - (repo_root / "build").mkdir(exist_ok=True) - target_name = target_platform() - # Embed the version in the library - prop = "github.com/adbc-drivers/driverbase-go/driverbase.infoDriverVersion" - ldflags = " ".join( - [ - # Don't exclude symbols (-s) so panics will have symbol information - # This will exclude DWARF debug tables (-w). - "-w", - f"-X {prop}={version}", - ] - ) - - tags = ["driverlib"] - if to_bool(get_var("DEBUG", "False")): - tags.append("assert") - - extra_tags = get_var("BUILD_TAGS", "") - if extra_tags: - extra_tags = extra_tags.split(",") - extra_tags = [tag.strip() for tag in extra_tags] - extra_tags = [tag for tag in extra_tags if tag] - tags.extend(extra_tags) - - tags = ",".join(tags) - tags = "-tags=" + tags - - info("Building", target, "version", version) - - env = {} - for var in SMUGGLE_VARS: - if var in os.environ: - env[var] = os.environ[var] - - if platform.system() == "Darwin" and target_name == "macos": - append_flags(env, "CGO_CFLAGS", "-mmacosx-version-min=11.0") - append_flags(env, "CGO_LDFLAGS", "-mmacosx-version-min=11.0") - - if should_use_docker(): - vendor_env = {"GOWORK": "off"} - check_call(["go", "mod", "vendor"], cwd=driver_root, env=vendor_env) - ldflags += ( - " -linkmode external -extldflags=-Wl,--version-script=/only-export-adbc.ld" - ) - - # Command differs under Docker so don't invoke this otherwise - maybe_build_docker( - repo_root=repo_root, - driver_root=driver_root, - env=env | vendor_env, - args=[ - "go", - "build", - "-buildmode=c-shared", - tags, - "-o", - f"/source/build/{target}", - "-ldflags", - ldflags, - "./pkg", - ], - container="manylinux", - ) - else: - check_call( - [ - "go", - "build", - "-buildmode=c-shared", - tags, - "-o", - f"{repo_root / 'build' / target}", - "-ldflags", - ldflags, - "./pkg", - ], - cwd=driver_root, - env=env, - ) - - output = (repo_root / "build" / target).resolve() - output.chmod(0o755) - header = output.with_suffix(".h") - header.unlink(missing_ok=True) - - -def build_rust( - repo_root: Path, - driver_root: Path, - driver: str, - target: str, -) -> None: - strict = to_bool(get_var("RELEASE", "false")) - version = detect_version(driver_root, strict=strict) - (repo_root / "build").mkdir(exist_ok=True) - - debug = to_bool(get_var("DEBUG", "False")) - target_name = target_platform() - - # Note: version embedded in library is determined by Cargo.toml - # TODO: check that it matches git tag? - args = [] - if not debug: - args.append("--release") - - features = [] - extra_features = get_var("FEATURES", "") - if extra_features: - extra_features = extra_features.split(",") - extra_features = [tag.strip() for tag in extra_features] - extra_features = [tag for tag in extra_features if tag] - features.extend(extra_features) - - if features: - args.append("--features") - args.append(",".join(features)) - - info("Building", target, "version", version, "features", features) - - env = {} - if platform.system() == "Darwin" and target_name == "macos": - # https://doc.rust-lang.org/nightly/rustc/platform-support/apple-darwin.html#os-version - env["MACOSX_DEPLOYMENT_TARGET"] = "11.0" - - maybe_build_docker( + make_env = make_config.MakeEnv( + ci=to_bool(get_var("CI", "false")), + debug=to_bool(get_var("DEBUG", "False")), + host_platform=PLATFORM, + host_architecture=normalize_arch(platform.machine()), + target_platform=target_platform(), + target_architecture=target_architecture(), repo_root=repo_root, driver_root=driver_root, - env=env, - args=["cargo", "build", *args], - container="manylinux-rust", + version=version, ) - - lib = driver_root / "target" - if debug: - lib = lib / "debug" - else: - lib = lib / "release" - - source_target = target - # Exclusion basically just for Databricks - their crate name is not - # "adbc_driver_databricks" but rather "databricks_adbc" - if target_name := get_var("TARGET_NAME", ""): - source_target = f"lib{target_name}.{target_extension()}" - if target_platform() == "windows": - source_target = source_target.removeprefix("lib") - lib = lib / source_target - info("Copying", lib, "to", repo_root / "build" / target) - - lib.rename(repo_root / "build" / target) - output = (repo_root / "build" / target).resolve() - output.chmod(0o755) - - -def build_script( - repo_root: Path, - driver_root: Path, - driver: str, - target: str, - *, - ci: bool = False, -) -> None: - strict = to_bool(get_var("RELEASE", "false")) - version = detect_version(driver_root, strict=strict) - (repo_root / "build").mkdir(exist_ok=True) - - debug = to_bool(get_var("DEBUG", "False")) - target_name = target_platform() - - args = [] - if debug: - args.append("test") - else: - args.append("release") - args.append(target_name) - args.append(target_architecture()) - - info("Building", target, "version", version) - - env = {} - if platform.system() == "Darwin" and target_name == "macos": - env["MACOSX_DEPLOYMENT_TARGET"] = "11.0" - - args = ["./ci/scripts/build.sh", *args] - if ci and target_name == "windows": - # Force use of Git Bash on GitHub Actions - args = [r"C:\Program Files\Git\bin\bash.EXE", *args] - - toolchain = get_var("TOOLCHAIN", "") - if not toolchain: - raise ValueError("Must specify TOOLCHAIN=toolchain for script-based build") - - container = { - "cpp": "manylinux-cpp", - "go": "manylinux", - "rust": "manylinux-rust", - }.get(toolchain) - if container is None: - raise ValueError(f"Unsupported TOOLCHAIN={toolchain} for script-based build") - - # if we're using a script, don't invoke docker for Go; the script itself - # will invoke docker - - if should_use_docker() and toolchain == "go": - check_call(args, cwd=driver_root, env=env) - else: - maybe_build_docker( - repo_root=repo_root, - driver_root=driver_root, - env=env, - args=args, - container=container, - ) - - output = (repo_root / "build" / target).resolve() - output.chmod(0o755) - - -def check_linux(binary: Path) -> None: - check_linux_symbols(read_linux_symbols(binary), binary) - - -def check_linux_symbols(symbols: list[str], binary: Path) -> None: - # Make sure only 'Adbc*' symbols are exported - bad_symbols = [] - for symbol in symbols: - if " T " not in symbol: - continue - _, _, name = symbol.partition(" T ") - if not name.startswith("Adbc"): - bad_symbols.append(name) - if bad_symbols: - raise RuntimeError( - f"{', '.join(bad_symbols[:3])}... ({len(bad_symbols)} symbols total) should not be exported from {binary}" - ) - - # Like upstream. Match manylinux2014's versions. - # https://peps.python.org/pep-0599/#the-manylinux2014-policy - manylinux = get_var("MANYLINUX", "manylinux2014").lower() - if manylinux == "manylinux2014": - glibc_max = "2.17" - glibcxx_max = "3.4.19" - elif manylinux == "manylinux_2_28": - glibc_max = "2.28" - glibcxx_max = "3.4.32" - - for symbol in symbols: - if "@GLIBC_" in symbol: - version = packaging.version.Version(symbol.partition("@")[2][6:]) - if version > packaging.version.Version(glibc_max): - raise RuntimeError( - f"{symbol} requires too new a glibc (max {glibc_max})" - ) - elif "@GLIBCXX_" in symbol: - version = packaging.version.Version(symbol.partition("@")[2][8:]) - if version > packaging.version.Version(glibcxx_max): - raise RuntimeError( - f"{symbol} requires too new a glibcxx (max {glibcxx_max})" - ) - - -def check_macos(binary: Path) -> None: - output = check_output(["otool", "-l", str(binary)]).splitlines() - minos = None - for line in output: - line = line.strip() - if not line.startswith("minos"): - continue - _, _, minos = line.partition(" ") - break - - if minos is None: - raise RuntimeError("Could not determine minimum macOS version") - - minos = packaging.version.Version(minos) - maxos = packaging.version.Version("11.0") - - if minos > maxos: - raise RuntimeError( - f"{binary} requires macOS {minos} but {maxos} was expected at most" - ) - - -def check(binary: Path) -> None: - if target_platform() == "linux": - if platform.system() != "Linux": - if should_use_docker(): - repo_root = Path(".").resolve() - check_linux_symbols( - read_linux_symbols_in_docker(repo_root, binary), - binary, - ) - else: - info( - "Skipping Linux compatibility checks on non-Linux host (no Docker)" - ) - return - check_linux(binary) - elif target_platform() == "macos": - if platform.system() != "Darwin": - info("Skipping macOS compatibility checks on non-macOS host") - return - check_macos(binary) + with (driver_root / "adbc-make.toml").open("rb") as f: + raw_make = tomllib.load(f) + make = make_config.MakeConfig.model_validate(raw_make) + return make_env, make, make.build_plan(make_env) def task_build(): - driver = get_var("DRIVER", "") - if not driver: - raise ValueError("Must specify DRIVER=driver") - - ci = to_bool(get_var("CI", False)) - lang = get_var("IMPL_LANG", "go").strip().lower() - - repo_root = Path(".").resolve().absolute() - driver_root = Path(driver) - if driver_root.is_dir(): - driver_root = driver_root.resolve() - elif ( - Path("./go.mod").is_file() or Path("./Cargo.toml").is_file() or lang == "script" - ): - driver_root = Path(".").resolve() + make_env, make, make_plan = _load_build_context() + driver_root = make_env.driver_root # Compute dependencies file_deps = [] + file_deps.append(driver_root / "adbc-make.toml") extensions = [".go", ".c", ".cc", ".cpp", ".h", ".rs"] for dirname, _, filenames in driver_root.walk(): for filename in filenames: @@ -743,51 +351,31 @@ def task_build(): elif any(filename.endswith(ext) for ext in extensions): file_deps.append(Path(dirname) / filename) - target = f"libadbc_driver_{driver}.{target_extension()}" - - if lang == "go": - actions = [ - lambda: build_go(repo_root, driver_root, driver, target), - ] - elif lang == "rust": - actions = [ - lambda: build_rust(repo_root, driver_root, driver, target), - ] - elif lang == "script": - actions = [ - lambda: build_script(repo_root, driver_root, driver, target, ci=ci), - ] - else: - raise ValueError(f"Unsupported LANG={lang}") - - targets = [repo_root / "build" / target] - result = { - "actions": actions, + "actions": [make_plan.run], "file_dep": [str(p) for p in file_deps], - "targets": targets, + "targets": [str(make_plan.target_path)], } # Force rebuild when cross-compiling (don't use doit cache) - if get_var("TARGET", "").strip(): + if make_env.is_cross_compile: result["uptodate"] = [False] # codespell:ignore uptodate + info("Build env:", make_env.model_dump_json()) + info("Build config:", make.model_dump_json()) + info("Build plan:", make_plan.model_dump_json()) + return result def task_check(): - driver = get_var("DRIVER", "") - if not driver: - raise ValueError("Must specify DRIVER=driver") - - repo_root = Path(".").resolve() - target = repo_root / "build" / f"libadbc_driver_{driver}.{target_extension()}" + make_env, make, make_plan = _load_build_context() + target = make_plan.target_path return { - "actions": [ - lambda: check(target), - ], - "file_dep": [target], + "actions": [lambda: make_checks.check(make_env, make, target)], + "task_dep": ["build"], + "file_dep": [str(target)], "targets": [], } diff --git a/adbc_drivers_dev/make_checks.py b/adbc_drivers_dev/make_checks.py new file mode 100644 index 0000000..45bdd24 --- /dev/null +++ b/adbc_drivers_dev/make_checks.py @@ -0,0 +1,150 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import subprocess +import sys +from pathlib import Path + +import packaging.version + +from .make_config import MakeConfig, MakeEnv + + +def _read_linux_symbols(binary: Path) -> list[str]: + return ( + subprocess.check_output( + ["nm", "--demangle", "--dynamic", str(binary)], text=True + ) + .strip() + .splitlines() + ) + + +def _read_linux_symbols_in_docker( + make_env: MakeEnv, make_config: MakeConfig, binary: Path +) -> list[str]: + rel_binary = binary.resolve().relative_to(make_env.repo_root.resolve()) + env = { + **os.environ, + "SOURCE_ROOT": str(make_env.repo_root), + "DOCKER_DEFAULT_PLATFORM": ( + f"{make_env.target_platform}/{make_env.target_architecture}" + ), + "MANYLINUX": make_config.manylinux, + } + return ( + subprocess.check_output( + [ + "docker", + "compose", + "run", + "--rm", + "manylinux", + "nm", + "--demangle", + "--dynamic", + f"/source/{rel_binary.as_posix()}", + ], + cwd=Path(__file__).parent, + env=env, + text=True, + ) + .strip() + .splitlines() + ) + + +def check_linux_symbols(symbols: list[str], binary: Path, manylinux: str) -> None: + bad_symbols = [] + for symbol in symbols: + if " T " not in symbol: + continue + _, _, name = symbol.partition(" T ") + if not name.startswith("Adbc"): + bad_symbols.append(name) + if bad_symbols: + raise RuntimeError( + f"{', '.join(bad_symbols[:3])}... ({len(bad_symbols)} symbols total) should not be exported from {binary}" + ) + + limits = { + "manylinux2014": ("2.17", "3.4.19"), + "manylinux_2_28": ("2.28", "3.4.32"), + } + try: + glibc_max, glibcxx_max = limits[manylinux.lower()] + except KeyError as err: + raise ValueError(f"Unsupported manylinux policy: {manylinux}") from err + + for symbol in symbols: + if "@GLIBC_" in symbol: + version = packaging.version.Version(symbol.partition("@")[2][6:]) + if version > packaging.version.Version(glibc_max): + raise RuntimeError( + f"{symbol} requires too new a glibc (max {glibc_max})" + ) + elif "@GLIBCXX_" in symbol: + version = packaging.version.Version(symbol.partition("@")[2][8:]) + if version > packaging.version.Version(glibcxx_max): + raise RuntimeError( + f"{symbol} requires too new a glibcxx (max {glibcxx_max})" + ) + + +def _check_linux(make_env: MakeEnv, make_config: MakeConfig, binary: Path) -> None: + if make_env.host_platform == "linux": + symbols = _read_linux_symbols(binary) + elif make_env.use_docker: + symbols = _read_linux_symbols_in_docker(make_env, make_config, binary) + else: + print( + "? Skipping Linux compatibility checks on non-Linux host (no Docker)", + file=sys.stderr, + ) + return + check_linux_symbols(symbols, binary, make_config.manylinux) + + +def _check_macos(binary: Path) -> None: + output = subprocess.check_output(["otool", "-l", str(binary)], text=True) + minos = None + for line in output.splitlines(): + line = line.strip() + if line.startswith("minos"): + _, _, minos = line.partition(" ") + break + + if minos is None: + raise RuntimeError("Could not determine minimum macOS version") + + version = packaging.version.Version(minos) + max_version = packaging.version.Version("11.0") + if version > max_version: + raise RuntimeError( + f"{binary} requires macOS {version} but {max_version} was expected at most" + ) + + +def check(make_env: MakeEnv, make_config: MakeConfig, binary: Path) -> None: + if make_env.target_platform == "linux": + _check_linux(make_env, make_config, binary) + elif make_env.target_platform == "macos": + if make_env.host_platform != "macos": + print( + "? Skipping macOS compatibility checks on non-macOS host", + file=sys.stderr, + ) + return + _check_macos(binary) diff --git a/adbc_drivers_dev/make_config.py b/adbc_drivers_dev/make_config.py new file mode 100644 index 0000000..af4ffd7 --- /dev/null +++ b/adbc_drivers_dev/make_config.py @@ -0,0 +1,504 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import secrets +import shlex +import subprocess +import sys +import time +import tomllib +import typing +from pathlib import Path + +from pydantic import BaseModel, Field + +_GO_VERSION_FLAG = "github.com/adbc-drivers/driverbase-go/driverbase.infoDriverVersion" +_SMUGGLE_VARS = {"CGO_CFLAGS", "CGO_LDFLAGS", "GOWORK", "PROTOC"} +_APPEND_ENV_VARS = {"CGO_CFLAGS", "CGO_LDFLAGS"} + + +def merge_build_env( + base: typing.Mapping[str, str], overrides: typing.Mapping[str, str] +) -> dict[str, str]: + """Merge build variables, preserving user-supplied CGO flags.""" + env = dict(base) + for key, value in overrides.items(): + if key in _APPEND_ENV_VARS and env.get(key): + env[key] += " " + value + else: + env[key] = value + return env + + +class MakeEnv(BaseModel): + ci: bool = Field( + default=False, description="Whether to build the driver in CI mode" + ) + debug: bool = Field( + default=False, description="Whether to build the driver in debug mode" + ) + host_platform: typing.Literal["linux", "macos", "windows"] + host_architecture: typing.Literal["amd64", "arm64"] + target_platform: typing.Literal["linux", "macos", "windows"] + target_architecture: typing.Literal["amd64", "arm64"] + repo_root: Path + driver_root: Path + version: str + + @property + def shared_library_affix(self) -> tuple[str, str]: + if self.target_platform == "linux": + return ("lib", ".so") + elif self.target_platform == "macos": + return ("lib", ".dylib") + elif self.target_platform == "windows": + # For CI, we always prefix the final artifact with "lib" + return ("lib", ".dll") + else: + raise ValueError(f"Unknown target platform: {self.target_platform}") + + @property + def source_library_affix(self) -> tuple[str, str]: + if self.target_platform == "windows": + return ("", ".dll") + return self.shared_library_affix + + def shared_library_name(self, driver: str) -> str: + prefix, suffix = self.shared_library_affix + output_name = f"{prefix}adbc_driver_{driver}{suffix}" + return output_name + + @property + def is_cross_compile(self) -> bool: + return ( + self.host_platform != self.target_platform + or self.host_architecture != self.target_architecture + ) + + @property + def use_docker(self) -> bool: + if self.target_platform == "linux": + return self.is_cross_compile or (not self.debug and self.ci) + return False + + +class MakePlan(BaseModel): + make_env: MakeEnv + make_config: "MakeConfig" + env_vars: dict[str, str] = Field( + default_factory=dict, + description="Environment variables to set when building the driver", + ) + commands: list[list[str]] = Field( + default_factory=list, description="The commands to run to build the driver" + ) + pre_commands: list[list[str]] = Field( + default_factory=list, + description="Commands to run directly on the host before building the driver", + ) + cleanup_paths: list[Path] = Field( + default_factory=list, + description="Generated files to remove after building the driver", + ) + artifact_path: Path | None + docker_container: str | None + + @property + def target_path(self) -> Path: + output_dir = self.make_env.driver_root / "build" + output_name = self.make_env.shared_library_name(self.make_config.driver) + return output_dir / output_name + + def _run_direct(self, commands: list[list[str]]) -> None: + for command in commands: + print( + "*", + " ".join(shlex.quote(arg) for arg in command), + f"[{self.make_env.driver_root}]", + file=sys.stderr, + ) + subprocess.run( + command, + cwd=self.make_env.driver_root, + env=merge_build_env(os.environ, self.env_vars), + check=True, + ) + + def _run_docker(self) -> None: + outer_env = { + **os.environ, + "SOURCE_ROOT": str(self.make_env.repo_root), + "ARCH": self.make_env.target_architecture, + "DOCKER_DEFAULT_PLATFORM": f"{self.make_env.target_platform}/{self.make_env.target_architecture}", + } + build_env = { + key: value for key, value in os.environ.items() if key in _SMUGGLE_VARS + } + build_env = merge_build_env(build_env, self.env_vars) + inner_env = ["env"] + inner_env += [f"{key}={shlex.quote(value)}" for key, value in build_env.items()] + + user_args = [] + if hasattr(os, "getuid"): + user_args = ["--user", str(os.getuid())] + + container_name = f"adbc-make-{self.make_config.driver}-{secrets.token_hex(4)}" + + # pull now, so it's not included in startup time below + try: + subprocess.check_call( + [ + "docker", + "compose", + "pull", + self.docker_container, + ], + env=outer_env, + cwd=Path(__file__).parent, + ) + except subprocess.CalledProcessError: + # Couldn't pull, so try to build + subprocess.check_call( + [ + "docker", + "compose", + "build", + self.docker_container, + ], + env=outer_env, + cwd=Path(__file__).parent, + ) + + with subprocess.Popen( + [ + "docker", + "compose", + "run", + "--rm", + "--name", + container_name, + *user_args, + *( + arg + for volume in self.make_config.additional_volumes + for arg in ("-v", volume) + ), + self.docker_container, + "bash", + "-c", + "sleep infinity", + ], + env=outer_env, + cwd=Path(__file__).parent, + ) as proc: + try: + # Wait for container to initialize + deadline = time.monotonic() + 120 + while time.monotonic() < deadline: + try: + subprocess.check_call( + [ + "docker", + "exec", + *user_args, + container_name, + "true", + ], + env=outer_env, + ) + break + except subprocess.CalledProcessError: + time.sleep(1) + + workdir = f"/source/{self.make_env.driver_root.relative_to(self.make_env.repo_root)}" + for command in self.commands: + # TODO: inner_env, user + if proc.poll() is not None: + raise RuntimeError( + f"Docker container {container_name} exited unexpectedly" + ) + wrapped_command = [ + "docker", + "exec", + *user_args, + "--workdir", + workdir, + container_name, + "bash", + "-c", + " ".join(inner_env + [shlex.quote(arg) for arg in command]), + ] + print( + "*", " ".join(wrapped_command), f"[{workdir}]", file=sys.stderr + ) + subprocess.run( + wrapped_command, + cwd=self.make_env.driver_root, + env=outer_env, + check=True, + ) + finally: + # result ignored + subprocess.run(["docker", "kill", container_name], env=outer_env) + proc.terminate() + proc.wait(timeout=30) + + def run(self) -> None: + target_path = self.target_path + target_path.parent.mkdir(parents=True, exist_ok=True) + if self.artifact_path is not None: + self.artifact_path.parent.mkdir(parents=True, exist_ok=True) + self._run_direct(self.pre_commands) + if self.docker_container is not None: + self._run_docker() + else: + self._run_direct(self.commands) + if self.artifact_path is not None: + self.artifact_path.resolve().copy(self.target_path) + self.target_path.chmod(0o755) + for path in self.cleanup_paths: + path.unlink(missing_ok=True) + + +class LangGo(BaseModel): + model_config = { + "extra": "forbid", + "validate_by_name": True, + "validate_by_alias": True, + } + + lang: typing.Literal["go"] + build_tags: list[str] = Field(default_factory=list, alias="build-tags") + go_mod_path: str | None = Field(default=None, alias="go-mod-path") + + +class LangRust(BaseModel): + model_config = { + "extra": "forbid", + "validate_by_name": True, + "validate_by_alias": True, + } + + lang: typing.Literal["rust"] + features: typing.List[str] = Field( + default_factory=list, + description="The features to enable when building the Rust driver, e.g. ['static-linking', 'bundled']", + ) + manifest_path: str | None = Field( + default=None, + alias="manifest-path", + ) + + +class LangScript(BaseModel): + model_config = { + "extra": "forbid", + "validate_by_name": True, + "validate_by_alias": True, + } + + lang: typing.Literal["script"] + toolchain: typing.Literal["cpp", "go", "rust"] + + @property + def docker_container(self) -> str: + if self.toolchain == "cpp": + return "manylinux-cpp" + elif self.toolchain == "go": + return "manylinux" + elif self.toolchain == "rust": + return "manylinux-rust" + else: + raise ValueError(f"Unknown toolchain: {self.toolchain}") + + +class MakeConfig(BaseModel): + model_config = { + "extra": "forbid", + "validate_by_name": True, + "validate_by_alias": True, + } + + driver: str = Field(description="The driver to build, e.g. 'spark', 'datafusion'") + lang: typing.Union[LangGo | LangRust | LangScript] = Field( + discriminator="lang", description="The implementation language" + ) + manylinux: str = Field( + default="manylinux2014", + description="The manylinux version to use when verifying allowed symbols on Linux, e.g. 'manylinux2014', 'manylinux_2_28'", + ) + additional_volumes: list[str] = Field( + default_factory=list, + alias="additional-volumes", + description="Additional Docker volume mounts, in HOST:CONTAINER format", + ) + + def build_plan(self, config: MakeEnv) -> MakePlan: + env_vars = default_build_env(config) + + if isinstance(self.lang, LangGo): + module_path = Path(self.lang.go_mod_path or ".") + module_root = config.driver_root / module_path + ldflags = [ + # Don't exclude symbols so panics will have symbol information + # "-s", + # Exclude DWARF debug tables + "-w", + # Embed Go version + f"-X {_GO_VERSION_FLAG}={config.version}", + ] + tags = ["driverlib"] + if config.debug: + tags.append("assert") + tags.extend(self.lang.build_tags) + + go = ["go"] + if self.lang.go_mod_path: + go.extend(["-C", str(module_path)]) + + output_name = config.shared_library_name(self.driver) + module_output = module_root / "build" / output_name + args = [ + *go, + "build", + "-buildmode=c-shared", + f"-tags={','.join(tags)}", + ] + + pre_commands = [] + docker_container = None + if config.use_docker: + env_vars["GOWORK"] = "off" + pre_commands.append([*go, "mod", "vendor"]) + ldflags.extend( + [ + "-linkmode external", + "-extldflags=-Wl,--version-script=/only-export-adbc.ld", + ] + ) + docker_container = "manylinux" + + args.extend( + [ + f"-ldflags={' '.join(ldflags)}", + "-o", + str(Path("build") / output_name), + "./pkg", + ] + ) + + artifact_path = None + if module_root != config.driver_root: + artifact_path = module_output + + return MakePlan( + make_env=config, + make_config=self, + env_vars=env_vars, + commands=[args], + pre_commands=pre_commands, + cleanup_paths=[module_output.with_suffix(".h")], + artifact_path=artifact_path, + docker_container=docker_container, + ) + + elif isinstance(self.lang, LangRust): + args = ["cargo", "build"] + + artifact_path = config.driver_root + manifest_path = config.driver_root / "Cargo.toml" + if self.lang.manifest_path: + artifact_path /= self.lang.manifest_path + manifest_path = artifact_path / "Cargo.toml" + args.append("--manifest-path") + # Use relative path so it also works in Docker + args.append(str(Path(self.lang.manifest_path) / "Cargo.toml")) + + artifact_path /= "target" + if config.debug: + artifact_path /= "debug" + else: + args.append("--release") + artifact_path /= "release" + + if self.lang.features: + args.append("--features") + args.append(",".join(self.lang.features)) + + with manifest_path.open("rb") as f: + cargo_toml = tomllib.load(f) + + if "lib" in cargo_toml and "name" in cargo_toml["lib"]: + lib_name = cargo_toml["lib"]["name"] + else: + lib_name = cargo_toml["package"]["name"].replace("-", "_") + + prefix, suffix = config.source_library_affix + artifact_path /= f"{prefix}{lib_name}{suffix}" + + docker_container = None + if config.use_docker: + docker_container = "manylinux-rust" + + return MakePlan( + make_env=config, + make_config=self, + env_vars=env_vars, + commands=[args], + artifact_path=artifact_path, + docker_container=docker_container, + ) + + elif isinstance(self.lang, LangScript): + args = ["./ci/scripts/build.sh"] + if config.debug: + args.append("test") + else: + args.append("release") + + args.append(config.target_platform) + args.append(config.target_architecture) + + if config.target_platform == "windows" and config.ci: + # Force use of Git Bash on GitHub Actions + args = [r"C:\Program Files\Git\bin\bash.EXE", *args] + + docker_container = None + if config.use_docker: + docker_container = self.lang.docker_container + + return MakePlan( + make_env=config, + make_config=self, + env_vars=env_vars, + commands=[args], + artifact_path=None, + docker_container=docker_container, + ) + + raise NotImplementedError( + f"Build plan not implemented for lang={self.lang.lang}" + ) + + +def default_build_env(config: MakeEnv) -> dict[str, str]: + env = {} + if config.target_platform == "macos": + # https://doc.rust-lang.org/nightly/rustc/platform-support/apple-darwin.html#os-version + env["MACOSX_DEPLOYMENT_TARGET"] = "11.0" + env["CGO_CFLAGS"] = "-mmacosx-version-min=11.0" + env["CGO_LDFLAGS"] = "-mmacosx-version-min=11.0" + + return env diff --git a/adbc_drivers_dev/templates/pixi.toml b/adbc_drivers_dev/templates/pixi.toml index 8574c59..d04a375 100644 --- a/adbc_drivers_dev/templates/pixi.toml +++ b/adbc_drivers_dev/templates/pixi.toml @@ -31,11 +31,10 @@ platforms = ["linux-64", "osx-arm64", "win-64", "linux-aarch64"] version = "0.1.0" [tasks] +make = "adbc-make run build VERBOSE=true" <% if lang == "go" %> -make = "adbc-make run build DRIVER=<{driver}> VERBOSE=true" test = "go test -tags assert -v ./..." <% elif lang == "rust" %> -make = "adbc-make run build DRIVER=<{driver}> VERBOSE=true IMPL_LANG=rust" test = "cargo test" <% endif %> release = "adbc-release" diff --git a/adbc_drivers_dev/templates/test.yaml b/adbc_drivers_dev/templates/test.yaml index 509d77a..1f41448 100644 --- a/adbc_drivers_dev/templates/test.yaml +++ b/adbc_drivers_dev/templates/test.yaml @@ -416,7 +416,7 @@ jobs: source .env.test fi set +a - pixi run adbc-make build DEBUG=true VERBOSE=true DRIVER=<{driver}> IMPL_LANG=<{lang}> <{' '.join(lang_config.build.additional_make_args) }> + pixi run adbc-make build DEBUG=true VERBOSE=true <{' '.join(lang_config.build.additional_make_args) }> - name: Start Test Dependencies # Can't use Docker on macOS AArch64 runners, and Windows containers # work but often the container doesn't support Windows @@ -597,7 +597,7 @@ jobs: source .env.release fi set +a - pixi run adbc-make check CI=true VERBOSE=true DRIVER=<{driver}> IMPL_LANG=<{lang}> <{' '.join(lang_config.build.additional_make_args) }><% if release %> RELEASE=true<% endif %> + pixi run adbc-make check CI=true VERBOSE=true <{' '.join(lang_config.build.additional_make_args) }><% if release %> RELEASE=true<% endif %> if [[ -f ci/scripts/post-build.sh ]]; then ./ci/scripts/post-build.sh release ${{ matrix.platform }} ${{ matrix.arch }} diff --git a/pixi.lock b/pixi.lock index fe891cb..5a693a4 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1,18 +1,31 @@ -version: 6 +version: 7 +platforms: +- name: linux-64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=x86_64 +- name: osx-arm64 + virtual-packages: + - __unix=0=0 + - __osx=13.0 + - __archspec=0=m1 +- name: win-64 + virtual-packages: + - __win=10.0 + - __archspec=0=x86_64 environments: default: channels: - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple - options: - pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda @@ -28,39 +41,42 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.2-h32b2ec7_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/88/25f1e65ff6ed678e1be9aaeabeedcb26531d17b6b86c4b1d50d8f0c50825/pygit2-1.19.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/14/88/25f1e65ff6ed678e1be9aaeabeedcb26531d17b6b86c4b1d50d8f0c50825/pygit2-1.19.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a1/5c/8b56b08db91e569d0a4fbfa3e492ed2026081bdd7e892f63ba1c88a2f548/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda @@ -71,53 +87,86 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.2-h40d2674_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl - - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl + - pypi: ./ - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a3/9f/7a39d4c612e12966130504e1610f500b397d7968feb6d25e1353614dab74/pygit2-1.19.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.1-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.3-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.6-h4b44e0e_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7d/68/d8d58938dfb1370b266a1a729e6d77a985be23689a0496498ee17b2cbf90/platformdirs-4.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9c/38/3d6dcbf8379cb86d71a2325210ca3469a33767d8254b74d8c343db26ce87/doit-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/a1/a8f21afe574f22fde3d04fb102c4e75b5a1077fa1ea1ee3f7b072aa8f858/pygit2-1.19.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/67/be582a7370fdc9e6846c5be4888a530dcadd055eef5b932e0e85c33c7d73/ruamel_yaml_clib-0.2.15-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl test: channels: - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple - options: - pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda @@ -131,48 +180,60 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.2-h32b2ec7_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.2-h32b2ec7_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/88/25f1e65ff6ed678e1be9aaeabeedcb26531d17b6b86c4b1d50d8f0c50825/pygit2-1.19.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/14/88/25f1e65ff6ed678e1be9aaeabeedcb26531d17b6b86c4b1d50d8f0c50825/pygit2-1.19.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a1/5c/8b56b08db91e569d0a4fbfa3e492ed2026081bdd7e892f63ba1c88a2f548/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda @@ -181,41 +242,81 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.2-h40d2674_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl - - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a3/9f/7a39d4c612e12966130504e1610f500b397d7968feb6d25e1353614dab74/pygit2-1.19.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.1-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.3-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.6-h4b44e0e_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7d/68/d8d58938dfb1370b266a1a729e6d77a985be23689a0496498ee17b2cbf90/platformdirs-4.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9c/38/3d6dcbf8379cb86d71a2325210ca3469a33767d8254b74d8c343db26ce87/doit-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/a1/a8f21afe574f22fde3d04fb102c4e75b5a1077fa1ea1ee3f7b072aa8f858/pygit2-1.19.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/67/be582a7370fdc9e6846c5be4888a530dcadd055eef5b932e0e85c33c7d73/ruamel_yaml_clib-0.2.15-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 @@ -238,27 +339,6 @@ packages: purls: [] size: 23621 timestamp: 1650670423406 -- pypi: ./ - name: adbc-drivers-dev - version: '0.1' - sha256: aa7a1b0cb6620a538c61aeed2cea704c1664f1d66eb4b6f1c8472b12a689adfc - requires_dist: - - doit - - jinja2 - - packaging - - platformdirs - - pydantic>=2.0 - - pygit2 - - requests - - ruamel-yaml>=0.18.11,<0.19 - - tomlkit>=0.13.2,<0.14 -- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - name: annotated-types - version: 0.7.0 - sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 - requires_dist: - - typing-extensions>=4.0.0 ; python_full_version < '3.9' - requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 md5: 51a19bba1b8ebfb60df25cde030b7ebc @@ -270,177 +350,28 @@ packages: purls: [] size: 260341 timestamp: 1757437258798 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1 - md5: 58fd217444c2a5701a44244faf518206 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 + md5: 186a18e3ba246eccfc7cff00cd19a870 depends: - - __osx >=11.0 - license: bzip2-1.0.6 - license_family: BSD + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT purls: [] - size: 125061 - timestamp: 1757437486465 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - sha256: b5974ec9b50e3c514a382335efa81ed02b05906849827a34061c496f4defa0b2 - md5: bddacf101bb4dd0e51811cb69c7790e2 + size: 12728445 + timestamp: 1767969922681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda + sha256: 1027bd8aa0d5144e954e426ab6218fd5c14e54a98f571985675468b339c808ca + md5: 3ec0aa5037d39b06554109a01e6fb0c6 depends: - - __unix - license: ISC - purls: [] - size: 146519 - timestamp: 1767500828366 -- pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl - name: certifi - version: 2026.1.4 - sha256: 9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: cffi - version: 2.0.0 - sha256: afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775 - requires_dist: - - pycparser ; implementation_name != 'PyPy' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl - name: cffi - version: 2.0.0 - sha256: c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13 - requires_dist: - - pycparser ; implementation_name != 'PyPy' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl - name: charset-normalizer - version: 3.4.4 - sha256: da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: charset-normalizer - version: 3.4.4 - sha256: ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - name: cloudpickle - version: 3.1.2 - sha256: 9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 - md5: 962b9857ee8e7018c22f2776ffa0b2d7 - depends: - - python >=3.9 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/colorama?source=hash-mapping - size: 27011 - timestamp: 1733218222191 -- pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl - name: doit - version: 0.36.0 - sha256: ebc285f6666871b5300091c26eafdff3de968a6bd60ea35dd1e3fc6f2e32479a - requires_dist: - - cloudpickle - - importlib-metadata>=4.4 - - tomli ; python_full_version < '3.11' and extra == 'toml' - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 - md5: 8e662bd460bda79b1ea39194e3c4c9ab - depends: - - python >=3.10 - - typing_extensions >=4.6.0 - license: MIT and PSF-2.0 - purls: - - pkg:pypi/exceptiongroup?source=hash-mapping - size: 21333 - timestamp: 1763918099466 -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 - md5: 186a18e3ba246eccfc7cff00cd19a870 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libstdcxx >=14 - license: MIT - license_family: MIT - purls: [] - size: 12728445 - timestamp: 1767969922681 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - sha256: d4cefbca587429d1192509edc52c88de52bc96c2447771ddc1f8bee928aed5ef - md5: 1e93aca311da0210e660d2247812fa02 - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: [] - size: 12358010 - timestamp: 1767970350308 -- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl - name: idna - version: '3.11' - sha256: 771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea - requires_dist: - - ruff>=0.6.2 ; extra == 'all' - - mypy>=1.11.2 ; extra == 'all' - - pytest>=8.3.2 ; extra == 'all' - - flake8>=7.1.1 ; extra == 'all' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl - name: importlib-metadata - version: 8.7.1 - sha256: 5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 - requires_dist: - - zipp>=3.20 - - pytest>=6,!=8.1.* ; extra == 'test' - - packaging ; extra == 'test' - - pyfakefs ; extra == 'test' - - flufl-flake8 ; extra == 'test' - - pytest-perf>=0.9.2 ; extra == 'test' - - jaraco-test>=5.4 ; extra == 'test' - - sphinx>=3.5 ; extra == 'doc' - - jaraco-packaging>=9.3 ; extra == 'doc' - - rst-linker>=1.9 ; extra == 'doc' - - furo ; extra == 'doc' - - sphinx-lint ; extra == 'doc' - - jaraco-tidelift>=1.4 ; extra == 'doc' - - ipython ; extra == 'perf' - - pytest-checkdocs>=2.4 ; extra == 'check' - - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' - - pytest-cov ; extra == 'cover' - - pytest-enabler>=3.4 ; extra == 'enabler' - - pytest-mypy>=1.0.1 ; extra == 'type' - - mypy<1.19 ; platform_python_implementation == 'PyPy' and extra == 'type' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19 - md5: 9614359868482abba1bd15ce465e3c42 - depends: - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/iniconfig?source=compressed-mapping - size: 13387 - timestamp: 1760831448842 -- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - name: jinja2 - version: 3.1.6 - sha256: 85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 - requires_dist: - - markupsafe>=2.0 - - babel>=2.7 ; extra == 'i18n' - requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - sha256: 1027bd8aa0d5144e954e426ab6218fd5c14e54a98f571985675468b339c808ca - md5: 3ec0aa5037d39b06554109a01e6fb0c6 - depends: - - __glibc >=2.17,<3.0.a0 - - zstd >=1.5.7,<1.6.0a0 - constrains: - - binutils_impl_linux-64 2.45 - license: GPL-3.0-only - license_family: GPL + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45 + license: GPL-3.0-only + license_family: GPL purls: [] size: 730831 timestamp: 1766513089214 @@ -457,18 +388,6 @@ packages: purls: [] size: 76643 timestamp: 1763549731408 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98 - md5: b79875dbb5b1db9a4a22a4520f918e1a - depends: - - __osx >=11.0 - constrains: - - expat 2.7.3.* - license: MIT - license_family: MIT - purls: [] - size: 67800 - timestamp: 1763549994166 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54 md5: 35f29eec58405aaf55e01cb470d8c26a @@ -480,16 +399,6 @@ packages: purls: [] size: 57821 timestamp: 1760295480630 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f - md5: 411ff7cd5d1472bba0f55c0faf04453b - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: [] - size: 40251 - timestamp: 1760295839166 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda sha256: 6eed58051c2e12b804d53ceff5994a350c61baf117ec83f5f10c953a3f311451 md5: 6d0363467e6ed84f11435eb309f2ff06 @@ -526,17 +435,6 @@ packages: purls: [] size: 112894 timestamp: 1749230047870 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285 - md5: d6df911d4564d77c4374b02552cb17d1 - depends: - - __osx >=11.0 - constrains: - - xz 5.8.1.* - license: 0BSD - purls: [] - size: 92286 - timestamp: 1749230283517 - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda sha256: 3aa92d4074d4063f2a162cd8ecb45dccac93e543e565c01a787e16a43501f7ee md5: c7e925f37e3b40d893459e625f6a53f1 @@ -548,16 +446,6 @@ packages: purls: [] size: 91183 timestamp: 1748393666725 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2 - md5: 85ccccb47823dd9f7a99d2c7f530342f - depends: - - __osx >=11.0 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 71829 - timestamp: 1748393749336 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda sha256: 04596fcee262a870e4b7c9807224680ff48d4d0cc0dac076a602503d3dc6d217 md5: da5be73701eecd0e8454423fd6ffcf30 @@ -570,17 +458,6 @@ packages: purls: [] size: 942808 timestamp: 1768147973361 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - sha256: 6e9b9f269732cbc4698c7984aa5b9682c168e2a8d1e0406e1ff10091ca046167 - md5: 4b0bf313c53c3e89692f020fb55d5f2c - depends: - - __osx >=11.0 - - icu >=78.2,<79.0a0 - - libzlib >=1.3.1,<2.0a0 - license: blessing - purls: [] - size: 909777 - timestamp: 1768148320535 - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda sha256: 813427918316a00c904723f1dfc3da1bbc1974c5cfe1ed1e704c6f4e0798cbc6 md5: 68f68355000ec3f1d6f26ea13e8f525f @@ -618,28 +495,6 @@ packages: purls: [] size: 60963 timestamp: 1727963148474 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b - md5: 369964e85dc26bfe78f41399b366c435 - depends: - - __osx >=11.0 - constrains: - - zlib 1.3.1 *_2 - license: Zlib - license_family: Other - purls: [] - size: 46438 - timestamp: 1727963202283 -- pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: markupsafe - version: 3.0.3 - sha256: 457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - name: markupsafe - version: 3.0.3 - sha256: c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 - requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 md5: 47e340acb35de30501a76c7c799c41d7 @@ -650,15 +505,6 @@ packages: purls: [] size: 891641 timestamp: 1738195959188 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 - md5: 068d497125e4bf8a66bf707254fff5ae - depends: - - __osx >=11.0 - license: X11 AND BSD-3-Clause - purls: [] - size: 797030 - timestamp: 1738196177597 - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d md5: 9ee58d5c534af06558933af3c845a780 @@ -671,22 +517,126 @@ packages: purls: [] size: 3165399 timestamp: 1762839186699 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda - sha256: ebe93dafcc09e099782fe3907485d4e1671296bc14f8c383cb6f3dfebb773988 - md5: b34dc4172653c13dcf453862f251af2b +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.2-h32b2ec7_100_cp314.conda + build_number: 100 + sha256: a120fb2da4e4d51dd32918c149b04a08815fd2bd52099dad1334647984bb07f1 + md5: 1cef1236a05c3a98f68c33ae9425f656 depends: - - __osx >=11.0 - - ca-certificates - license: Apache-2.0 - license_family: Apache + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.1,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.1,<4.0a0 + - libuuid >=2.41.2,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.4,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 purls: [] - size: 3108371 - timestamp: 1762839712322 -- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - name: packaging - version: '25.0' - sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 - requires_python: '>=3.8' + size: 36790521 + timestamp: 1765021515427 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda + sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64 + md5: 86bc20552bf46075e3d92b67f089172d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3284905 + timestamp: 1763054914403 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + sha256: b5974ec9b50e3c514a382335efa81ed02b05906849827a34061c496f4defa0b2 + md5: bddacf101bb4dd0e51811cb69c7790e2 + depends: + - __unix + license: ISC + purls: [] + size: 146519 + timestamp: 1767500828366 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + sha256: 95e8e74062a5fe5f870ac8c90302b6e89945165fdaed7810606e84ddee6aac12 + md5: e27d2ac27b096dc51fedfcf775a53f9b + depends: + - __win + license: ISC + purls: [] + run_exports: {} + size: 132136 + timestamp: 1784754918886 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama?source=hash-mapping + run_exports: {} + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 + md5: 8e662bd460bda79b1ea39194e3c4c9ab + depends: + - python >=3.10 + - typing_extensions >=4.6.0 + license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup?source=hash-mapping + run_exports: {} + size: 21333 + timestamp: 1763918099466 +- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda + sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19 + md5: 9614359868482abba1bd15ce465e3c42 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/iniconfig?source=hash-mapping + run_exports: {} + size: 13387 + timestamp: 1760831448842 - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 md5: 58335b26c38bf4a20f399384c33cbcf9 @@ -699,22 +649,19 @@ packages: - pkg:pypi/packaging?source=hash-mapping size: 62477 timestamp: 1745345660407 -- pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl - name: platformdirs - version: 4.5.1 - sha256: d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31 - requires_dist: - - furo>=2025.9.25 ; extra == 'docs' - - proselint>=0.14 ; extra == 'docs' - - sphinx-autodoc-typehints>=3.2 ; extra == 'docs' - - sphinx>=8.2.3 ; extra == 'docs' - - appdirs==1.4.4 ; extra == 'test' - - covdefaults>=2.3 ; extra == 'test' - - pytest-cov>=7 ; extra == 'test' - - pytest-mock>=3.15.1 ; extra == 'test' - - pytest>=8.4.2 ; extra == 'test' - - mypy>=1.18.2 ; extra == 'type' - requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 + md5: 4c06a92e74452cfa53623a81592e8934 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=hash-mapping + run_exports: {} + size: 91574 + timestamp: 1777103621679 - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e md5: d7585b6550ad04c8c5e21097ada2888e @@ -724,54 +671,10 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/pluggy?source=compressed-mapping + - pkg:pypi/pluggy?source=hash-mapping + run_exports: {} size: 25877 timestamp: 1764896838868 -- pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - name: pycparser - version: '2.23' - sha256: e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934 - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl - name: pydantic - version: 2.12.5 - sha256: e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d - requires_dist: - - annotated-types>=0.6.0 - - pydantic-core==2.41.5 - - typing-extensions>=4.14.1 - - typing-inspection>=0.4.2 - - email-validator>=2.0.0 ; extra == 'email' - - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - name: pydantic-core - version: 2.41.5 - sha256: 22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375 - requires_dist: - - typing-extensions>=4.14.1 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl - name: pydantic-core - version: 2.41.5 - sha256: 1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14 - requires_dist: - - typing-extensions>=4.14.1 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/14/88/25f1e65ff6ed678e1be9aaeabeedcb26531d17b6b86c4b1d50d8f0c50825/pygit2-1.19.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - name: pygit2 - version: 1.19.1 - sha256: 074b0b14c6f3c7e2c6ea0b01a90832407a71520c920918aa07f509c91f1691f9 - requires_dist: - - cffi>=2.0 - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/a3/9f/7a39d4c612e12966130504e1610f500b397d7968feb6d25e1353614dab74/pygit2-1.19.1-cp314-cp314-macosx_11_0_arm64.whl - name: pygit2 - version: 1.19.1 - sha256: d0f3924d8d0d54a7fe186761c76dc1b6e5fcf41794a6daba1630db3bc216b9ba - requires_dist: - - cffi>=2.0 - requires_python: '>=3.11' - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a md5: 6b6ece66ebcae2d5f326c77ef2c5a066 @@ -783,6 +686,18 @@ packages: - pkg:pypi/pygments?source=hash-mapping size: 889287 timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 + md5: 16c18772b340887160c79a6acc022db0 + depends: + - python >=3.10 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/pygments?source=hash-mapping + run_exports: {} + size: 893031 + timestamp: 1774796815820 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda sha256: 9e749fb465a8bedf0184d8b8996992a38de351f7c64e967031944978de03a520 md5: 2b694bad8a50dc2f712f5368de866480 @@ -804,59 +719,28 @@ packages: - pkg:pypi/pytest?source=hash-mapping size: 299581 timestamp: 1765062031645 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.2-h32b2ec7_100_cp314.conda - build_number: 100 - sha256: a120fb2da4e4d51dd32918c149b04a08815fd2bd52099dad1334647984bb07f1 - md5: 1cef1236a05c3a98f68c33ae9425f656 - depends: - - __glibc >=2.17,<3.0.a0 - - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.3,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - libgcc >=14 - - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.51.1,<4.0a0 - - libuuid >=2.41.2,<3.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.4,<4.0a0 - - python_abi 3.14.* *_cp314 - - readline >=8.2,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - purls: [] - size: 36790521 - timestamp: 1765021515427 - python_site_packages_path: lib/python3.14/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.2-h40d2674_100_cp314.conda - build_number: 100 - sha256: 1a93782e90b53e04c2b1a50a0f8bf0887936649d19dba6a05b05c4b44dae96b7 - md5: 14f15ab0d31a2ee5635aa56e77132594 +- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda + sha256: 430051d80765207a7d782b2b188230ba1489d35c6e75fd9903f76cb9fda4af16 + md5: 64c98a12c4e23eb238bf66bbecafdf3c depends: - - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.3,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.51.1,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.4,<4.0a0 - - python_abi 3.14.* *_cp314 - - readline >=8.2,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - purls: [] - size: 13575758 - timestamp: 1765021280625 - python_site_packages_path: lib/python3.14/site-packages + - colorama + - pygments >=2.7.2 + - python >=3.10 + - iniconfig >=1.0.1 + - packaging >=22 + - pluggy >=1.5,<2 + - tomli >=1 + - exceptiongroup >=1 + - python + constrains: + - pytest-faulthandler >=2 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pytest?source=compressed-mapping + run_exports: {} + size: 306724 + timestamp: 1782127176429 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda build_number: 8 sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 @@ -866,43 +750,747 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6989 timestamp: 1752805904792 -- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 - md5: d7d95fc8287ea7bf33e0e7116d2b95ec +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + sha256: 62940c563de45790ba0f076b9f2085a842a65662268b02dd136a8e9b1eaf47a8 + md5: 72e780e9aa2d0a3295f59b1874e3768b depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL - purls: [] - size: 345073 - timestamp: 1765813471974 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 - md5: f8381319127120ce51e081dce4865cf4 + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=hash-mapping + size: 21453 + timestamp: 1768146676791 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd + md5: b5325cf06a000c5b14970462ff5e4d58 depends: - - __osx >=11.0 - - ncurses >=6.5,<7.0a0 + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=hash-mapping + run_exports: {} + size: 21561 + timestamp: 1774492402955 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions?source=hash-mapping + size: 51692 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + sha256: 2d888f90af0686044882c74193ec80a90ec1943145d94a7b1b048958acda1848 + md5: c70ad746c22219b9700931707482992c + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions?source=hash-mapping + run_exports: {} + size: 52631 + timestamp: 1783002732887 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + sha256: b928c30ddcb0e3f544c6eade8352737e6e610e263276b90232db6a578ef899d8 + md5: fcb489df604d100968b737f2cb6076c6 + license: LicenseRef-Public-Domain + purls: [] + run_exports: {} + size: 118849 + timestamp: 1784250406640 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda + sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1 + md5: 58fd217444c2a5701a44244faf518206 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 125061 + timestamp: 1757437486465 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda + sha256: d4cefbca587429d1192509edc52c88de52bc96c2447771ddc1f8bee928aed5ef + md5: 1e93aca311da0210e660d2247812fa02 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 12358010 + timestamp: 1767970350308 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda + sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98 + md5: b79875dbb5b1db9a4a22a4520f918e1a + depends: + - __osx >=11.0 + constrains: + - expat 2.7.3.* + license: MIT + license_family: MIT + purls: [] + size: 67800 + timestamp: 1763549994166 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda + sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f + md5: 411ff7cd5d1472bba0f55c0faf04453b + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 40251 + timestamp: 1760295839166 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda + sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285 + md5: d6df911d4564d77c4374b02552cb17d1 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.1.* + license: 0BSD + purls: [] + size: 92286 + timestamp: 1749230283517 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda + sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2 + md5: 85ccccb47823dd9f7a99d2c7f530342f + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 71829 + timestamp: 1748393749336 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda + sha256: 6e9b9f269732cbc4698c7984aa5b9682c168e2a8d1e0406e1ff10091ca046167 + md5: 4b0bf313c53c3e89692f020fb55d5f2c + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 909777 + timestamp: 1768148320535 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b + md5: 369964e85dc26bfe78f41399b366c435 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + purls: [] + size: 46438 + timestamp: 1727963202283 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 + md5: 068d497125e4bf8a66bf707254fff5ae + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + size: 797030 + timestamp: 1738196177597 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda + sha256: ebe93dafcc09e099782fe3907485d4e1671296bc14f8c383cb6f3dfebb773988 + md5: b34dc4172653c13dcf453862f251af2b + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3108371 + timestamp: 1762839712322 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.2-h40d2674_100_cp314.conda + build_number: 100 + sha256: 1a93782e90b53e04c2b1a50a0f8bf0887936649d19dba6a05b05c4b44dae96b7 + md5: 14f15ab0d31a2ee5635aa56e77132594 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.1,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.1,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.4,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + size: 13575758 + timestamp: 1765021280625 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 + depends: + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL purls: [] size: 313930 timestamp: 1765813902568 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda + sha256: ad0c67cb03c163a109820dc9ecf77faf6ec7150e942d1e8bb13e5d39dc058ab7 + md5: a73d54a5abba6543cb2f0af1bfbd6851 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3125484 + timestamp: 1763055028377 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 + md5: ab136e4c34e97f34fb621d2592a393d8 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 433413 + timestamp: 1764777166076 +- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + sha256: 76dfb71df5e8d1c4eded2dbb5ba15bb8fb2e2b0fe42d94145d5eed4c75c35902 + md5: 4cb8e6b48f67de0b018719cdf1136306 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 56115 + timestamp: 1771350256444 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.1-hac47afa_1.conda + sha256: 1a54d874addda73b6f7164d5f3905821277a1831bcc05edd74b3085391688571 + md5: ccc490c81ffe14181861beac0e8f3169 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.8.1.* + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 71631 + timestamp: 1781203724164 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + sha256: 59d01f2dfa8b77491b5888a5ab88ff4e1574c9359f7e229da254cdfe27ddc190 + md5: 720b39f5ec0610457b725eb3f396219a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libffi >=3.5.2,<3.6.0a0 + size: 45831 + timestamp: 1769456418774 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + sha256: d636d1a25234063642f9c531a7bb58d84c1c496411280a36ea000bd122f078f1 + md5: 8f83619ab1588b98dd99c90b0bfc5c6d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 106486 + timestamp: 1775825663227 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + sha256: 40dcd0b9522a6e0af72a9db0ced619176e7cfdb114855c7a64f278e73f8a7514 + md5: e4a9fc2bba3b022dad998c78856afe47 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 89411 + timestamp: 1769482314283 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_0.conda + sha256: 62e1c45ec71ab2e5deeeb0e47e7df6a609991e91d46348f16df50c68fee145c8 + md5: ca0d59f40a02a15e9b5d0ff8db0f85e3 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: blessing + purls: [] + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 1313790 + timestamp: 1785016158097 +- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + sha256: 0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527 + md5: 5d2ff29d465097458cc3ff6569151991 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 58529 + timestamp: 1785276664143 +- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.3-hf411b9b_0.conda + sha256: cb6e7ba0d010ee0d3249ce9886de3d7613d26d9965d4c95666fa66b9c4c31001 + md5: e99f95734a326c0fd4d02bbd995150d4 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - openssl >=3.6.3,<4.0a0 + size: 9414790 + timestamp: 1781071745579 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.6-h4b44e0e_101_cp314.conda + build_number: 101 + sha256: 3a9ae901cd853d507d97aa8b72af4b9a572a3f92dcc5bad8a1318f77ff4e0e64 + md5: 67bbf51f88a2053513d7c78f485f7479 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.53.3,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 18338767 + timestamp: 1784911044838 + python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_3.conda + sha256: 13fa29257d43f8e630a1e591ed77fae9bbbb236b011432f01e2034cf36e6bf03 + md5: aaf79e2af50a151fb5b5a3e3f38b7a69 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: TCL + purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3782314 + timestamp: 1784229072899 +- conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 + md5: 71b24316859acd00bdb8b38f5e2ce328 + constrains: + - vc14_runtime >=14.29.30037 + - vs2015_runtime >=14.29.30037 + license: LicenseRef-MicrosoftWindowsSDK10 + purls: [] + run_exports: {} + size: 694692 + timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + sha256: 35444c55a92e2f7f7ba26bc70f81e56e52344f7d064c0fd4b40a46a58517b79c + md5: aa805b5522c2a98fa286e551a1f48546 + depends: + - vc14_runtime >=14.51.36247 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 21383 + timestamp: 1785359368566 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + sha256: 4e4cb599cdc41bf2109d1464c127b5bcbddf548ce3e322e612afb691338b48f8 + md5: ac5333bb3d429361f23adf704cc49a78 + depends: + - ucrt >=10.0.20348.0 + - vcomp14 14.51.36247 habf1de7_41 + constrains: + - vs2015_runtime 14.51.36247.* *_41 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + run_exports: {} + size: 767955 + timestamp: 1785359364369 +- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + sha256: 731e043390c9457299484d39e427221fc868a9249540a498a5a4f6456c7744d1 + md5: 350bb67a5c8e5f1c53347ac544ab6600 + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.51.36247.* *_41 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + run_exports: + strong: + - vcomp14 >=14.51.36247 + size: 155910 + timestamp: 1785359349999 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + sha256: 368d8628424966fd8f9c8018326a9c779e06913dd39e646cf331226acc90e5b2 + md5: 053b84beec00b71ea8ff7a4f84b55207 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 388453 + timestamp: 1764777142545 +- pypi: ./ + name: adbc-drivers-dev + requires_dist: + - doit + - jinja2 + - packaging + - platformdirs + - pydantic>=2.0 + - pygit2 + - requests + - ruamel-yaml>=0.18.11,<0.19 + - tomlkit>=0.13.2,<0.14 + requires_python: '>=3.14' +- pypi: https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl + name: certifi + version: 2026.7.22 + sha256: 62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + name: pycparser + version: '3.0' + sha256: b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + name: idna + version: '3.11' + sha256: 771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea + requires_dist: + - ruff>=0.6.2 ; extra == 'all' + - mypy>=1.11.2 ; extra == 'all' + - pytest>=8.3.2 ; extra == 'all' + - flake8>=7.1.1 ; extra == 'all' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/14/88/25f1e65ff6ed678e1be9aaeabeedcb26531d17b6b86c4b1d50d8f0c50825/pygit2-1.19.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + name: pygit2 + version: 1.19.1 + sha256: 074b0b14c6f3c7e2c6ea0b01a90832407a71520c920918aa07f509c91f1691f9 + requires_dist: + - cffi>=2.0 + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + name: typing-extensions + version: 4.15.0 + sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl + name: idna + version: '3.18' + sha256: 7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 + requires_dist: + - ruff>=0.6.2 ; extra == 'all' + - mypy>=1.11.2 ; extra == 'all' + - pytest>=8.3.2 ; extra == 'all' + requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl name: requests - version: 2.32.5 - sha256: 2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 + version: 2.32.5 + sha256: 2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 + requires_dist: + - charset-normalizer>=2,<4 + - idna>=2.5,<4 + - urllib3>=1.21.1,<3 + - certifi>=2017.4.17 + - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks' + - chardet>=3.0.2,<6 ; extra == 'use-chardet-on-py3' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl + name: packaging + version: '25.0' + sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl + name: markupsafe + version: 3.0.3 + sha256: bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl + name: charset-normalizer + version: 3.4.4 + sha256: da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + name: zipp + version: 3.23.0 + sha256: 071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e + requires_dist: + - pytest>=6,!=8.1.* ; extra == 'test' + - jaraco-itertools ; extra == 'test' + - jaraco-functools ; extra == 'test' + - more-itertools ; extra == 'test' + - big-o ; extra == 'test' + - pytest-ignore-flaky ; extra == 'test' + - jaraco-test ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest-mypy ; extra == 'type' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + name: urllib3 + version: 2.6.3 + sha256: bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4 + requires_dist: + - brotli>=1.2.0 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=1.2.0.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2>=4,<5 ; extra == 'h2' + - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks' + - backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: 457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl + name: cffi + version: 2.1.0 + sha256: 1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb + requires_dist: + - pycparser ; implementation_name != 'PyPy' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/44/83/a2960d2c975836daa629a73995134fd86520c101412578c57da3d2aa71ee/doit-0.36.0-py3-none-any.whl + name: doit + version: 0.36.0 + sha256: ebc285f6666871b5300091c26eafdff3de968a6bd60ea35dd1e3fc6f2e32479a + requires_dist: + - cloudpickle + - importlib-metadata>=4.4 + - tomli ; python_full_version < '3.11' and extra == 'toml' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: cffi + version: 2.0.0 + sha256: afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775 + requires_dist: + - pycparser ; implementation_name != 'PyPy' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl + name: typing-extensions + version: 4.16.0 + sha256: 481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl + name: charset-normalizer + version: 3.4.9 + sha256: 16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.41.5 + sha256: 22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl + name: cffi + version: 2.0.0 + sha256: c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13 + requires_dist: + - pycparser ; implementation_name != 'PyPy' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + name: pydantic + version: 2.12.5 + sha256: e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d + requires_dist: + - annotated-types>=0.6.0 + - pydantic-core==2.41.5 + - typing-extensions>=4.14.1 + - typing-inspection>=0.4.2 + - email-validator>=2.0.0 ; extra == 'email' + - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + name: jinja2 + version: 3.1.6 + sha256: 85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + requires_dist: + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: charset-normalizer + version: 3.4.4 + sha256: ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl + name: ruamel-yaml-clib + version: 0.2.15 + sha256: 480894aee0b29752560a9de46c0e5f84a82602f2bc5c6cde8db9a345319acfdf + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.41.5 + sha256: 1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + name: annotated-types + version: 0.7.0 + sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 + requires_dist: + - typing-extensions>=4.0.0 ; python_full_version < '3.9' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/7d/68/d8d58938dfb1370b266a1a729e6d77a985be23689a0496498ee17b2cbf90/platformdirs-4.11.0-py3-none-any.whl + name: platformdirs + version: 4.11.0 + sha256: 360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl + name: urllib3 + version: 2.7.0 + sha256: 9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 + requires_dist: + - brotli>=1.2.0 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=1.2.0.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2>=4,<5 ; extra == 'h2' + - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks' + - backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + name: cloudpickle + version: 3.1.2 + sha256: 9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl + name: annotated-types + version: 0.8.0 + sha256: f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9c/38/3d6dcbf8379cb86d71a2325210ca3469a33767d8254b74d8c343db26ce87/doit-0.37.0-py3-none-any.whl + name: doit + version: 0.37.0 + sha256: a9f181566aa90faac515e276f85e6526019554ed7e13c12cf9dc094ffecf3e1b + requires_dist: + - tomli ; python_full_version < '3.11' and extra == 'toml' + - cloudpickle ; platform_python_implementation != 'PyPy' and extra == 'cloudpickle' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl + name: pycparser + version: '2.23' + sha256: e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl + name: requests + version: 2.34.2 + sha256: 2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 requires_dist: - charset-normalizer>=2,<4 - idna>=2.5,<4 - - urllib3>=1.21.1,<3 - - certifi>=2017.4.17 + - urllib3>=1.26,<3 + - certifi>=2023.5.7 - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks' - - chardet>=3.0.2,<6 ; extra == 'use-chardet-on-py3' + - chardet>=3.0.2,<8 ; extra == 'use-chardet-on-py3' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a1/5c/8b56b08db91e569d0a4fbfa3e492ed2026081bdd7e892f63ba1c88a2f548/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: ruamel-yaml-clib + version: 0.2.15 + sha256: 2812ff359ec1f30129b62372e5f22a52936fac13d5d21e70373dbca5d64bb97c requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a3/9f/7a39d4c612e12966130504e1610f500b397d7968feb6d25e1353614dab74/pygit2-1.19.1-cp314-cp314-macosx_11_0_arm64.whl + name: pygit2 + version: 1.19.1 + sha256: d0f3924d8d0d54a7fe186761c76dc1b6e5fcf41794a6daba1630db3bc216b9ba + requires_dist: + - cffi>=2.0 + requires_python: '>=3.11' - pypi: https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl name: ruamel-yaml version: 0.18.17 @@ -913,62 +1501,43 @@ packages: - ryd ; extra == 'docs' - mercurial>5.7 ; extra == 'docs' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl - name: ruamel-yaml-clib - version: 0.2.15 - sha256: 480894aee0b29752560a9de46c0e5f84a82602f2bc5c6cde8db9a345319acfdf - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a1/5c/8b56b08db91e569d0a4fbfa3e492ed2026081bdd7e892f63ba1c88a2f548/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: ruamel-yaml-clib - version: 0.2.15 - sha256: 2812ff359ec1f30129b62372e5f22a52936fac13d5d21e70373dbca5d64bb97c +- pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + name: markupsafe + version: 3.0.3 + sha256: c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64 - md5: 86bc20552bf46075e3d92b67f089172d - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - libzlib >=1.3.1,<2.0a0 - constrains: - - xorg-libx11 >=1.8.12,<2.0a0 - license: TCL - license_family: BSD - purls: [] - size: 3284905 - timestamp: 1763054914403 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda - sha256: ad0c67cb03c163a109820dc9ecf77faf6ec7150e942d1e8bb13e5d39dc058ab7 - md5: a73d54a5abba6543cb2f0af1bfbd6851 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: TCL - license_family: BSD - purls: [] - size: 3125484 - timestamp: 1763055028377 -- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - sha256: 62940c563de45790ba0f076b9f2085a842a65662268b02dd136a8e9b1eaf47a8 - md5: 72e780e9aa2d0a3295f59b1874e3768b - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomli?source=compressed-mapping - size: 21453 - timestamp: 1768146676791 +- pypi: https://files.pythonhosted.org/packages/bc/a1/a8f21afe574f22fde3d04fb102c4e75b5a1077fa1ea1ee3f7b072aa8f858/pygit2-1.19.3-cp314-cp314-win_amd64.whl + name: pygit2 + version: 1.19.3 + sha256: 0ff9f187b01d6629c14ad069b100e147093b70279496984faa012783c5832b66 + requires_dist: + - cffi>=2.0 + requires_python: '>=3.11' - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl name: tomlkit version: 0.13.3 sha256: c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0 requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl - name: typing-extensions - version: 4.15.0 - sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 +- pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl + name: platformdirs + version: 4.5.1 + sha256: d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31 + requires_dist: + - furo>=2025.9.25 ; extra == 'docs' + - proselint>=0.14 ; extra == 'docs' + - sphinx-autodoc-typehints>=3.2 ; extra == 'docs' + - sphinx>=8.2.3 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=7 ; extra == 'test' + - pytest-mock>=3.15.1 ; extra == 'test' + - pytest>=8.4.2 ; extra == 'test' + - mypy>=1.18.2 ; extra == 'type' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d2/67/be582a7370fdc9e6846c5be4888a530dcadd055eef5b932e0e85c33c7d73/ruamel_yaml_clib-0.2.15-cp314-cp314-win_amd64.whl + name: ruamel-yaml-clib + version: 0.2.15 + sha256: ac9b8d5fa4bb7fd2917ab5027f60d4234345fd366fe39aa711d5dca090aa1467 requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl name: typing-inspection @@ -977,79 +1546,58 @@ packages: requires_dist: - typing-extensions>=4.12.0 requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 - md5: 0caa1af407ecff61170c9437a808404d - depends: - - python >=3.10 - - python - license: PSF-2.0 - license_family: PSF - purls: - - pkg:pypi/typing-extensions?source=hash-mapping - size: 51692 - timestamp: 1756220668932 -- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c - md5: ad659d0a2b3e47e38d829aa8cad2d610 - license: LicenseRef-Public-Domain - purls: [] - size: 119135 - timestamp: 1767016325805 -- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl - name: urllib3 - version: 2.6.3 - sha256: bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4 - requires_dist: - - brotli>=1.2.0 ; platform_python_implementation == 'CPython' and extra == 'brotli' - - brotlicffi>=1.2.0.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2>=4,<5 ; extra == 'h2' - - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks' - - backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl - name: zipp - version: 3.23.0 - sha256: 071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e +- pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl + name: packaging + version: '26.2' + sha256: 5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl + name: certifi + version: 2026.1.4 + sha256: 9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl + name: importlib-metadata + version: 8.7.1 + sha256: 5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 requires_dist: + - zipp>=3.20 - pytest>=6,!=8.1.* ; extra == 'test' - - jaraco-itertools ; extra == 'test' - - jaraco-functools ; extra == 'test' - - more-itertools ; extra == 'test' - - big-o ; extra == 'test' - - pytest-ignore-flaky ; extra == 'test' - - jaraco-test ; extra == 'test' + - packaging ; extra == 'test' + - pyfakefs ; extra == 'test' + - flufl-flake8 ; extra == 'test' + - pytest-perf>=0.9.2 ; extra == 'test' + - jaraco-test>=5.4 ; extra == 'test' - sphinx>=3.5 ; extra == 'doc' - jaraco-packaging>=9.3 ; extra == 'doc' - rst-linker>=1.9 ; extra == 'doc' - furo ; extra == 'doc' - sphinx-lint ; extra == 'doc' - jaraco-tidelift>=1.4 ; extra == 'doc' + - ipython ; extra == 'perf' - pytest-checkdocs>=2.4 ; extra == 'check' - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' - pytest-cov ; extra == 'cover' - - pytest-enabler>=2.2 ; extra == 'enabler' - - pytest-mypy ; extra == 'type' + - pytest-enabler>=3.4 ; extra == 'enabler' + - pytest-mypy>=1.0.1 ; extra == 'type' + - mypy<1.19 ; platform_python_implementation == 'PyPy' and extra == 'type' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + name: pydantic-core + version: 2.46.4 + sha256: 811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + name: pydantic + version: 2.13.4 + sha256: 45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba + requires_dist: + - annotated-types>=0.6.0 + - pydantic-core==2.46.4 + - typing-extensions>=4.14.1 + - typing-inspection>=0.4.2 + - email-validator>=2.0.0 ; extra == 'email' + - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 - md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 - depends: - - __glibc >=2.17,<3.0.a0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 601375 - timestamp: 1764777111296 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 - md5: ab136e4c34e97f34fb621d2592a393d8 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 433413 - timestamp: 1764777166076 diff --git a/pyproject.toml b/pyproject.toml index 6034f6c..c433ba3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ [project] name = "adbc-drivers-dev" version = "0.1" +requires-python = ">=3.14" dependencies = [ "doit", @@ -45,7 +46,7 @@ packages = ["adbc_drivers_dev", "adbc_drivers_dev.rat"] [tool.pixi.workspace] channels = ["conda-forge"] -platforms = ["linux-64", "osx-arm64"] +platforms = ["linux-64", "osx-arm64", "win-64"] [tool.pixi.pypi-dependencies] adbc-drivers-dev = { path = ".", editable = true } diff --git a/tests/make/godummy/adbc-make.toml b/tests/make/godummy/adbc-make.toml new file mode 100644 index 0000000..c06471d --- /dev/null +++ b/tests/make/godummy/adbc-make.toml @@ -0,0 +1,19 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +driver = "godummy" + +[lang] +lang = "go" +go-mod-path = "module" diff --git a/tests/make/godummy/module/go.mod b/tests/make/godummy/module/go.mod new file mode 100644 index 0000000..4627b06 --- /dev/null +++ b/tests/make/godummy/module/go.mod @@ -0,0 +1,17 @@ +// Copyright (c) 2026 ADBC Drivers Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module github.com/adbc-drivers/dev/tests/godummy + +go 1.25 diff --git a/tests/make/godummy/module/pkg/main.go b/tests/make/godummy/module/pkg/main.go new file mode 100644 index 0000000..53e9df2 --- /dev/null +++ b/tests/make/godummy/module/pkg/main.go @@ -0,0 +1,25 @@ +// Copyright (c) 2026 ADBC Drivers Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +/* +#include +*/ +import "C" + +//export AdbcDummyInit +func AdbcDummyInit() {} + +func main() {} diff --git a/tests/make/rustdummy/Cargo.lock b/tests/make/rustdummy/Cargo.lock new file mode 100644 index 0000000..3653278 --- /dev/null +++ b/tests/make/rustdummy/Cargo.lock @@ -0,0 +1,768 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adbc_core" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365059b13a01bbf6f324b5bfe328232a819679731431f78105e2883256236858" +dependencies = [ + "arrow-array", + "arrow-schema", +] + +[[package]] +name = "adbc_driver_manager" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aac8bb789ff1f493bcb5d423c65b7a1b21ba5516f5e60797b4e1c64b34a2b61" +dependencies = [ + "adbc_core", + "adbc_ffi", + "arrow-array", + "arrow-schema", + "libloading", + "path-slash", + "regex", + "toml", + "windows-registry", + "windows-sys", +] + +[[package]] +name = "adbc_dummy" +version = "0.1.0" +dependencies = [ + "adbc_core", + "adbc_driver_manager", + "adbc_ffi", + "arrow-array", + "arrow-buffer", + "arrow-schema", +] + +[[package]] +name = "adbc_ffi" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cdef84c12e9e8858b300440c36ca94ba24fb2e188175251dc39bb44ba3584e" +dependencies = [ + "adbc_core", + "arrow-array", + "arrow-schema", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "const-random", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrow-array" +version = "59.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9486151b2f0785bafc6fa04fc5c99fcb4495455662e58787ea32eaaed33c4192" +dependencies = [ + "ahash", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "half", + "hashbrown", + "num-complex", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-buffer" +version = "59.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4776577a87794bfdf0b4e90e2ea12454fa7738ea2823c4be5b9d1851da7b434" +dependencies = [ + "bytes", + "half", + "num-bigint", + "num-traits", +] + +[[package]] +name = "arrow-data" +version = "59.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38fe43e2e8704360f1464e6e8cc4fc381ef02cc4fb0192afa8df1aaa0115c66" +dependencies = [ + "arrow-buffer", + "arrow-schema", + "half", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-schema" +version = "59.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e4969dc350d571766247143ab36a5187d095d3d3690970408bc630d47c69e5" +dependencies = [ + "bitflags", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "cc" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "windows-link", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "futures-core" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" + +[[package]] +name = "futures-task" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" + +[[package]] +name = "futures-util" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml" +version = "1.1.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +dependencies = [ + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] diff --git a/tests/make/rustdummy/Cargo.toml b/tests/make/rustdummy/Cargo.toml new file mode 100644 index 0000000..2400fa2 --- /dev/null +++ b/tests/make/rustdummy/Cargo.toml @@ -0,0 +1,40 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# This file has been modified from its original version, which is +# under the Apache License: +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +name = "adbc_dummy" +description = "A dummy ADBC driver for testing purposes" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" +publish = false + +[dependencies] +adbc_core = "0.24.0" +adbc_ffi = "0.24.0" +adbc_driver_manager = "0.24.0" +arrow-array = "59.1" +arrow-buffer = "59.1" +arrow-schema = "59.1" + +[lib] +crate-type = ["lib", "cdylib"] diff --git a/tests/make/rustdummy/README.md b/tests/make/rustdummy/README.md new file mode 100644 index 0000000..bdeef08 --- /dev/null +++ b/tests/make/rustdummy/README.md @@ -0,0 +1,18 @@ + + +This is a dummy driver purely for testing the make implementation. Originally +from apache/arrow-adbc. diff --git a/tests/make/rustdummy/adbc-make.toml b/tests/make/rustdummy/adbc-make.toml new file mode 100644 index 0000000..db0ad95 --- /dev/null +++ b/tests/make/rustdummy/adbc-make.toml @@ -0,0 +1,18 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +driver = "rustdummy" + +[lang] +lang = "rust" diff --git a/tests/make/rustdummy/src/lib.rs b/tests/make/rustdummy/src/lib.rs new file mode 100644 index 0000000..d48c047 --- /dev/null +++ b/tests/make/rustdummy/src/lib.rs @@ -0,0 +1,926 @@ +// Copyright (c) 2026 ADBC Drivers Contributors +// +// This file has been modified from its original version, which is +// under the Apache License: +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use std::collections::HashSet; +use std::sync::Arc; +use std::{collections::HashMap, fmt::Debug, hash::Hash}; + +use adbc_core::options::Statistics; +use arrow_array::{ + Array, ArrayRef, BinaryArray, BooleanArray, Float64Array, Int16Array, Int32Array, Int64Array, + ListArray, MapArray, RecordBatch, RecordBatchReader, StringArray, StructArray, UInt32Array, + UInt64Array, UnionArray, +}; +use arrow_buffer::{OffsetBuffer, ScalarBuffer}; +use arrow_schema::{ArrowError, DataType, Field, Schema, SchemaRef, UnionFields}; + +use adbc_core::{ + Connection, Database, Driver, Optionable, PartitionedResult, Statement, constants, + error::{Error, Result, Status}, + options::{ + InfoCode, ObjectDepth, OptionConnection, OptionDatabase, OptionStatement, OptionValue, + }, + schemas, +}; + +pub const VENDOR_INFO_CODE: u32 = 10_042; + +#[derive(Debug)] +pub struct SingleBatchReader { + batch: Option, + schema: SchemaRef, +} + +impl SingleBatchReader { + pub fn new(batch: RecordBatch) -> Self { + let schema = batch.schema(); + Self { + batch: Some(batch), + schema, + } + } +} + +impl Iterator for SingleBatchReader { + type Item = std::result::Result; + + fn next(&mut self) -> Option { + Ok(self.batch.take()).transpose() + } +} + +impl RecordBatchReader for SingleBatchReader { + fn schema(&self) -> SchemaRef { + self.schema.clone() + } +} + +fn get_table_schema() -> Schema { + Schema::new(vec![ + Field::new("a", DataType::UInt32, true), + Field::new("b", DataType::Float64, false), + Field::new("c", DataType::Utf8, true), + ]) +} + +fn get_table_data() -> RecordBatch { + RecordBatch::try_new( + Arc::new(get_table_schema()), + vec![ + Arc::new(UInt32Array::from(vec![1, 2, 3])), + Arc::new(Float64Array::from(vec![1.5, 2.5, 3.5])), + Arc::new(StringArray::from(vec!["A", "B", "C"])), + ], + ) + .unwrap() +} + +fn set_option(options: &mut HashMap, key: T, value: OptionValue) -> Result<()> +where + T: Eq + Hash, +{ + options.insert(key, value); + Ok(()) +} + +fn get_option_bytes(options: &HashMap, key: T, kind: &str) -> Result> +where + T: Eq + Hash + Debug, +{ + let value = options.get(&key); + match value { + None => Err(Error::with_message_and_status( + format!("Unrecognized {kind} option: {key:?}"), + Status::NotFound, + )), + Some(value) => match value { + OptionValue::Bytes(value) => Ok(value.clone()), + _ => Err(Error::with_message_and_status( + format!("Incorrect value for {kind} option: {key:?}"), + Status::InvalidData, + )), + }, + } +} + +fn get_option_double(options: &HashMap, key: T, kind: &str) -> Result +where + T: Eq + Hash + Debug, +{ + let value = options.get(&key); + match value { + None => Err(Error::with_message_and_status( + format!("Unrecognized {kind} option: {key:?}"), + Status::NotFound, + )), + Some(value) => match value { + OptionValue::Double(value) => Ok(*value), + _ => Err(Error::with_message_and_status( + format!("Incorrect value for {kind} option: {key:?}"), + Status::InvalidData, + )), + }, + } +} + +fn get_option_int(options: &HashMap, key: T, kind: &str) -> Result +where + T: Eq + Hash + Debug, +{ + let value = options.get(&key); + match value { + None => Err(Error::with_message_and_status( + format!("Unrecognized {kind} option: {key:?}"), + Status::NotFound, + )), + Some(value) => match value { + OptionValue::Int(value) => Ok(*value), + _ => Err(Error::with_message_and_status( + format!("Incorrect value for {kind} option: {key:?}"), + Status::InvalidData, + )), + }, + } +} + +fn get_option_string(options: &HashMap, key: T, kind: &str) -> Result +where + T: Eq + Hash + Debug, +{ + let value = options.get(&key); + match value { + None => Err(Error::with_message_and_status( + format!("Unrecognized {kind} option: {key:?}"), + Status::NotFound, + )), + Some(value) => match value { + OptionValue::String(value) => Ok(value.clone()), + _ => Err(Error::with_message_and_status( + format!("Incorrect value for {kind} option: {key:?}"), + Status::InvalidData, + )), + }, + } +} + +fn maybe_panic(fnname: impl AsRef) { + if let Some(func) = std::env::var_os("PANICDUMMY_FUNC").map(|x| x.to_string_lossy().to_string()) + { + if fnname.as_ref() == func { + let message = std::env::var_os("PANICDUMMY_MESSAGE") + .map(|x| x.to_string_lossy().to_string()) + .unwrap_or_else(|| format!("We panicked in {}!", fnname.as_ref())); + panic!("{}", message); + } + } +} + +/// A dummy driver used for testing purposes. +#[derive(Default)] +pub struct DummyDriver {} + +impl Driver for DummyDriver { + type DatabaseType = DummyDatabase; + + fn new_database(&mut self) -> Result { + Ok(Self::DatabaseType::default()) + } + + fn new_database_with_opts( + &mut self, + opts: impl IntoIterator::Option, OptionValue)>, + ) -> Result { + let mut database = Self::DatabaseType::default(); + for (key, value) in opts { + database.set_option(key, value)?; + } + Ok(database) + } +} + +#[derive(Default)] +pub struct DummyDatabase { + options: HashMap, +} + +impl Optionable for DummyDatabase { + type Option = OptionDatabase; + + fn set_option(&mut self, key: Self::Option, value: OptionValue) -> Result<()> { + set_option(&mut self.options, key, value) + } + + fn get_option_bytes(&self, key: Self::Option) -> Result> { + get_option_bytes(&self.options, key, "database") + } + + fn get_option_double(&self, key: Self::Option) -> Result { + get_option_double(&self.options, key, "database") + } + + fn get_option_int(&self, key: Self::Option) -> Result { + get_option_int(&self.options, key, "database") + } + + fn get_option_string(&self, key: Self::Option) -> Result { + get_option_string(&self.options, key, "database") + } +} + +impl Database for DummyDatabase { + type ConnectionType = DummyConnection; + + fn new_connection(&self) -> Result { + Ok(Self::ConnectionType::default()) + } + + fn new_connection_with_opts( + &self, + opts: impl IntoIterator::Option, OptionValue)>, + ) -> Result { + let mut connection = Self::ConnectionType::default(); + for (key, value) in opts { + connection.set_option(key, value)?; + } + Ok(connection) + } +} + +#[derive(Default)] +pub struct DummyConnection { + options: HashMap, +} + +impl Optionable for DummyConnection { + type Option = OptionConnection; + + fn set_option(&mut self, key: Self::Option, value: OptionValue) -> Result<()> { + set_option(&mut self.options, key, value) + } + + fn get_option_bytes(&self, key: Self::Option) -> Result> { + get_option_bytes(&self.options, key, "connection") + } + + fn get_option_double(&self, key: Self::Option) -> Result { + get_option_double(&self.options, key, "connection") + } + + fn get_option_int(&self, key: Self::Option) -> Result { + get_option_int(&self.options, key, "connection") + } + + fn get_option_string(&self, key: Self::Option) -> Result { + get_option_string(&self.options, key, "connection") + } +} + +impl Connection for DummyConnection { + type StatementType = DummyStatement; + + fn new_statement(&mut self) -> Result { + Ok(Self::StatementType::default()) + } + + // This method is used to test that errors round-trip correctly. + fn cancel(&mut self) -> Result<()> { + let mut error = Error::with_message_and_status("message", Status::Cancelled); + error.vendor_code = constants::ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA; + error.sqlstate = [1, 2, 3, 4, 5]; + error.details = Some(vec![ + ("key1".into(), b"AAA".into()), + ("key2".into(), b"ZZZZZ".into()), + ]); + Err(error) + } + + fn commit(&mut self) -> Result<()> { + Ok(()) + } + + fn get_info( + &self, + codes: Option>, + ) -> Result> { + let string_value_array = StringArray::from(vec!["MyVendorName", "MyVendorInfoValue"]); + let bool_value_array = BooleanArray::from(vec![true]); + let int64_value_array = Int64Array::from(vec![42]); + let int32_bitmask_array = Int32Array::from(vec![1337]); + let string_list_array = ListArray::new( + Arc::new(Field::new("item", DataType::Utf8, true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 2])), + Arc::new(StringArray::from(vec!["Hello", "World"])), + None, + ); + let int32_to_int32_list_map_array = MapArray::try_new( + Arc::new(Field::new_struct( + "entries", + vec![ + Field::new("key", DataType::Int32, false), + Field::new_list("value", Field::new_list_field(DataType::Int32, true), true), + ], + false, + )), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 2])), + StructArray::new( + vec![ + Field::new("key", DataType::Int32, false), + Field::new_list("value", Field::new_list_field(DataType::Int32, true), true), + ] + .into(), + vec![ + Arc::new(Int32Array::from(vec![42, 1337])), + Arc::new(ListArray::new( + Arc::new(Field::new("item", DataType::Int32, true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 6])), + Arc::new(Int32Array::from(vec![1, 2, 3, 1, 4, 9])), + None, + )), + ], + None, + ), + None, + false, + )?; + + // Every info value this driver knows, as (code, union type id, offset into that type's + // child array). Includes a vendor-specific code to exercise `InfoCode::Other`. + let known_info: [(InfoCode, i8, i32); 7] = [ + (InfoCode::VendorName, 0, 0), + (InfoCode::VendorVersion, 1, 0), + (InfoCode::VendorArrowVersion, 2, 0), + (InfoCode::DriverName, 3, 0), + (InfoCode::DriverVersion, 4, 0), + (InfoCode::DriverArrowVersion, 5, 0), + (InfoCode::Other(VENDOR_INFO_CODE), 0, 1), + ]; + let rows: Vec<&(InfoCode, i8, i32)> = known_info + .iter() + .filter(|(code, _, _)| codes.as_ref().is_none_or(|codes| codes.contains(code))) + .collect(); + + let name_array = UInt32Array::from( + rows.iter() + .map(|(code, _, _)| code.into()) + .collect::>(), + ); + let type_id_buffer = rows + .iter() + .map(|(_, type_id, _)| *type_id) + .collect::>(); + let value_offsets_buffer = rows + .iter() + .map(|(_, _, offset)| *offset) + .collect::>(); + + let value_array = UnionArray::try_new( + UnionFields::try_new( + [0, 1, 2, 3, 4, 5], + [ + Field::new("string_value", string_value_array.data_type().clone(), true), + Field::new("bool_value", bool_value_array.data_type().clone(), true), + Field::new("int64_value", int64_value_array.data_type().clone(), true), + Field::new( + "int32_bitmask", + int32_bitmask_array.data_type().clone(), + true, + ), + Field::new("string_list", string_list_array.data_type().clone(), true), + Field::new( + "int32_to_int32_list_map", + int32_to_int32_list_map_array.data_type().clone(), + true, + ), + ], + ) + .expect("must be valid"), + type_id_buffer, + Some(value_offsets_buffer), + vec![ + Arc::new(string_value_array), + Arc::new(bool_value_array), + Arc::new(int64_value_array), + Arc::new(int32_bitmask_array), + Arc::new(string_list_array), + Arc::new(int32_to_int32_list_map_array), + ], + )?; + + let batch = RecordBatch::try_new( + schemas::GET_INFO_SCHEMA.clone(), + vec![Arc::new(name_array), Arc::new(value_array)], + )?; + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn get_objects( + &self, + _depth: ObjectDepth, + _catalog: Option<&str>, + _db_schema: Option<&str>, + _table_name: Option<&str>, + _table_type: Option>, + _column_name: Option<&str>, + ) -> Result> { + let constraint_column_usage_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("fk_catalog", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["my_catalog"])) as ArrayRef, + ), + ( + Arc::new(Field::new("fk_db_schema", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["my_db_schema"])) as ArrayRef, + ), + ( + Arc::new(Field::new("fk_table", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["my_table"])) as ArrayRef, + ), + ( + Arc::new(Field::new("fk_column_name", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["my_column"])) as ArrayRef, + ), + ]); + + let constraint_column_usage_array = ListArray::new( + Arc::new(Field::new("item", schemas::USAGE_SCHEMA.clone(), true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(constraint_column_usage_array_inner), + None, + ); + + let constraint_column_names_array = ListArray::new( + Arc::new(Field::new("item", DataType::Utf8, true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(StringArray::from(vec!["my_other_column"])), + None, + ); + + let table_constraints_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("constraint_name", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["my_constraint"])) as ArrayRef, + ), + ( + Arc::new(Field::new("constraint_type", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["FOREIGN KEY"])) as ArrayRef, + ), + ( + Arc::new(Field::new( + "constraint_column_names", + DataType::new_list(DataType::Utf8, true), + false, + )), + Arc::new(constraint_column_names_array) as ArrayRef, + ), + ( + Arc::new(Field::new( + "constraint_column_usage", + DataType::new_list(schemas::USAGE_SCHEMA.clone(), true), + true, + )), + Arc::new(constraint_column_usage_array) as ArrayRef, + ), + ]); + + let table_columns_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("column_name", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["my_column"])) as ArrayRef, + ), + ( + Arc::new(Field::new("ordinal_position", DataType::Int32, true)), + Arc::new(Int32Array::from(vec![0])) as ArrayRef, + ), + ( + Arc::new(Field::new("remarks", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["Nice column!"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_data_type", DataType::Int16, true)), + Arc::new(Int16Array::from(vec![0])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_type_name", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["my_type"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_column_size", DataType::Int32, true)), + Arc::new(Int32Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_decimal_digits", DataType::Int16, true)), + Arc::new(Int16Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_num_prec_radix", DataType::Int16, true)), + Arc::new(Int16Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_nullable", DataType::Int16, true)), + Arc::new(Int16Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_column_def", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["column_def"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_sql_data_type", DataType::Int16, true)), + Arc::new(Int16Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_datetime_sub", DataType::Int16, true)), + Arc::new(Int16Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_char_octet_length", DataType::Int32, true)), + Arc::new(Int32Array::from(vec![42])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_is_nullable", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["YES"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_scope_catalog", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["MyCatalog"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_scope_schema", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["MySchema"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_scope_table", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["MyTable"])) as ArrayRef, + ), + ( + Arc::new(Field::new("xdbc_is_autoincrement", DataType::Boolean, true)), + Arc::new(BooleanArray::from(vec![true])) as ArrayRef, + ), + ( + Arc::new(Field::new( + "xdbc_is_generatedcolumn", + DataType::Boolean, + true, + )), + Arc::new(BooleanArray::from(vec![true])) as ArrayRef, + ), + ]); + + let table_columns_array = ListArray::new( + Arc::new(Field::new("item", schemas::COLUMN_SCHEMA.clone(), true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(table_columns_array_inner), + None, + ); + + let table_constraints_array = ListArray::new( + Arc::new(Field::new("item", schemas::CONSTRAINT_SCHEMA.clone(), true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(table_constraints_array_inner), + None, + ); + + let db_schema_tables_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("table_name", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["default"])) as ArrayRef, + ), + ( + Arc::new(Field::new("table_type", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["table"])) as ArrayRef, + ), + ( + Arc::new(Field::new( + "table_columns", + DataType::new_list(schemas::COLUMN_SCHEMA.clone(), true), + true, + )), + Arc::new(table_columns_array) as ArrayRef, + ), + ( + Arc::new(Field::new( + "table_constraints", + DataType::new_list(schemas::CONSTRAINT_SCHEMA.clone(), true), + true, + )), + Arc::new(table_constraints_array) as ArrayRef, + ), + ]); + + let db_schema_tables_array = ListArray::new( + Arc::new(Field::new("item", schemas::TABLE_SCHEMA.clone(), true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(db_schema_tables_array_inner), + None, + ); + + let catalog_db_schemas_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("db_schema_name", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["default"])) as ArrayRef, + ), + ( + Arc::new(Field::new_list( + "db_schema_tables", + Arc::new(Field::new("item", schemas::TABLE_SCHEMA.clone(), true)), + true, + )), + Arc::new(db_schema_tables_array) as ArrayRef, + ), + ]); + + let catalog_name_array = StringArray::from(vec!["default"]); + let catalog_db_schemas_array = ListArray::new( + Arc::new(Field::new( + "item", + schemas::OBJECTS_DB_SCHEMA_SCHEMA.clone(), + true, + )), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(catalog_db_schemas_array_inner), + None, + ); + + let batch = RecordBatch::try_new( + schemas::GET_OBJECTS_SCHEMA.clone(), + vec![ + Arc::new(catalog_name_array), + Arc::new(catalog_db_schemas_array), + ], + )?; + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn get_statistics( + &self, + _catalog: Option<&str>, + _db_schema: Option<&str>, + _table_name: Option<&str>, + _approximate: bool, + ) -> Result> { + let statistic_value_int64_array = Int64Array::from(Vec::::new()); + let statistic_value_uint64_array = UInt64Array::from(vec![42]); + let statistic_value_float64_array = Float64Array::from(Vec::::new()); + let statistic_value_binary_array = BinaryArray::from(Vec::<&[u8]>::new()); + let type_id_buffer = [1_i8].into_iter().collect::>(); + let value_offsets_buffer = [0_i32].into_iter().collect::>(); + let statistic_value_array = UnionArray::try_new( + UnionFields::try_new( + [0, 1, 2, 3], + [ + Field::new("int64", DataType::Int64, true), + Field::new("uint64", DataType::UInt64, true), + Field::new("float64", DataType::Float64, true), + Field::new("binary", DataType::Binary, true), + ], + ) + .expect("must be valid"), + type_id_buffer, + Some(value_offsets_buffer), + vec![ + Arc::new(statistic_value_int64_array), + Arc::new(statistic_value_uint64_array), + Arc::new(statistic_value_float64_array), + Arc::new(statistic_value_binary_array), + ], + )?; + + let db_schema_statistics_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("table_name", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["default"])) as ArrayRef, + ), + ( + Arc::new(Field::new("column_name", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["my_column"])) as ArrayRef, + ), + ( + Arc::new(Field::new("statistic_key", DataType::Int16, false)), + Arc::new(Int16Array::from(vec![Into::::into( + Statistics::AverageByteWidth, + )])) as ArrayRef, + ), + ( + Arc::new(Field::new( + "statistic_value", + schemas::STATISTIC_VALUE_SCHEMA.clone(), + false, + )), + Arc::new(statistic_value_array) as ArrayRef, + ), + ( + Arc::new(Field::new( + "statistic_is_approximate", + DataType::Boolean, + false, + )), + Arc::new(BooleanArray::from(vec![false])) as ArrayRef, + ), + ]); + + let db_schema_statistics_array = ListArray::new( + Arc::new(Field::new("item", schemas::STATISTICS_SCHEMA.clone(), true)), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(db_schema_statistics_array_inner), + None, + ); + + let catalog_db_schemas_array_inner = StructArray::from(vec![ + ( + Arc::new(Field::new("db_schema_name", DataType::Utf8, true)), + Arc::new(StringArray::from(vec!["default"])) as ArrayRef, + ), + ( + Arc::new(Field::new_list( + "db_schema_statistics", + Arc::new(Field::new("item", schemas::STATISTICS_SCHEMA.clone(), true)), + false, + )), + Arc::new(db_schema_statistics_array) as ArrayRef, + ), + ]); + + let catalog_name_array = StringArray::from(vec!["default"]); + let catalog_db_schemas_array = ListArray::new( + Arc::new(Field::new( + "item", + schemas::STATISTICS_DB_SCHEMA_SCHEMA.clone(), + true, + )), + OffsetBuffer::new(ScalarBuffer::from(vec![0, 1])), + Arc::new(catalog_db_schemas_array_inner), + None, + ); + + let batch = RecordBatch::try_new( + schemas::GET_STATISTICS_SCHEMA.clone(), + vec![ + Arc::new(catalog_name_array), + Arc::new(catalog_db_schemas_array), + ], + )?; + + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn get_statistic_names(&self) -> Result> { + let name_array = StringArray::from(vec!["sum", "min", "max"]); + let key_array = Int16Array::from(vec![0, 1, 2]); + let batch = RecordBatch::try_new( + schemas::GET_STATISTIC_NAMES_SCHEMA.clone(), + vec![Arc::new(name_array), Arc::new(key_array)], + )?; + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn get_table_schema( + &self, + catalog: Option<&str>, + db_schema: Option<&str>, + table_name: &str, + ) -> Result { + let catalog = catalog.unwrap_or("default"); + let db_schema = db_schema.unwrap_or("default"); + + if catalog == "default" && db_schema == "default" && table_name == "default" { + Ok(get_table_schema()) + } else { + Err(Error::with_message_and_status( + format!("Table {catalog}.{db_schema}.{table_name} does not exist"), + Status::NotFound, + )) + } + } + + fn get_table_types(&self) -> Result> { + let array = Arc::new(StringArray::from(vec!["table", "view"])); + let batch = RecordBatch::try_new(schemas::GET_TABLE_TYPES_SCHEMA.clone(), vec![array])?; + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn read_partition( + &self, + _partition: impl AsRef<[u8]>, + ) -> Result> { + let batch = get_table_data(); + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn rollback(&mut self) -> Result<()> { + Ok(()) + } +} + +#[derive(Default)] +pub struct DummyStatement { + options: HashMap, +} + +impl Optionable for DummyStatement { + type Option = OptionStatement; + + fn set_option(&mut self, key: Self::Option, value: OptionValue) -> Result<()> { + set_option(&mut self.options, key, value) + } + + fn get_option_bytes(&self, key: Self::Option) -> Result> { + get_option_bytes(&self.options, key, "statement") + } + + fn get_option_double(&self, key: Self::Option) -> Result { + get_option_double(&self.options, key, "statement") + } + + fn get_option_int(&self, key: Self::Option) -> Result { + get_option_int(&self.options, key, "statement") + } + + fn get_option_string(&self, key: Self::Option) -> Result { + get_option_string(&self.options, key, "statement") + } +} + +impl Statement for DummyStatement { + fn bind(&mut self, _batch: RecordBatch) -> Result<()> { + Ok(()) + } + + fn bind_stream(&mut self, _reader: Box) -> Result<()> { + Ok(()) + } + + fn cancel(&mut self) -> Result<()> { + Ok(()) + } + + fn execute(&mut self) -> Result> { + maybe_panic("StatementExecuteQuery"); + let batch = get_table_data(); + let reader = SingleBatchReader::new(batch); + Ok(Box::new(reader)) + } + + fn execute_partitions(&mut self) -> Result { + Ok(PartitionedResult { + partitions: vec![b"AAA".into(), b"ZZZZZ".into()], + schema: get_table_schema(), + rows_affected: 0, + }) + } + + fn execute_schema(&mut self) -> Result { + Ok(get_table_schema()) + } + + fn execute_update(&mut self) -> Result> { + Ok(Some(0)) + } + + fn get_parameter_schema(&self) -> Result { + Ok(get_table_schema()) + } + + fn prepare(&mut self) -> Result<()> { + Ok(()) + } + + fn set_sql_query(&mut self, _query: impl AsRef) -> Result<()> { + Ok(()) + } + + fn set_substrait_plan(&mut self, _plan: impl AsRef<[u8]>) -> Result<()> { + Ok(()) + } +} + +impl Drop for DummyStatement { + fn drop(&mut self) { + maybe_panic("StatementClose"); + } +} + +adbc_ffi::export_driver!(AdbcDummyInit, DummyDriver); diff --git a/tests/test_detect_version.py b/tests/test_detect_version.py index 2a85b95..9611663 100644 --- a/tests/test_detect_version.py +++ b/tests/test_detect_version.py @@ -61,6 +61,18 @@ def test_on_tag_subdir(repo): assert version == "v1.2.3" +def test_on_tag_worktree(repo): + subprocess.check_call(["git", "tag", "v1.2.3"], cwd=repo) + worktree = repo.parent / f"temp_{repo.name}_worktree" + subprocess.check_call( + ["git", "worktree", "add", "--quiet", "--detach", worktree], cwd=repo + ) + + assert (worktree / ".git").is_file() + version = detect_version(worktree) + assert version == "v1.2.3" + + def test_after_tag(repo): subprocess.check_call(["git", "tag", "v1.2.3"], cwd=repo) subprocess.check_call( diff --git a/tests/test_make.py b/tests/test_make.py new file mode 100644 index 0000000..43d9d0e --- /dev/null +++ b/tests/test_make.py @@ -0,0 +1,537 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import functools +import os +import platform +import subprocess +import sys +from pathlib import Path + +import pytest + +from adbc_drivers_dev.make_config import ( + LangGo, + LangRust, + LangScript, + MakeConfig, + MakeEnv, + merge_build_env, +) + + +@pytest.fixture(scope="session") +def rust_driver_root() -> tuple[Path, Path]: + repo_root = Path(__file__).parent.parent + rust_driver_root = repo_root / "tests" / "make" / "rustdummy" + return repo_root, rust_driver_root + + +@pytest.fixture(scope="session") +def go_driver_root() -> tuple[Path, Path]: + repo_root = Path(__file__).parent.parent + go_driver_root = repo_root / "tests" / "make" / "godummy" + return repo_root, go_driver_root + + +def debug_subprocess(func: callable) -> callable: + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except subprocess.CalledProcessError as e: + print( + ">>> STDOUT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", file=sys.stderr + ) + print(e.stdout, file=sys.stderr) + print( + ">>> STDERR >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", file=sys.stderr + ) + print(e.stderr, file=sys.stderr) + raise + + return wrapper + + +def test_build_config(rust_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = rust_driver_root + config = MakeEnv( + ci=False, + debug=False, + host_platform="linux", + host_architecture="amd64", + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + assert config.shared_library_affix == ("lib", ".so") + assert not config.use_docker + + config = MakeEnv( + ci=False, + debug=True, + host_platform="linux", + host_architecture="amd64", + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + assert not config.use_docker + + config = MakeEnv( + ci=False, + debug=True, + host_platform="macos", + host_architecture="arm64", + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + assert config.use_docker + + config = MakeEnv( + ci=False, + debug=True, + host_platform="macos", + host_architecture="arm64", + target_platform="macos", + target_architecture="arm64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + assert not config.use_docker + + config = MakeEnv( + ci=True, + debug=True, + host_platform="macos", + host_architecture="arm64", + target_platform="macos", + target_architecture="arm64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + assert not config.use_docker + + config = MakeEnv( + ci=True, + debug=False, + host_platform="linux", + host_architecture="amd64", + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + assert config.use_docker + + +def test_merge_build_env() -> None: + assert merge_build_env( + {"CGO_CFLAGS": "-O2", "OTHER": "old"}, + {"CGO_CFLAGS": "-mmacosx-version-min=11.0", "OTHER": "new"}, + ) == { + "CGO_CFLAGS": "-O2 -mmacosx-version-min=11.0", + "OTHER": "new", + } + assert merge_build_env( + {"CGO_LDFLAGS": ""}, {"CGO_LDFLAGS": "-mmacosx-version-min=11.0"} + ) == {"CGO_LDFLAGS": "-mmacosx-version-min=11.0"} + + +def test_go_linux_amd64(go_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = go_driver_root + config = MakeEnv( + ci=False, + debug=False, + host_platform="linux", + host_architecture="amd64", + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + make_config = MakeConfig( + driver="godummy", + lang=LangGo(lang="go", go_mod_path="module", build_tags=["custom_feature"]), + ) + + plan = make_config.build_plan(config) + assert plan.env_vars == {} + assert plan.commands == [ + [ + "go", + "-C", + "module", + "build", + "-buildmode=c-shared", + "-tags=driverlib,custom_feature", + "-ldflags=-w -X github.com/adbc-drivers/driverbase-go/driverbase.infoDriverVersion=0.1.0", + "-o", + "build/libadbc_driver_godummy.so", + "./pkg", + ] + ] + assert plan.pre_commands == [] + assert plan.artifact_path == ( + driver_root / "module" / "build" / "libadbc_driver_godummy.so" + ) + assert plan.target_path == driver_root / "build" / "libadbc_driver_godummy.so" + assert plan.cleanup_paths == [ + driver_root / "module" / "build" / "libadbc_driver_godummy.h" + ] + assert plan.docker_container is None + + config.debug = True + plan = make_config.build_plan(config) + assert "-tags=driverlib,assert,custom_feature" in plan.commands[0] + + +def test_go_linux_amd64_ci(go_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = go_driver_root + config = MakeEnv( + ci=True, + debug=False, + host_platform="linux", + host_architecture="amd64", + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + make_config = MakeConfig( + driver="godummy", lang=LangGo(lang="go", go_mod_path="module") + ) + + plan = make_config.build_plan(config) + assert plan.env_vars == {"GOWORK": "off"} + assert plan.pre_commands == [["go", "-C", "module", "mod", "vendor"]] + assert plan.commands == [ + [ + "go", + "-C", + "module", + "build", + "-buildmode=c-shared", + "-tags=driverlib", + "-ldflags=-w -X github.com/adbc-drivers/driverbase-go/driverbase.infoDriverVersion=0.1.0 -linkmode external -extldflags=-Wl,--version-script=/only-export-adbc.ld", + "-o", + "build/libadbc_driver_godummy.so", + "./pkg", + ] + ] + assert plan.docker_container == "manylinux" + + +def test_go_windows_amd64(go_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = go_driver_root + config = MakeEnv( + ci=False, + debug=False, + host_platform="windows", + host_architecture="amd64", + target_platform="windows", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + make_config = MakeConfig( + driver="godummy", lang=LangGo(lang="go", go_mod_path="module") + ) + + plan = make_config.build_plan(config) + assert "build/libadbc_driver_godummy.dll" in plan.commands[0] + assert plan.target_path == driver_root / "build" / "libadbc_driver_godummy.dll" + assert plan.docker_container is None + + +def test_rust_linux_amd64(rust_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = rust_driver_root + plat = "linux" + arch = "amd64" + config = MakeEnv( + ci=False, + debug=False, + host_platform=plat, + host_architecture=arch, + target_platform=plat, + target_architecture=arch, + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + + make_config = MakeConfig(driver="foobar", lang=LangRust(lang="rust", features=[])) + plan = make_config.build_plan(config) + assert plan.env_vars == {} + assert plan.commands == [["cargo", "build", "--release"]] + assert plan.artifact_path == driver_root / "target" / "release" / "libadbc_dummy.so" + assert plan.docker_container is None + + make_config = MakeConfig( + driver="foobar", lang=LangRust(lang="rust", features=["foobar"]) + ) + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--release", "--features", "foobar"]] + + config.debug = True + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--features", "foobar"]] + assert plan.docker_container is None + + config.debug = False + config.ci = True + plan = make_config.build_plan(config) + assert plan.docker_container == "manylinux-rust" + + +def test_rust_macos_arm64(rust_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = rust_driver_root + plat = "macos" + arch = "arm64" + config = MakeEnv( + ci=False, + debug=False, + host_platform=plat, + host_architecture=arch, + target_platform=plat, + target_architecture=arch, + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + + make_config = MakeConfig(driver="foobar", lang=LangRust(lang="rust", features=[])) + plan = make_config.build_plan(config) + assert plan.env_vars == { + "CGO_CFLAGS": "-mmacosx-version-min=11.0", + "CGO_LDFLAGS": "-mmacosx-version-min=11.0", + "MACOSX_DEPLOYMENT_TARGET": "11.0", + } + assert plan.commands == [["cargo", "build", "--release"]] + assert ( + plan.artifact_path == driver_root / "target" / "release" / "libadbc_dummy.dylib" + ) + assert plan.docker_container is None + + make_config = MakeConfig( + driver="foobar", lang=LangRust(lang="rust", features=["foobar"]) + ) + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--release", "--features", "foobar"]] + + config.debug = True + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--features", "foobar"]] + assert plan.docker_container is None + + +def test_rust_windows_amd64(rust_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = rust_driver_root + plat = "windows" + arch = "amd64" + config = MakeEnv( + ci=False, + debug=False, + host_platform=plat, + host_architecture=arch, + target_platform=plat, + target_architecture=arch, + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + + make_config = MakeConfig(driver="foobar", lang=LangRust(lang="rust", features=[])) + plan = make_config.build_plan(config) + assert plan.env_vars == {} + assert plan.commands == [["cargo", "build", "--release"]] + assert plan.artifact_path == driver_root / "target" / "release" / "adbc_dummy.dll" + assert plan.target_path == driver_root / "build" / "libadbc_driver_foobar.dll" + assert plan.docker_container is None + + make_config = MakeConfig( + driver="foobar", lang=LangRust(lang="rust", features=["foobar"]) + ) + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--release", "--features", "foobar"]] + + config.debug = True + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--features", "foobar"]] + assert plan.docker_container is None + + +def test_rust_cross_compile(rust_driver_root: tuple[Path, Path]) -> None: + # We only support xcompling from macOS to Linux + repo_root, driver_root = rust_driver_root + plat = "macos" + arch = "arm64" + config = MakeEnv( + ci=False, + debug=False, + host_platform=plat, + host_architecture=arch, + target_platform="linux", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + + make_config = MakeConfig(driver="foobar", lang=LangRust(lang="rust", features=[])) + plan = make_config.build_plan(config) + assert plan.env_vars == {} + assert plan.commands == [["cargo", "build", "--release"]] + assert plan.artifact_path == driver_root / "target" / "release" / "libadbc_dummy.so" + assert plan.docker_container == "manylinux-rust" + + make_config = MakeConfig( + driver="foobar", lang=LangRust(lang="rust", features=["foobar"]) + ) + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--release", "--features", "foobar"]] + + config.debug = True + plan = make_config.build_plan(config) + assert plan.commands == [["cargo", "build", "--features", "foobar"]] + assert plan.docker_container == "manylinux-rust" + + +def test_script_windows_amd64(rust_driver_root: tuple[Path, Path]) -> None: + repo_root, driver_root = rust_driver_root + config = MakeEnv( + ci=True, + debug=False, + host_platform="windows", + host_architecture="amd64", + target_platform="windows", + target_architecture="amd64", + repo_root=repo_root, + driver_root=driver_root, + version="0.1.0", + ) + + make_config = MakeConfig( + driver="foobar", lang=LangScript(lang="script", toolchain="cpp") + ) + plan = make_config.build_plan(config) + assert plan.env_vars == {} + assert plan.commands == [ + [ + r"C:\Program Files\Git\bin\bash.EXE", + "./ci/scripts/build.sh", + "release", + "windows", + "amd64", + ] + ] + assert plan.artifact_path is None + assert plan.target_path == driver_root / "build" / "libadbc_driver_foobar.dll" + assert plan.docker_container is None + + +@debug_subprocess +def test_go_actual_release(go_driver_root: tuple[Path, Path]) -> None: + _, driver_root = go_driver_root + env = os.environ.copy() + env.pop("CI", None) + result = subprocess.check_output( + ["adbc-make", "-a"], + cwd=driver_root, + text=True, + stderr=subprocess.STDOUT, + env=env, + ) + assert "* go -C module build" in result + assert "* docker" not in result + assert (driver_root / "build" / "libadbc_driver_godummy.so").is_file() + assert not (driver_root / "module" / "build" / "libadbc_driver_godummy.h").exists() + + +@debug_subprocess +def test_go_actual_release_ci(go_driver_root: tuple[Path, Path]) -> None: + _, driver_root = go_driver_root + result = subprocess.check_output( + ["adbc-make", "-a", "CI=true"], + cwd=driver_root, + text=True, + stderr=subprocess.STDOUT, + ) + assert "* go -C module mod vendor" in result + assert "* docker exec" in result + assert "-linkmode external" in result + assert (driver_root / "build" / "libadbc_driver_godummy.so").is_file() + assert not (driver_root / "module" / "build" / "libadbc_driver_godummy.h").exists() + + +@debug_subprocess +def test_rust_actual_debug(rust_driver_root: tuple[Path, Path]) -> None: + result = subprocess.check_output( + ["adbc-make", "-a", "DEBUG=true"], + cwd=rust_driver_root[1], + text=True, + stderr=subprocess.STDOUT, + ) + assert "Finished `dev` profile" in result + assert "* cargo build" in result + assert "* docker" not in result + + +@debug_subprocess +def test_rust_actual_release(rust_driver_root: tuple[Path, Path]) -> None: + env = os.environ.copy() + if "CI" in env: + del env["CI"] + result = subprocess.check_output( + ["adbc-make", "-a"], + cwd=rust_driver_root[1], + text=True, + stderr=subprocess.STDOUT, + env=env, + ) + assert "Finished `release` profile" in result + assert "* cargo build" in result + assert "* docker" not in result + + +@debug_subprocess +def test_rust_actual_release_ci(rust_driver_root: tuple[Path, Path]) -> None: + result = subprocess.check_output( + ["adbc-make", "-a", "CI=true"], + cwd=rust_driver_root[1], + text=True, + stderr=subprocess.STDOUT, + ) + print(result) + # TODO: force-tag and check version too + assert "Finished `release` profile" in result + if platform.system() == "Linux": + assert "* docker exec" in result + assert "-c env cargo build" in result + else: + assert "* docker exec" not in result + assert "* cargo build" in result diff --git a/tests/test_make_checks.py b/tests/test_make_checks.py new file mode 100644 index 0000000..650ab38 --- /dev/null +++ b/tests/test_make_checks.py @@ -0,0 +1,82 @@ +# Copyright (c) 2026 ADBC Drivers Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import Path + +import pytest + +from adbc_drivers_dev import make_checks + + +def test_check_linux_symbols_accepts_adbc_exports() -> None: + make_checks.check_linux_symbols( + [ + "000000 T AdbcDatabaseNew", + "000000 T AdbcConnectionInit", + " U external_symbol", + "000000 B _cgo_runtime", + ], + Path("driver.so"), + "manylinux2014", + ) + + +def test_check_linux_symbols_rejects_non_adbc_exports() -> None: + with pytest.raises(RuntimeError, match="bad_symbol"): + make_checks.check_linux_symbols( + ["000000 T AdbcDatabaseNew", "000000 T bad_symbol"], + Path("driver.so"), + "manylinux2014", + ) + + +def test_check_linux_symbols_enforces_manylinux_limits() -> None: + with pytest.raises(RuntimeError, match="GLIBC_2.18"): + make_checks.check_linux_symbols( + [" U function@GLIBC_2.18"], Path("driver.so"), "manylinux2014" + ) + + make_checks.check_linux_symbols( + [" U function@GLIBC_2.28", " U function@GLIBCXX_3.4.32"], + Path("driver.so"), + "manylinux_2_28", + ) + + +def test_check_linux_symbols_rejects_unknown_policy() -> None: + with pytest.raises(ValueError, match="Unsupported manylinux policy"): + make_checks.check_linux_symbols([], Path("driver.so"), "unknown") + + +def test_check_macos_rejects_new_deployment_target( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + make_checks.subprocess, + "check_output", + lambda *args, **kwargs: " minos 12.0\n", + ) + with pytest.raises(RuntimeError, match="macOS 12.0"): + make_checks._check_macos(Path("driver.dylib")) + + +def test_check_macos_accepts_supported_deployment_target( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + make_checks.subprocess, + "check_output", + lambda *args, **kwargs: " minos 11.0\n", + ) + make_checks._check_macos(Path("driver.dylib"))