diff --git a/mason.py b/mason.py index ba62a306c..c83474509 100644 --- a/mason.py +++ b/mason.py @@ -159,8 +159,8 @@ def get_args(): ) parser.add_argument( "--timeout", - type=str, - help="Timeout for the Beaker task (e.g., '2h', '30m', '1d'). If not specified, no timeout is set.", + type=int, + help="Timeout for the Beaker task in seconds (e.g., 7200 for 2 hours). If not specified, no timeout is set.", default=None, ) # Split up the mason args from the Python args. @@ -232,15 +232,15 @@ def get_env_vars( additional_env_var_names = {var["name"] for var in additional_env_vars} env_vars = [ - beaker.EnvVar(name=name, value=value) + beaker.BeakerEnvVar(name=name, value=value) for name, value in DEFAULT_ENV_VARS.items() if name not in additional_env_var_names ] - env_vars.extend([beaker.EnvVar(name=env_var["name"], value=env_var["value"]) for env_var in additional_env_vars]) + env_vars.extend([beaker.BeakerEnvVar(name=env_var["name"], value=env_var["value"]) for env_var in additional_env_vars]) # add user-specific secrets - env_vars.extend([beaker.EnvVar(name=secret["name"], secret=secret["value"]) for secret in additional_secrets]) + env_vars.extend([beaker.BeakerEnvVar(name=secret["name"], secret=secret["value"]) for secret in additional_secrets]) useful_secrets = [ "HF_TOKEN", @@ -254,22 +254,24 @@ def get_env_vars( ] for useful_secret in useful_secrets: if f"{whoami}_{useful_secret}" in beaker_secrets: - env_vars.append(beaker.EnvVar(name=useful_secret, secret=f"{whoami}_{useful_secret}")) + env_vars.append(beaker.BeakerEnvVar(name=useful_secret, secret=f"{whoami}_{useful_secret}")) elif useful_secret in beaker_secrets: - env_vars.append(beaker.EnvVar(name=useful_secret, secret=useful_secret)) + env_vars.append(beaker.BeakerEnvVar(name=useful_secret, secret=useful_secret)) # use the user's PATH; including the conda / python PATH if not pure_docker_mode: - env_vars.extend([beaker.EnvVar(name="PATH", value=os.getenv("PATH"))]) + env_vars.extend([beaker.BeakerEnvVar(name="PATH", value=os.getenv("PATH"))]) # if all cluster is in weka, we mount the weka if all(c in WEKA_CLUSTERS for c in cluster): env_vars.extend( [ - beaker.EnvVar(name="HF_HOME", value="/weka/oe-adapt-default/allennlp/.cache/huggingface"), - beaker.EnvVar(name="HF_DATASETS_CACHE", value="/weka/oe-adapt-default/allennlp/.cache/huggingface"), - beaker.EnvVar(name="HF_HUB_CACHE", value="/weka/oe-adapt-default/allennlp/.cache/hub"), - beaker.EnvVar( + beaker.BeakerEnvVar(name="HF_HOME", value="/weka/oe-adapt-default/allennlp/.cache/huggingface"), + beaker.BeakerEnvVar( + name="HF_DATASETS_CACHE", value="/weka/oe-adapt-default/allennlp/.cache/huggingface" + ), + beaker.BeakerEnvVar(name="HF_HUB_CACHE", value="/weka/oe-adapt-default/allennlp/.cache/hub"), + beaker.BeakerEnvVar( name="CHECKPOINT_OUTPUT_DIR", value=f"/weka/oe-adapt-default/allennlp/deletable_checkpoint_states/{global_wandb_id}", ), @@ -278,8 +280,8 @@ def get_env_vars( if num_nodes > 1: env_vars.extend( [ - beaker.EnvVar(name="NCCL_SOCKET_IFNAME", value="ib"), - beaker.EnvVar(name="NCCL_IB_HCA", value="^=mlx5_bond_0"), + beaker.BeakerEnvVar(name="NCCL_SOCKET_IFNAME", value="ib"), + beaker.BeakerEnvVar(name="NCCL_IB_HCA", value="^=mlx5_bond_0"), ] ) # if all cluster is in gcp we add the following env @@ -287,10 +289,10 @@ def get_env_vars( elif all(c in GCP_CLUSTERS for c in cluster): env_vars.extend( [ - beaker.EnvVar(name="HF_HOME", value="/filestore/.cache/huggingface"), - beaker.EnvVar(name="HF_DATASETS_CACHE", value="/filestore/.cache/huggingface"), - beaker.EnvVar(name="HF_HUB_CACHE", value="/filestore/.cache/hub"), - beaker.EnvVar( + beaker.BeakerEnvVar(name="HF_HOME", value="/filestore/.cache/huggingface"), + beaker.BeakerEnvVar(name="HF_DATASETS_CACHE", value="/filestore/.cache/huggingface"), + beaker.BeakerEnvVar(name="HF_HUB_CACHE", value="/filestore/.cache/hub"), + beaker.BeakerEnvVar( name="HF_HUB_ENABLE_HF_TRANSFER", value="0", # we disable it because GCP is weird on uploading to the hub ), @@ -299,40 +301,40 @@ def get_env_vars( if num_nodes > 1: env_vars.extend( [ - beaker.EnvVar(name="LD_LIBRARY_PATH", value=r"/var/lib/tcpxo/lib64:${LD_LIBRARY_PATH}"), - beaker.EnvVar(name="NCCL_CROSS_NIC", value="0"), - beaker.EnvVar(name="NCCL_ALGO", value="Ring,Tree"), - beaker.EnvVar(name="NCCL_PROTO", value="Simple"), - beaker.EnvVar(name="NCCL_MIN_NCHANNELS", value="4"), - beaker.EnvVar(name="NCCL_P2P_NET_CHUNKSIZE", value="524288"), - beaker.EnvVar(name="NCCL_P2P_PCI_CHUNKSIZE", value="524288"), - beaker.EnvVar(name="NCCL_P2P_NVL_CHUNKSIZE", value="1048576"), - beaker.EnvVar(name="NCCL_FASTRAK_NUM_FLOWS", value="2"), - beaker.EnvVar(name="NCCL_FASTRAK_ENABLE_CONTROL_CHANNEL", value="0"), - beaker.EnvVar(name="NCCL_BUFFSIZE", value="8388608"), - beaker.EnvVar(name="NCCL_FASTRAK_USE_SNAP", value="1"), - beaker.EnvVar(name="CUDA_VISIBLE_DEVICES", value="0,1,2,3,4,5,6,7"), - beaker.EnvVar(name="NCCL_NET_GDR_LEVEL", value="PIX"), - beaker.EnvVar(name="NCCL_FASTRAK_ENABLE_HOTPATH_LOGGING", value="0"), - beaker.EnvVar(name="NCCL_TUNER_PLUGIN", value="libnccl-tuner.so"), - beaker.EnvVar( + beaker.BeakerEnvVar(name="LD_LIBRARY_PATH", value=r"/var/lib/tcpxo/lib64:${LD_LIBRARY_PATH}"), + beaker.BeakerEnvVar(name="NCCL_CROSS_NIC", value="0"), + beaker.BeakerEnvVar(name="NCCL_ALGO", value="Ring,Tree"), + beaker.BeakerEnvVar(name="NCCL_PROTO", value="Simple"), + beaker.BeakerEnvVar(name="NCCL_MIN_NCHANNELS", value="4"), + beaker.BeakerEnvVar(name="NCCL_P2P_NET_CHUNKSIZE", value="524288"), + beaker.BeakerEnvVar(name="NCCL_P2P_PCI_CHUNKSIZE", value="524288"), + beaker.BeakerEnvVar(name="NCCL_P2P_NVL_CHUNKSIZE", value="1048576"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_NUM_FLOWS", value="2"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_ENABLE_CONTROL_CHANNEL", value="0"), + beaker.BeakerEnvVar(name="NCCL_BUFFSIZE", value="8388608"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_USE_SNAP", value="1"), + beaker.BeakerEnvVar(name="CUDA_VISIBLE_DEVICES", value="0,1,2,3,4,5,6,7"), + beaker.BeakerEnvVar(name="NCCL_NET_GDR_LEVEL", value="PIX"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_ENABLE_HOTPATH_LOGGING", value="0"), + beaker.BeakerEnvVar(name="NCCL_TUNER_PLUGIN", value="libnccl-tuner.so"), + beaker.BeakerEnvVar( name="NCCL_TUNER_CONFIG_PATH", value="/var/lib/tcpxo/lib64/a3plus_tuner_config.textproto" ), - beaker.EnvVar( + beaker.BeakerEnvVar( name="NCCL_SHIMNET_GUEST_CONFIG_CHECKER_CONFIG_FILE", value="/var/lib/tcpxo/lib64/a3plus_guest_config.textproto", ), - beaker.EnvVar(name="NCCL_FASTRAK_PLUGIN_ACCEPT_TIMEOUT_MS", value="600000"), - beaker.EnvVar(name="NCCL_NVLS_ENABLE", value="0"), - beaker.EnvVar(name="NCCL_FASTRAK_CTRL_DEV", value="enp0s12"), - beaker.EnvVar( + beaker.BeakerEnvVar(name="NCCL_FASTRAK_PLUGIN_ACCEPT_TIMEOUT_MS", value="600000"), + beaker.BeakerEnvVar(name="NCCL_NVLS_ENABLE", value="0"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_CTRL_DEV", value="enp0s12"), + beaker.BeakerEnvVar( name="NCCL_FASTRAK_IFNAME", value="enp6s0,enp7s0,enp13s0,enp14s0,enp134s0,enp135s0,enp141s0,enp142s0", ), - beaker.EnvVar(name="NCCL_SOCKET_IFNAME", value="enp0s12"), - beaker.EnvVar(name="NCCL_USE_SNAP", value="1"), - beaker.EnvVar(name="NCCL_FASTRAK_USE_LLCM", value="1"), - beaker.EnvVar(name="NCCL_FASTRAK_LLCM_DEVICE_DIRECTORY", value="/dev/aperture_devices"), + beaker.BeakerEnvVar(name="NCCL_SOCKET_IFNAME", value="enp0s12"), + beaker.BeakerEnvVar(name="NCCL_USE_SNAP", value="1"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_USE_LLCM", value="1"), + beaker.BeakerEnvVar(name="NCCL_FASTRAK_LLCM_DEVICE_DIRECTORY", value="/dev/aperture_devices"), ] ) # don't mount anything; assume no cache @@ -342,8 +344,8 @@ def get_env_vars( if resumable: env_vars.extend( [ - beaker.EnvVar(name="WANDB_RUN_ID", value=global_wandb_id), - beaker.EnvVar(name="WANDB_RESUME", value="allow"), + beaker.BeakerEnvVar(name="WANDB_RUN_ID", value=global_wandb_id), + beaker.BeakerEnvVar(name="WANDB_RESUME", value="allow"), ] ) @@ -356,16 +358,22 @@ def get_datasets(beaker_datasets, cluster: List[str]): # if all cluster is in weka, we mount the weka if all(c in WEKA_CLUSTERS for c in cluster): res = [ - beaker.DataMount(source=beaker.DataSource(weka="oe-adapt-default"), mount_path="/weka/oe-adapt-default"), - beaker.DataMount( - source=beaker.DataSource(weka="oe-training-default"), mount_path="/weka/oe-training-default" + beaker.BeakerDataMount( + source=beaker.BeakerDataSource(weka="oe-adapt-default"), mount_path="/weka/oe-adapt-default" + ), + beaker.BeakerDataMount( + source=beaker.BeakerDataSource(weka="oe-training-default"), mount_path="/weka/oe-training-default" ), ] elif all(c in GCP_CLUSTERS for c in cluster): - res = [beaker.DataMount(source=beaker.DataSource(host_path="/mnt/filestore_1"), mount_path="/filestore")] + res = [ + beaker.BeakerDataMount( + source=beaker.BeakerDataSource(host_path="/mnt/filestore_1"), mount_path="/filestore" + ) + ] for beaker_dataset in beaker_datasets: - to_append = beaker.DataMount( - source=beaker.DataSource(beaker=beaker_dataset["beaker"]), mount_path=beaker_dataset["mount_path"] + to_append = beaker.BeakerDataMount( + source=beaker.BeakerDataSource(beaker=beaker_dataset["beaker"]), mount_path=beaker_dataset["mount_path"] ) res.append(to_append) @@ -716,17 +724,19 @@ def make_task_spec(args, full_command: str, i: int, beaker_secrets: str, whoami: raise ValueError("GCP clusters do not have the dev filesystem, please use a proper image") if args.hostname is not None: - constraints = beaker.Constraints(hostname=args.hostname) + constraints = beaker.BeakerConstraints(hostname=args.hostname) else: - constraints = beaker.Constraints(cluster=args.cluster) - spec = beaker.TaskSpec( + constraints = beaker.BeakerConstraints(cluster=args.cluster) + spec = beaker.BeakerTaskSpec( name=f"{args.task_name}__{i}", - image=beaker.ImageSource(beaker=args.image), + image=beaker.BeakerImageSource(beaker=args.image), command=["/bin/bash", "-c"], arguments=[full_command], - result=beaker.ResultSpec(path="/output"), + result=beaker.BeakerResultSpec(path="/output"), datasets=get_datasets(args.beaker_datasets, args.cluster), - context=beaker.TaskContext(priority=beaker.Priority(args.priority), preemptible=args.preemptible), + context=beaker.BeakerTaskContext( + priority=beaker.BeakerJobPriority[args.priority], preemptible=args.preemptible + ), constraints=constraints, env_vars=get_env_vars( args.pure_docker_mode, @@ -738,7 +748,7 @@ def make_task_spec(args, full_command: str, i: int, beaker_secrets: str, whoami: args.env, args.secret, ), - resources=beaker.TaskResources(gpu_count=args.gpus, shared_memory=args.shared_memory), + resources=beaker.BeakerTaskResources(gpu_count=args.gpus, shared_memory=args.shared_memory), replicas=args.num_nodes, ) if args.num_nodes > 1: @@ -769,8 +779,8 @@ def main(): beaker_client = beaker.Beaker.from_env(default_workspace=args.workspace) else: beaker_client = beaker.Beaker.from_env() - beaker_secrets = [secret.name for secret in beaker_client.workspace.secrets()] - whoami = beaker_client.account.whoami().name + beaker_secrets = [secret.name for secret in beaker_client.secret.list()] + whoami = beaker_client.user.get().name full_commands = [make_internal_command(command, args, whoami, is_external_user) for command in commands] if is_external_user: @@ -789,17 +799,17 @@ def main(): console.print(Text(full_command)) if is_external_user: return - experiment_spec = beaker.ExperimentSpec( + experiment_spec = beaker.BeakerExperimentSpec( description=args.description, tasks=[ make_task_spec(args, full_command, i, beaker_secrets, whoami, args.resumable) for i, full_command in enumerate(full_commands) ], budget=args.budget, - retry=beaker.RetrySpec(allowed_task_retries=args.max_retries), + retry=beaker.BeakerRetrySpec(allowed_task_retries=args.max_retries), ) exp = beaker_client.experiment.create(spec=experiment_spec) - console.log(f"Kicked off Beaker job. https://beaker.org/ex/{exp.id}") + console.log(f"Kicked off Beaker job. https://beaker.org/ex/{exp.experiment.id}") if __name__ == "__main__": diff --git a/open_instruct/test_utils.py b/open_instruct/test_utils.py index 925a4c21a..5f72253c1 100644 --- a/open_instruct/test_utils.py +++ b/open_instruct/test_utils.py @@ -85,16 +85,22 @@ def _setup_beaker_mocks(mock_beaker_from_env, mock_is_beaker_job, initial_descri mock_client = mock.MagicMock() mock_beaker_from_env.return_value = mock_client + # Mock the workload object + mock_workload = mock.MagicMock() + mock_client.workload.get.return_value = mock_workload + + # Mock the spec object returned by experiment.get_spec mock_spec = mock.MagicMock() mock_spec.description = initial_description - mock_client.experiment.get.return_value = mock_spec + mock_client.experiment.get_spec.return_value = mock_spec description_history = [] - def track_description(exp_id, desc): - description_history.append(desc) + def track_description(workload, description=None): + if description is not None: + description_history.append(description) - mock_client.experiment.set_description.side_effect = track_description + mock_client.workload.update.side_effect = track_description return mock_client, mock_spec, description_history diff --git a/open_instruct/utils.py b/open_instruct/utils.py index be5d40099..39df68181 100644 --- a/open_instruct/utils.py +++ b/open_instruct/utils.py @@ -978,13 +978,16 @@ def maybe_update_beaker_description( try: client = beaker.Beaker.from_env() - except beaker.exceptions.ConfigurationError as e: + except beaker.exceptions.BeakerConfigurationError as e: logger.warning(f"Failed to initialize Beaker client: {e}") return try: - spec = client.experiment.get(experiment_id) - except beaker.exceptions.ExperimentNotFound: + # Get the workload first (experiment_id is actually BEAKER_WORKLOAD_ID) + workload = client.workload.get(experiment_id) + # Then get the experiment spec from the workload + spec = client.experiment.get_spec(workload) + except (beaker.exceptions.BeakerExperimentNotFound, ValueError): logger.warning( f"Failed to get Beaker experiment with ID: {experiment_id}" "This might be fine if you are e.g. running in an interactive job." @@ -1025,7 +1028,8 @@ def maybe_update_beaker_description( description_components.append(progress_bar) new_description = " ".join(description_components) try: - client.experiment.set_description(experiment_id, new_description) + # Update the workload description using the workload object we got earlier + client.workload.update(workload, description=new_description) except requests.exceptions.HTTPError as e: logger.warning( f"Failed to update Beaker description due to HTTP error: {e}" diff --git a/pyproject.toml b/pyproject.toml index 5ec2c83b3..a00784abd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,7 @@ link-mode = "hardlink" [dependency-groups] dev = [ - "beaker-py>=1.32.2,<2.0", + "beaker-py>=2.5.0", "mkdocs-material>=9.6.8", "markdown-include>=0.8.1", "pytest>=8.3.4", diff --git a/scripts/train/debug/finetune.sh b/scripts/train/debug/finetune.sh index e307055c1..7afb0ce5a 100755 --- a/scripts/train/debug/finetune.sh +++ b/scripts/train/debug/finetune.sh @@ -1,4 +1,6 @@ -uv run accelerate launch \ +#!/bin/bash + +LAUNCH_CMD="accelerate launch \ --mixed_precision bf16 \ --num_processes 1 \ open_instruct/finetune.py \ @@ -12,11 +14,34 @@ uv run accelerate launch \ --warmup_ratio 0.03 \ --weight_decay 0.0 \ --num_train_epochs 2 \ - --output_dir output/ \ --report_to wandb \ --logging_steps 1 \ --model_revision main \ --dataset_mixer_list allenai/tulu-3-sft-personas-algebra 100 \ --add_bos \ --seed 123 \ - # --with_tracking \ \ No newline at end of file + --chat_template_name tulu \ + --with_tracking" + +if [ -n "$1" ]; then + BEAKER_IMAGE="$1" + echo "Using Beaker image: $BEAKER_IMAGE" + + uv run python mason.py \ + --cluster ai2/jupiter \ + --workspace ai2/open-instruct-dev \ + --priority normal \ + --image "$BEAKER_IMAGE" \ + --description "Single GPU finetune job." \ + --pure_docker_mode \ + --preemptible \ + --num_nodes 1 \ + --budget ai2/oe-adapt \ + --gpus 1 \ + --non_resumable \ + -- \ + $LAUNCH_CMD +else + echo "Running locally..." + uv run $LAUNCH_CMD +fi diff --git a/scripts/train/debug/large_test_script.sh b/scripts/train/debug/large_test_script.sh index 383a7a9d4..7d5898d0c 100755 --- a/scripts/train/debug/large_test_script.sh +++ b/scripts/train/debug/large_test_script.sh @@ -13,7 +13,7 @@ uv run python mason.py \ --preemptible \ --num_nodes 2 \ --description "Large (multi-node) test script." \ - --timeout "1h" \ + --timeout 3600 \ --max_retries 0 \ --env VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \ --budget ai2/oe-adapt \ diff --git a/scripts/train/debug/single_gpu_on_beaker.sh b/scripts/train/debug/single_gpu_on_beaker.sh index 5265941f9..b643db650 100755 --- a/scripts/train/debug/single_gpu_on_beaker.sh +++ b/scripts/train/debug/single_gpu_on_beaker.sh @@ -17,7 +17,7 @@ uv run python mason.py \ --priority urgent \ --num_nodes 1 \ --max_retries 0 \ - --timeout "15m" \ + --timeout 900 \ --env VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \ --budget ai2/oe-adapt \ --gpus 1 \ diff --git a/scripts/train/debug/tool_grpo_fast.sh b/scripts/train/debug/tool_grpo_fast.sh index 7173290ae..69361d64f 100755 --- a/scripts/train/debug/tool_grpo_fast.sh +++ b/scripts/train/debug/tool_grpo_fast.sh @@ -21,7 +21,7 @@ uv run python mason.py \ --preemptible \ --num_nodes 1 \ --max_retries 0 \ - --timeout "45m" \ + --timeout 2700 \ --env VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \ --env GIT_COMMIT="$(git rev-parse --short HEAD)" \ --budget ai2/oe-adapt \ diff --git a/scripts/train/tulu3/finetune_8b.sh b/scripts/train/tulu3/finetune_8b.sh old mode 100644 new mode 100755 index 8a42076e2..f9a1131f1 --- a/scripts/train/tulu3/finetune_8b.sh +++ b/scripts/train/tulu3/finetune_8b.sh @@ -1,12 +1,21 @@ -python mason.py \ +#!/bin/bash + +BEAKER_IMAGE="${1:-nathanl/open_instruct_auto}" + +echo "Using Beaker image: $BEAKER_IMAGE" + +uv run python mason.py \ --cluster ai2/jupiter \ - --workspace ai2/tulu-3-dev \ - --priority high \ - --image nathanl/open_instruct_auto --pure_docker_mode \ + --workspace ai2/open-instruct-dev \ + --priority normal \ + --image "$BEAKER_IMAGE" \ + --pure_docker_mode \ --preemptible \ --num_nodes 8 \ --budget ai2/oe-adapt \ - --gpus 8 -- accelerate launch \ + --gpus 8 \ + -- \ + accelerate launch \ --mixed_precision bf16 \ --num_processes 8 \ --use_deepspeed \ @@ -19,7 +28,8 @@ python mason.py \ --tokenizer_name meta-llama/Llama-3.1-8B \ --tokenizer_revision main \ --use_slow_tokenizer \ - --dataset_mixer_list allenai/tulu-3-sft-mixture 1.0 \ + --chat_template tulu \ + --dataset_mixer_list allenai/tulu-3-sft-mixture 512 \ --max_seq_length 4096 \ --per_device_train_batch_size 1 \ --gradient_accumulation_steps 2 \ @@ -33,4 +43,4 @@ python mason.py \ --report_to wandb \ --with_tracking \ --logging_steps 1 \ - --seed 8 \ No newline at end of file + --seed 8 diff --git a/uv.lock b/uv.lock index e6c858c79..a4ea563e3 100644 --- a/uv.lock +++ b/uv.lock @@ -238,21 +238,19 @@ wheels = [ [[package]] name = "beaker-py" -version = "1.36.4" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docker" }, + { name = "google-crc32c" }, { name = "grpcio" }, { name = "packaging" }, { name = "protobuf" }, - { name = "pydantic" }, { name = "pyyaml" }, { name = "requests" }, - { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/05/10/526ccf25572e442844fb545bec273ebcfd1360e2a711f542610ac3222877/beaker_py-1.36.4.tar.gz", hash = "sha256:d958d702ff5ac6f4de4fa7c50db7e25a68cb68a2ab245a0f137adf6d2ba7d648", size = 118807, upload-time = "2025-07-16T22:30:46.998Z" } +sdist = { url = "https://files.pythonhosted.org/packages/84/6c/32a4254ceb98d01a403665a0636030ad65ea618f6737a804ac1a0b5db99a/beaker_py-2.5.0.tar.gz", hash = "sha256:346045705d6e434296db03b2a95b9440e2b20af8f095b07551bb774ce2fbf5a2", size = 91252, upload-time = "2025-08-20T19:00:11.007Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/e4/01a69c51892dc8af740dad911899b308de8462a1ba7cfc4061a850221ea9/beaker_py-1.36.4-py3-none-any.whl", hash = "sha256:b7370ceeb1ddeb631d4c2c2b3d5335a51d65117e6a38b03b7cf2ddfbbefd4520", size = 132650, upload-time = "2025-07-16T22:30:45.167Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f2/81b2c9f4e3f2d4d1c0f45ad7465d244de2739d4977b8a49a84e0be8d4baf/beaker_py-2.5.0-py3-none-any.whl", hash = "sha256:33f46ad795487beb8a433f8669a9f2513d04d40d394f28969dfea6e637c511a8", size = 102270, upload-time = "2025-08-20T19:00:09.436Z" }, ] [[package]] @@ -680,20 +678,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632, upload-time = "2024-10-05T20:14:57.687Z" }, ] -[[package]] -name = "docker" -version = "7.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pywin32", marker = "sys_platform == 'win32'" }, - { name = "requests" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, -] - [[package]] name = "docker-pycreds" version = "0.4.0" @@ -1017,6 +1001,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/12/ad37a1ef86006d0a0117fc06a4a00bd461c775356b534b425f00dde208ea/google_auth-2.39.0-py2.py3-none-any.whl", hash = "sha256:0150b6711e97fb9f52fe599f55648950cc4540015565d8fbb31be2ad6e1548a2", size = 212319, upload-time = "2025-04-14T17:44:47.699Z" }, ] +[[package]] +name = "google-crc32c" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/ae/87802e6d9f9d69adfaedfcfd599266bf386a54d0be058b532d04c794f76d/google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472", size = 14495, upload-time = "2025-03-26T14:29:13.32Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/69/b1b05cf415df0d86691d6a8b4b7e60ab3a6fb6efb783ee5cd3ed1382bfd3/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:b07d48faf8292b4db7c3d64ab86f950c2e94e93a11fd47271c28ba458e4a0d76", size = 30467, upload-time = "2025-03-26T14:31:11.92Z" }, + { url = "https://files.pythonhosted.org/packages/44/3d/92f8928ecd671bd5b071756596971c79d252d09b835cdca5a44177fa87aa/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7cc81b3a2fbd932a4313eb53cc7d9dde424088ca3a0337160f35d91826880c1d", size = 30311, upload-time = "2025-03-26T14:53:14.161Z" }, + { url = "https://files.pythonhosted.org/packages/33/42/c2d15a73df79d45ed6b430b9e801d0bd8e28ac139a9012d7d58af50a385d/google_crc32c-1.7.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c67ca0a1f5b56162951a9dae987988679a7db682d6f97ce0f6381ebf0fbea4c", size = 37889, upload-time = "2025-03-26T14:41:27.83Z" }, + { url = "https://files.pythonhosted.org/packages/57/ea/ac59c86a3c694afd117bb669bde32aaf17d0de4305d01d706495f09cbf19/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc5319db92daa516b653600794d5b9f9439a9a121f3e162f94b0e1891c7933cb", size = 33028, upload-time = "2025-03-26T14:41:29.141Z" }, + { url = "https://files.pythonhosted.org/packages/60/44/87e77e8476767a4a93f6cf271157c6d948eacec63688c093580af13b04be/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcdf5a64adb747610140572ed18d011896e3b9ae5195f2514b7ff678c80f1603", size = 38026, upload-time = "2025-03-26T14:41:29.921Z" }, + { url = "https://files.pythonhosted.org/packages/c8/bf/21ac7bb305cd7c1a6de9c52f71db0868e104a5b573a4977cd9d0ff830f82/google_crc32c-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:754561c6c66e89d55754106739e22fdaa93fafa8da7221b29c8b8e8270c6ec8a", size = 33476, upload-time = "2025-03-26T14:29:09.086Z" }, + { url = "https://files.pythonhosted.org/packages/f7/94/220139ea87822b6fdfdab4fb9ba81b3fff7ea2c82e2af34adc726085bffc/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6fbab4b935989e2c3610371963ba1b86afb09537fd0c633049be82afe153ac06", size = 30468, upload-time = "2025-03-26T14:32:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/94/97/789b23bdeeb9d15dc2904660463ad539d0318286d7633fe2760c10ed0c1c/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ed66cbe1ed9cbaaad9392b5259b3eba4a9e565420d734e6238813c428c3336c9", size = 30313, upload-time = "2025-03-26T14:57:38.758Z" }, + { url = "https://files.pythonhosted.org/packages/81/b8/976a2b843610c211e7ccb3e248996a61e87dbb2c09b1499847e295080aec/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6547b657621b6cbed3562ea7826c3e11cab01cd33b74e1f677690652883e77", size = 33048, upload-time = "2025-03-26T14:41:30.679Z" }, + { url = "https://files.pythonhosted.org/packages/c9/16/a3842c2cf591093b111d4a5e2bfb478ac6692d02f1b386d2a33283a19dc9/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68e17bad8f7dd9a49181a1f5a8f4b251c6dbc8cc96fb79f1d321dfd57d66f53", size = 32669, upload-time = "2025-03-26T14:41:31.432Z" }, + { url = "https://files.pythonhosted.org/packages/04/17/ed9aba495916fcf5fe4ecb2267ceb851fc5f273c4e4625ae453350cfd564/google_crc32c-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:6335de12921f06e1f774d0dd1fbea6bf610abe0887a1638f64d694013138be5d", size = 33476, upload-time = "2025-03-26T14:29:10.211Z" }, + { url = "https://files.pythonhosted.org/packages/dd/b7/787e2453cf8639c94b3d06c9d61f512234a82e1d12d13d18584bd3049904/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2d73a68a653c57281401871dd4aeebbb6af3191dcac751a76ce430df4d403194", size = 30470, upload-time = "2025-03-26T14:34:31.655Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b4/6042c2b0cbac3ec3a69bb4c49b28d2f517b7a0f4a0232603c42c58e22b44/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:22beacf83baaf59f9d3ab2bbb4db0fb018da8e5aebdce07ef9f09fce8220285e", size = 30315, upload-time = "2025-03-26T15:01:54.634Z" }, + { url = "https://files.pythonhosted.org/packages/29/ad/01e7a61a5d059bc57b702d9ff6a18b2585ad97f720bd0a0dbe215df1ab0e/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19eafa0e4af11b0a4eb3974483d55d2d77ad1911e6cf6f832e1574f6781fd337", size = 33180, upload-time = "2025-03-26T14:41:32.168Z" }, + { url = "https://files.pythonhosted.org/packages/3b/a5/7279055cf004561894ed3a7bfdf5bf90a53f28fadd01af7cd166e88ddf16/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d86616faaea68101195c6bdc40c494e4d76f41e07a37ffdef270879c15fb65", size = 32794, upload-time = "2025-03-26T14:41:33.264Z" }, + { url = "https://files.pythonhosted.org/packages/0f/d6/77060dbd140c624e42ae3ece3df53b9d811000729a5c821b9fd671ceaac6/google_crc32c-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:b7491bdc0c7564fcf48c0179d2048ab2f7c7ba36b84ccd3a3e1c3f7a72d3bba6", size = 33477, upload-time = "2025-03-26T14:29:10.94Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/31e57ce04530794917dfe25243860ec141de9fadf4aa9783dffe7dac7c39/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8e9afc74168b0b2232fb32dd202c93e46b7d5e4bf03e66ba5dc273bb3559589", size = 28242, upload-time = "2025-03-26T14:41:42.858Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f3/8b84cd4e0ad111e63e30eb89453f8dd308e3ad36f42305cf8c202461cdf0/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa8136cc14dd27f34a3221c0f16fd42d8a40e4778273e61a3c19aedaa44daf6b", size = 28049, upload-time = "2025-03-26T14:41:44.651Z" }, + { url = "https://files.pythonhosted.org/packages/16/1b/1693372bf423ada422f80fd88260dbfd140754adb15cbc4d7e9a68b1cb8e/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85fef7fae11494e747c9fd1359a527e5970fc9603c90764843caabd3a16a0a48", size = 28241, upload-time = "2025-03-26T14:41:45.898Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3c/2a19a60a473de48717b4efb19398c3f914795b64a96cf3fbe82588044f78/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6efb97eb4369d52593ad6f75e7e10d053cf00c48983f7a973105bc70b0ac4d82", size = 28048, upload-time = "2025-03-26T14:41:46.696Z" }, +] + [[package]] name = "googleapis-common-protos" version = "1.70.0" @@ -2267,7 +2279,7 @@ provides-extras = ["code"] [package.metadata.requires-dev] dev = [ - { name = "beaker-py", specifier = ">=1.32.2,<2.0" }, + { name = "beaker-py", specifier = ">=2.5.0" }, { name = "markdown-include", specifier = ">=0.8.1" }, { name = "mkdocs-material", specifier = ">=9.6.8" }, { name = "parameterized", specifier = ">=0.9.0" }, @@ -3091,22 +3103,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] -[[package]] -name = "pywin32" -version = "310" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/da/a5f38fffbba2fb99aa4aa905480ac4b8e83ca486659ac8c95bce47fb5276/pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1", size = 8848240, upload-time = "2025-03-17T00:55:46.783Z" }, - { url = "https://files.pythonhosted.org/packages/aa/fe/d873a773324fa565619ba555a82c9dabd677301720f3660a731a5d07e49a/pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d", size = 9601854, upload-time = "2025-03-17T00:55:48.783Z" }, - { url = "https://files.pythonhosted.org/packages/3c/84/1a8e3d7a15490d28a5d816efa229ecb4999cdc51a7c30dd8914f669093b8/pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213", size = 8522963, upload-time = "2025-03-17T00:55:50.969Z" }, - { url = "https://files.pythonhosted.org/packages/f7/b1/68aa2986129fb1011dabbe95f0136f44509afaf072b12b8f815905a39f33/pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd", size = 8784284, upload-time = "2025-03-17T00:55:53.124Z" }, - { url = "https://files.pythonhosted.org/packages/b3/bd/d1592635992dd8db5bb8ace0551bc3a769de1ac8850200cfa517e72739fb/pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c", size = 9520748, upload-time = "2025-03-17T00:55:55.203Z" }, - { url = "https://files.pythonhosted.org/packages/90/b1/ac8b1ffce6603849eb45a91cf126c0fa5431f186c2e768bf56889c46f51c/pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582", size = 8455941, upload-time = "2025-03-17T00:55:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ec/4fdbe47932f671d6e348474ea35ed94227fb5df56a7c30cbbb42cd396ed0/pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d", size = 8796239, upload-time = "2025-03-17T00:55:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/e3/e5/b0627f8bb84e06991bea89ad8153a9e50ace40b2e1195d68e9dff6b03d0f/pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060", size = 9503839, upload-time = "2025-03-17T00:56:00.8Z" }, - { url = "https://files.pythonhosted.org/packages/1f/32/9ccf53748df72301a89713936645a664ec001abd35ecc8578beda593d37d/pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966", size = 8459470, upload-time = "2025-03-17T00:56:02.601Z" }, -] - [[package]] name = "pyyaml" version = "6.0.2"