wandb 0.18.2__py3-none-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package_readme.md +89 -0
- wandb/__init__.py +245 -0
- wandb/__init__.pyi +1139 -0
- wandb/__main__.py +3 -0
- wandb/_globals.py +19 -0
- wandb/agents/__init__.py +0 -0
- wandb/agents/pyagent.py +363 -0
- wandb/analytics/__init__.py +3 -0
- wandb/analytics/sentry.py +266 -0
- wandb/apis/__init__.py +48 -0
- wandb/apis/attrs.py +40 -0
- wandb/apis/importers/__init__.py +1 -0
- wandb/apis/importers/internals/internal.py +385 -0
- wandb/apis/importers/internals/protocols.py +99 -0
- wandb/apis/importers/internals/util.py +78 -0
- wandb/apis/importers/mlflow.py +254 -0
- wandb/apis/importers/validation.py +108 -0
- wandb/apis/importers/wandb.py +1603 -0
- wandb/apis/internal.py +232 -0
- wandb/apis/normalize.py +89 -0
- wandb/apis/paginator.py +81 -0
- wandb/apis/public/__init__.py +34 -0
- wandb/apis/public/api.py +1305 -0
- wandb/apis/public/artifacts.py +1090 -0
- wandb/apis/public/const.py +4 -0
- wandb/apis/public/files.py +195 -0
- wandb/apis/public/history.py +149 -0
- wandb/apis/public/jobs.py +659 -0
- wandb/apis/public/projects.py +154 -0
- wandb/apis/public/query_generator.py +166 -0
- wandb/apis/public/reports.py +469 -0
- wandb/apis/public/runs.py +914 -0
- wandb/apis/public/sweeps.py +240 -0
- wandb/apis/public/teams.py +198 -0
- wandb/apis/public/users.py +136 -0
- wandb/apis/reports/__init__.py +1 -0
- wandb/apis/reports/v1/__init__.py +8 -0
- wandb/apis/reports/v2/__init__.py +8 -0
- wandb/apis/workspaces/__init__.py +8 -0
- wandb/beta/workflows.py +288 -0
- wandb/bin/nvidia_gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/__init__.py +0 -0
- wandb/cli/cli.py +3004 -0
- wandb/data_types.py +63 -0
- wandb/docker/__init__.py +342 -0
- wandb/docker/auth.py +436 -0
- wandb/docker/wandb-entrypoint.sh +33 -0
- wandb/docker/www_authenticate.py +94 -0
- wandb/env.py +514 -0
- wandb/errors/__init__.py +17 -0
- wandb/errors/errors.py +37 -0
- wandb/errors/term.py +103 -0
- wandb/errors/util.py +57 -0
- wandb/errors/warnings.py +2 -0
- wandb/filesync/__init__.py +0 -0
- wandb/filesync/dir_watcher.py +403 -0
- wandb/filesync/stats.py +100 -0
- wandb/filesync/step_checksum.py +142 -0
- wandb/filesync/step_prepare.py +179 -0
- wandb/filesync/step_upload.py +290 -0
- wandb/filesync/upload_job.py +142 -0
- wandb/integration/__init__.py +0 -0
- wandb/integration/catboost/__init__.py +5 -0
- wandb/integration/catboost/catboost.py +178 -0
- wandb/integration/cohere/__init__.py +3 -0
- wandb/integration/cohere/cohere.py +21 -0
- wandb/integration/cohere/resolver.py +347 -0
- wandb/integration/diffusers/__init__.py +3 -0
- wandb/integration/diffusers/autologger.py +76 -0
- wandb/integration/diffusers/pipeline_resolver.py +50 -0
- wandb/integration/diffusers/resolvers/__init__.py +9 -0
- wandb/integration/diffusers/resolvers/multimodal.py +882 -0
- wandb/integration/diffusers/resolvers/utils.py +102 -0
- wandb/integration/fastai/__init__.py +249 -0
- wandb/integration/gym/__init__.py +105 -0
- wandb/integration/huggingface/__init__.py +3 -0
- wandb/integration/huggingface/huggingface.py +18 -0
- wandb/integration/huggingface/resolver.py +213 -0
- wandb/integration/keras/__init__.py +11 -0
- wandb/integration/keras/callbacks/__init__.py +5 -0
- wandb/integration/keras/callbacks/metrics_logger.py +136 -0
- wandb/integration/keras/callbacks/model_checkpoint.py +195 -0
- wandb/integration/keras/callbacks/tables_builder.py +226 -0
- wandb/integration/keras/keras.py +1091 -0
- wandb/integration/kfp/__init__.py +6 -0
- wandb/integration/kfp/helpers.py +28 -0
- wandb/integration/kfp/kfp_patch.py +324 -0
- wandb/integration/kfp/wandb_logging.py +182 -0
- wandb/integration/langchain/__init__.py +3 -0
- wandb/integration/langchain/wandb_tracer.py +48 -0
- wandb/integration/lightgbm/__init__.py +239 -0
- wandb/integration/lightning/__init__.py +0 -0
- wandb/integration/lightning/fabric/__init__.py +3 -0
- wandb/integration/lightning/fabric/logger.py +762 -0
- wandb/integration/magic.py +556 -0
- wandb/integration/metaflow/__init__.py +3 -0
- wandb/integration/metaflow/metaflow.py +383 -0
- wandb/integration/openai/__init__.py +3 -0
- wandb/integration/openai/fine_tuning.py +480 -0
- wandb/integration/openai/openai.py +22 -0
- wandb/integration/openai/resolver.py +240 -0
- wandb/integration/prodigy/__init__.py +3 -0
- wandb/integration/prodigy/prodigy.py +299 -0
- wandb/integration/sacred/__init__.py +117 -0
- wandb/integration/sagemaker/__init__.py +12 -0
- wandb/integration/sagemaker/auth.py +28 -0
- wandb/integration/sagemaker/config.py +49 -0
- wandb/integration/sagemaker/files.py +3 -0
- wandb/integration/sagemaker/resources.py +34 -0
- wandb/integration/sb3/__init__.py +3 -0
- wandb/integration/sb3/sb3.py +153 -0
- wandb/integration/sklearn/__init__.py +37 -0
- wandb/integration/sklearn/calculate/__init__.py +32 -0
- wandb/integration/sklearn/calculate/calibration_curves.py +125 -0
- wandb/integration/sklearn/calculate/class_proportions.py +68 -0
- wandb/integration/sklearn/calculate/confusion_matrix.py +93 -0
- wandb/integration/sklearn/calculate/decision_boundaries.py +40 -0
- wandb/integration/sklearn/calculate/elbow_curve.py +55 -0
- wandb/integration/sklearn/calculate/feature_importances.py +67 -0
- wandb/integration/sklearn/calculate/learning_curve.py +64 -0
- wandb/integration/sklearn/calculate/outlier_candidates.py +69 -0
- wandb/integration/sklearn/calculate/residuals.py +86 -0
- wandb/integration/sklearn/calculate/silhouette.py +118 -0
- wandb/integration/sklearn/calculate/summary_metrics.py +62 -0
- wandb/integration/sklearn/plot/__init__.py +35 -0
- wandb/integration/sklearn/plot/classifier.py +329 -0
- wandb/integration/sklearn/plot/clusterer.py +146 -0
- wandb/integration/sklearn/plot/regressor.py +121 -0
- wandb/integration/sklearn/plot/shared.py +91 -0
- wandb/integration/sklearn/utils.py +183 -0
- wandb/integration/tensorboard/__init__.py +10 -0
- wandb/integration/tensorboard/log.py +355 -0
- wandb/integration/tensorboard/monkeypatch.py +185 -0
- wandb/integration/tensorflow/__init__.py +5 -0
- wandb/integration/tensorflow/estimator_hook.py +54 -0
- wandb/integration/torch/__init__.py +0 -0
- wandb/integration/torch/wandb_torch.py +554 -0
- wandb/integration/ultralytics/__init__.py +11 -0
- wandb/integration/ultralytics/bbox_utils.py +208 -0
- wandb/integration/ultralytics/callback.py +524 -0
- wandb/integration/ultralytics/classification_utils.py +83 -0
- wandb/integration/ultralytics/mask_utils.py +202 -0
- wandb/integration/ultralytics/pose_utils.py +103 -0
- wandb/integration/xgboost/__init__.py +11 -0
- wandb/integration/xgboost/xgboost.py +189 -0
- wandb/integration/yolov8/__init__.py +0 -0
- wandb/integration/yolov8/yolov8.py +284 -0
- wandb/jupyter.py +515 -0
- wandb/magic.py +3 -0
- wandb/mpmain/__init__.py +0 -0
- wandb/mpmain/__main__.py +1 -0
- wandb/old/__init__.py +0 -0
- wandb/old/core.py +53 -0
- wandb/old/settings.py +173 -0
- wandb/old/summary.py +440 -0
- wandb/plot/__init__.py +19 -0
- wandb/plot/bar.py +45 -0
- wandb/plot/confusion_matrix.py +100 -0
- wandb/plot/histogram.py +39 -0
- wandb/plot/line.py +43 -0
- wandb/plot/line_series.py +88 -0
- wandb/plot/pr_curve.py +136 -0
- wandb/plot/roc_curve.py +118 -0
- wandb/plot/scatter.py +32 -0
- wandb/plot/utils.py +183 -0
- wandb/plot/viz.py +123 -0
- wandb/proto/__init__.py +0 -0
- wandb/proto/v3/__init__.py +0 -0
- wandb/proto/v3/wandb_base_pb2.py +55 -0
- wandb/proto/v3/wandb_internal_pb2.py +1608 -0
- wandb/proto/v3/wandb_server_pb2.py +208 -0
- wandb/proto/v3/wandb_settings_pb2.py +112 -0
- wandb/proto/v3/wandb_telemetry_pb2.py +106 -0
- wandb/proto/v4/__init__.py +0 -0
- wandb/proto/v4/wandb_base_pb2.py +30 -0
- wandb/proto/v4/wandb_internal_pb2.py +360 -0
- wandb/proto/v4/wandb_server_pb2.py +63 -0
- wandb/proto/v4/wandb_settings_pb2.py +45 -0
- wandb/proto/v4/wandb_telemetry_pb2.py +41 -0
- wandb/proto/v5/wandb_base_pb2.py +31 -0
- wandb/proto/v5/wandb_internal_pb2.py +361 -0
- wandb/proto/v5/wandb_server_pb2.py +64 -0
- wandb/proto/v5/wandb_settings_pb2.py +46 -0
- wandb/proto/v5/wandb_telemetry_pb2.py +42 -0
- wandb/proto/wandb_base_pb2.py +10 -0
- wandb/proto/wandb_deprecated.py +53 -0
- wandb/proto/wandb_generate_deprecated.py +34 -0
- wandb/proto/wandb_generate_proto.py +49 -0
- wandb/proto/wandb_internal_pb2.py +16 -0
- wandb/proto/wandb_server_pb2.py +10 -0
- wandb/proto/wandb_settings_pb2.py +10 -0
- wandb/proto/wandb_telemetry_pb2.py +10 -0
- wandb/py.typed +0 -0
- wandb/sdk/__init__.py +37 -0
- wandb/sdk/artifacts/__init__.py +0 -0
- wandb/sdk/artifacts/_validators.py +90 -0
- wandb/sdk/artifacts/artifact.py +2389 -0
- wandb/sdk/artifacts/artifact_download_logger.py +43 -0
- wandb/sdk/artifacts/artifact_file_cache.py +253 -0
- wandb/sdk/artifacts/artifact_instance_cache.py +17 -0
- wandb/sdk/artifacts/artifact_manifest.py +74 -0
- wandb/sdk/artifacts/artifact_manifest_entry.py +249 -0
- wandb/sdk/artifacts/artifact_manifests/__init__.py +0 -0
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +92 -0
- wandb/sdk/artifacts/artifact_saver.py +269 -0
- wandb/sdk/artifacts/artifact_state.py +11 -0
- wandb/sdk/artifacts/artifact_ttl.py +7 -0
- wandb/sdk/artifacts/exceptions.py +57 -0
- wandb/sdk/artifacts/staging.py +25 -0
- wandb/sdk/artifacts/storage_handler.py +62 -0
- wandb/sdk/artifacts/storage_handlers/__init__.py +0 -0
- wandb/sdk/artifacts/storage_handlers/azure_handler.py +208 -0
- wandb/sdk/artifacts/storage_handlers/gcs_handler.py +228 -0
- wandb/sdk/artifacts/storage_handlers/http_handler.py +114 -0
- wandb/sdk/artifacts/storage_handlers/local_file_handler.py +141 -0
- wandb/sdk/artifacts/storage_handlers/multi_handler.py +56 -0
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +300 -0
- wandb/sdk/artifacts/storage_handlers/tracking_handler.py +72 -0
- wandb/sdk/artifacts/storage_handlers/wb_artifact_handler.py +135 -0
- wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +74 -0
- wandb/sdk/artifacts/storage_layout.py +6 -0
- wandb/sdk/artifacts/storage_policies/__init__.py +4 -0
- wandb/sdk/artifacts/storage_policies/register.py +1 -0
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +378 -0
- wandb/sdk/artifacts/storage_policy.py +72 -0
- wandb/sdk/backend/__init__.py +0 -0
- wandb/sdk/backend/backend.py +222 -0
- wandb/sdk/data_types/__init__.py +0 -0
- wandb/sdk/data_types/_dtypes.py +914 -0
- wandb/sdk/data_types/_private.py +10 -0
- wandb/sdk/data_types/audio.py +165 -0
- wandb/sdk/data_types/base_types/__init__.py +0 -0
- wandb/sdk/data_types/base_types/json_metadata.py +55 -0
- wandb/sdk/data_types/base_types/media.py +315 -0
- wandb/sdk/data_types/base_types/wb_value.py +272 -0
- wandb/sdk/data_types/bokeh.py +70 -0
- wandb/sdk/data_types/graph.py +405 -0
- wandb/sdk/data_types/helper_types/__init__.py +0 -0
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +295 -0
- wandb/sdk/data_types/helper_types/classes.py +159 -0
- wandb/sdk/data_types/helper_types/image_mask.py +235 -0
- wandb/sdk/data_types/histogram.py +96 -0
- wandb/sdk/data_types/html.py +115 -0
- wandb/sdk/data_types/image.py +845 -0
- wandb/sdk/data_types/molecule.py +241 -0
- wandb/sdk/data_types/object_3d.py +474 -0
- wandb/sdk/data_types/plotly.py +82 -0
- wandb/sdk/data_types/saved_model.py +446 -0
- wandb/sdk/data_types/table.py +1204 -0
- wandb/sdk/data_types/trace_tree.py +438 -0
- wandb/sdk/data_types/utils.py +229 -0
- wandb/sdk/data_types/video.py +247 -0
- wandb/sdk/integration_utils/__init__.py +0 -0
- wandb/sdk/integration_utils/auto_logging.py +239 -0
- wandb/sdk/integration_utils/data_logging.py +475 -0
- wandb/sdk/interface/__init__.py +0 -0
- wandb/sdk/interface/constants.py +4 -0
- wandb/sdk/interface/interface.py +972 -0
- wandb/sdk/interface/interface_queue.py +59 -0
- wandb/sdk/interface/interface_relay.py +53 -0
- wandb/sdk/interface/interface_shared.py +537 -0
- wandb/sdk/interface/interface_sock.py +61 -0
- wandb/sdk/interface/message_future.py +27 -0
- wandb/sdk/interface/message_future_poll.py +50 -0
- wandb/sdk/interface/router.py +118 -0
- wandb/sdk/interface/router_queue.py +44 -0
- wandb/sdk/interface/router_relay.py +39 -0
- wandb/sdk/interface/router_sock.py +36 -0
- wandb/sdk/interface/summary_record.py +67 -0
- wandb/sdk/internal/__init__.py +0 -0
- wandb/sdk/internal/context.py +89 -0
- wandb/sdk/internal/datastore.py +297 -0
- wandb/sdk/internal/file_pusher.py +181 -0
- wandb/sdk/internal/file_stream.py +695 -0
- wandb/sdk/internal/flow_control.py +263 -0
- wandb/sdk/internal/handler.py +901 -0
- wandb/sdk/internal/internal.py +417 -0
- wandb/sdk/internal/internal_api.py +4358 -0
- wandb/sdk/internal/internal_util.py +100 -0
- wandb/sdk/internal/job_builder.py +629 -0
- wandb/sdk/internal/profiler.py +78 -0
- wandb/sdk/internal/progress.py +83 -0
- wandb/sdk/internal/run.py +25 -0
- wandb/sdk/internal/sample.py +70 -0
- wandb/sdk/internal/sender.py +1686 -0
- wandb/sdk/internal/sender_config.py +197 -0
- wandb/sdk/internal/settings_static.py +90 -0
- wandb/sdk/internal/system/__init__.py +0 -0
- wandb/sdk/internal/system/assets/__init__.py +27 -0
- wandb/sdk/internal/system/assets/aggregators.py +37 -0
- wandb/sdk/internal/system/assets/asset_registry.py +20 -0
- wandb/sdk/internal/system/assets/cpu.py +163 -0
- wandb/sdk/internal/system/assets/disk.py +210 -0
- wandb/sdk/internal/system/assets/gpu.py +416 -0
- wandb/sdk/internal/system/assets/gpu_amd.py +239 -0
- wandb/sdk/internal/system/assets/gpu_apple.py +177 -0
- wandb/sdk/internal/system/assets/interfaces.py +207 -0
- wandb/sdk/internal/system/assets/ipu.py +177 -0
- wandb/sdk/internal/system/assets/memory.py +166 -0
- wandb/sdk/internal/system/assets/network.py +125 -0
- wandb/sdk/internal/system/assets/open_metrics.py +299 -0
- wandb/sdk/internal/system/assets/tpu.py +154 -0
- wandb/sdk/internal/system/assets/trainium.py +399 -0
- wandb/sdk/internal/system/env_probe_helpers.py +13 -0
- wandb/sdk/internal/system/system_info.py +249 -0
- wandb/sdk/internal/system/system_monitor.py +229 -0
- wandb/sdk/internal/tb_watcher.py +518 -0
- wandb/sdk/internal/thread_local_settings.py +18 -0
- wandb/sdk/internal/writer.py +206 -0
- wandb/sdk/launch/__init__.py +14 -0
- wandb/sdk/launch/_launch.py +330 -0
- wandb/sdk/launch/_launch_add.py +255 -0
- wandb/sdk/launch/_project_spec.py +566 -0
- wandb/sdk/launch/agent/__init__.py +5 -0
- wandb/sdk/launch/agent/agent.py +924 -0
- wandb/sdk/launch/agent/config.py +296 -0
- wandb/sdk/launch/agent/job_status_tracker.py +53 -0
- wandb/sdk/launch/agent/run_queue_item_file_saver.py +45 -0
- wandb/sdk/launch/builder/__init__.py +0 -0
- wandb/sdk/launch/builder/abstract.py +156 -0
- wandb/sdk/launch/builder/build.py +297 -0
- wandb/sdk/launch/builder/context_manager.py +235 -0
- wandb/sdk/launch/builder/docker_builder.py +177 -0
- wandb/sdk/launch/builder/kaniko_builder.py +595 -0
- wandb/sdk/launch/builder/noop.py +58 -0
- wandb/sdk/launch/builder/templates/_wandb_bootstrap.py +188 -0
- wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
- wandb/sdk/launch/create_job.py +528 -0
- wandb/sdk/launch/environment/abstract.py +29 -0
- wandb/sdk/launch/environment/aws_environment.py +322 -0
- wandb/sdk/launch/environment/azure_environment.py +105 -0
- wandb/sdk/launch/environment/gcp_environment.py +335 -0
- wandb/sdk/launch/environment/local_environment.py +66 -0
- wandb/sdk/launch/errors.py +19 -0
- wandb/sdk/launch/git_reference.py +109 -0
- wandb/sdk/launch/inputs/files.py +148 -0
- wandb/sdk/launch/inputs/internal.py +315 -0
- wandb/sdk/launch/inputs/manage.py +113 -0
- wandb/sdk/launch/inputs/schema.py +39 -0
- wandb/sdk/launch/loader.py +249 -0
- wandb/sdk/launch/registry/abstract.py +48 -0
- wandb/sdk/launch/registry/anon.py +29 -0
- wandb/sdk/launch/registry/azure_container_registry.py +124 -0
- wandb/sdk/launch/registry/elastic_container_registry.py +192 -0
- wandb/sdk/launch/registry/google_artifact_registry.py +219 -0
- wandb/sdk/launch/registry/local_registry.py +67 -0
- wandb/sdk/launch/runner/__init__.py +0 -0
- wandb/sdk/launch/runner/abstract.py +195 -0
- wandb/sdk/launch/runner/kubernetes_monitor.py +474 -0
- wandb/sdk/launch/runner/kubernetes_runner.py +963 -0
- wandb/sdk/launch/runner/local_container.py +301 -0
- wandb/sdk/launch/runner/local_process.py +78 -0
- wandb/sdk/launch/runner/sagemaker_runner.py +426 -0
- wandb/sdk/launch/runner/vertex_runner.py +230 -0
- wandb/sdk/launch/sweeps/__init__.py +39 -0
- wandb/sdk/launch/sweeps/scheduler.py +742 -0
- wandb/sdk/launch/sweeps/scheduler_sweep.py +91 -0
- wandb/sdk/launch/sweeps/utils.py +316 -0
- wandb/sdk/launch/utils.py +746 -0
- wandb/sdk/launch/wandb_reference.py +138 -0
- wandb/sdk/lib/__init__.py +5 -0
- wandb/sdk/lib/_settings_toposort_generate.py +159 -0
- wandb/sdk/lib/_settings_toposort_generated.py +250 -0
- wandb/sdk/lib/_wburls_generate.py +25 -0
- wandb/sdk/lib/_wburls_generated.py +22 -0
- wandb/sdk/lib/apikey.py +273 -0
- wandb/sdk/lib/capped_dict.py +26 -0
- wandb/sdk/lib/config_util.py +101 -0
- wandb/sdk/lib/credentials.py +141 -0
- wandb/sdk/lib/deprecate.py +42 -0
- wandb/sdk/lib/disabled.py +29 -0
- wandb/sdk/lib/exit_hooks.py +54 -0
- wandb/sdk/lib/file_stream_utils.py +118 -0
- wandb/sdk/lib/filenames.py +64 -0
- wandb/sdk/lib/filesystem.py +372 -0
- wandb/sdk/lib/fsm.py +174 -0
- wandb/sdk/lib/gitlib.py +239 -0
- wandb/sdk/lib/gql_request.py +65 -0
- wandb/sdk/lib/handler_util.py +21 -0
- wandb/sdk/lib/hashutil.py +84 -0
- wandb/sdk/lib/import_hooks.py +275 -0
- wandb/sdk/lib/ipython.py +146 -0
- wandb/sdk/lib/json_util.py +80 -0
- wandb/sdk/lib/lazyloader.py +63 -0
- wandb/sdk/lib/mailbox.py +460 -0
- wandb/sdk/lib/module.py +69 -0
- wandb/sdk/lib/paths.py +106 -0
- wandb/sdk/lib/preinit.py +42 -0
- wandb/sdk/lib/printer.py +313 -0
- wandb/sdk/lib/proto_util.py +90 -0
- wandb/sdk/lib/redirect.py +845 -0
- wandb/sdk/lib/reporting.py +99 -0
- wandb/sdk/lib/retry.py +289 -0
- wandb/sdk/lib/run_moment.py +78 -0
- wandb/sdk/lib/runid.py +12 -0
- wandb/sdk/lib/server.py +52 -0
- wandb/sdk/lib/service_connection.py +216 -0
- wandb/sdk/lib/service_token.py +94 -0
- wandb/sdk/lib/sock_client.py +295 -0
- wandb/sdk/lib/sparkline.py +45 -0
- wandb/sdk/lib/telemetry.py +100 -0
- wandb/sdk/lib/timed_input.py +133 -0
- wandb/sdk/lib/timer.py +19 -0
- wandb/sdk/lib/tracelog.py +255 -0
- wandb/sdk/lib/wburls.py +46 -0
- wandb/sdk/service/__init__.py +0 -0
- wandb/sdk/service/_startup_debug.py +22 -0
- wandb/sdk/service/port_file.py +53 -0
- wandb/sdk/service/server.py +116 -0
- wandb/sdk/service/server_sock.py +276 -0
- wandb/sdk/service/service.py +242 -0
- wandb/sdk/service/streams.py +417 -0
- wandb/sdk/verify/__init__.py +0 -0
- wandb/sdk/verify/verify.py +501 -0
- wandb/sdk/wandb_alerts.py +12 -0
- wandb/sdk/wandb_config.py +322 -0
- wandb/sdk/wandb_helper.py +54 -0
- wandb/sdk/wandb_init.py +1266 -0
- wandb/sdk/wandb_login.py +349 -0
- wandb/sdk/wandb_metric.py +110 -0
- wandb/sdk/wandb_require.py +97 -0
- wandb/sdk/wandb_require_helpers.py +44 -0
- wandb/sdk/wandb_run.py +4236 -0
- wandb/sdk/wandb_settings.py +2001 -0
- wandb/sdk/wandb_setup.py +409 -0
- wandb/sdk/wandb_summary.py +150 -0
- wandb/sdk/wandb_sweep.py +119 -0
- wandb/sdk/wandb_sync.py +81 -0
- wandb/sdk/wandb_watch.py +144 -0
- wandb/sklearn.py +35 -0
- wandb/sync/__init__.py +3 -0
- wandb/sync/sync.py +443 -0
- wandb/trigger.py +29 -0
- wandb/util.py +1956 -0
- wandb/vendor/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/setup.py +40 -0
- wandb/vendor/gql-0.2.0/tests/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/tests/starwars/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/tests/starwars/fixtures.py +96 -0
- wandb/vendor/gql-0.2.0/tests/starwars/schema.py +146 -0
- wandb/vendor/gql-0.2.0/tests/starwars/test_dsl.py +293 -0
- wandb/vendor/gql-0.2.0/tests/starwars/test_query.py +355 -0
- wandb/vendor/gql-0.2.0/tests/starwars/test_validation.py +171 -0
- wandb/vendor/gql-0.2.0/tests/test_client.py +31 -0
- wandb/vendor/gql-0.2.0/tests/test_transport.py +89 -0
- wandb/vendor/gql-0.2.0/wandb_gql/__init__.py +4 -0
- wandb/vendor/gql-0.2.0/wandb_gql/client.py +75 -0
- wandb/vendor/gql-0.2.0/wandb_gql/dsl.py +152 -0
- wandb/vendor/gql-0.2.0/wandb_gql/gql.py +10 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/http.py +6 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/local_schema.py +15 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/requests.py +46 -0
- wandb/vendor/gql-0.2.0/wandb_gql/utils.py +21 -0
- wandb/vendor/graphql-core-1.1/setup.py +86 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/__init__.py +287 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/__init__.py +6 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/base.py +42 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/format_error.py +11 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/located_error.py +29 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/syntax_error.py +36 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/__init__.py +26 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/base.py +311 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executor.py +398 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/asyncio.py +53 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/gevent.py +22 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/process.py +32 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/sync.py +7 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/thread.py +35 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/utils.py +6 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/executor.py +66 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/fragment.py +252 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/resolver.py +151 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/utils.py +7 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/middleware.py +57 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/values.py +145 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/graphql.py +60 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/ast.py +1349 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/base.py +19 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/lexer.py +435 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/location.py +30 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/parser.py +779 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/printer.py +193 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/source.py +18 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/visitor.py +222 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/visitor_meta.py +82 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/cached_property.py +17 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/contain_subset.py +28 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/default_ordered_dict.py +40 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/ordereddict.py +8 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/pair_set.py +43 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/version.py +78 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/__init__.py +67 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/definition.py +619 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/directives.py +132 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/introspection.py +440 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/scalars.py +131 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/schema.py +100 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/typemap.py +145 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/assert_valid_name.py +9 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/ast_from_value.py +65 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/ast_to_code.py +49 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/ast_to_dict.py +24 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/base.py +75 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/build_ast_schema.py +291 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/build_client_schema.py +250 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/concat_ast.py +9 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/extend_schema.py +357 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/get_field_def.py +27 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/get_operation_ast.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/introspection_query.py +90 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/is_valid_literal_value.py +67 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/is_valid_value.py +66 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/quoted_or_list.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/schema_printer.py +168 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/suggestion_list.py +56 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/type_comparators.py +69 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/type_from_ast.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/type_info.py +149 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/value_from_ast.py +69 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/__init__.py +4 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/__init__.py +79 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/arguments_of_correct_type.py +24 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/base.py +8 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/default_values_of_correct_type.py +44 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/fields_on_correct_type.py +113 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/fragments_on_composite_types.py +33 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_argument_names.py +70 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_directives.py +97 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_fragment_names.py +19 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_type_names.py +43 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/lone_anonymous_operation.py +23 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_fragment_cycles.py +59 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_undefined_variables.py +36 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_unused_fragments.py +38 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_unused_variables.py +37 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/overlapping_fields_can_be_merged.py +529 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/possible_fragment_spreads.py +44 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/provided_non_null_arguments.py +46 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/scalar_leafs.py +33 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_argument_names.py +32 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_fragment_names.py +28 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_input_field_names.py +33 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_operation_names.py +31 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_variable_names.py +27 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/variables_are_input_types.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/variables_in_allowed_position.py +53 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/validation.py +158 -0
- wandb/vendor/promise-2.3.0/conftest.py +30 -0
- wandb/vendor/promise-2.3.0/setup.py +64 -0
- wandb/vendor/promise-2.3.0/tests/__init__.py +0 -0
- wandb/vendor/promise-2.3.0/tests/conftest.py +8 -0
- wandb/vendor/promise-2.3.0/tests/test_awaitable.py +32 -0
- wandb/vendor/promise-2.3.0/tests/test_awaitable_35.py +47 -0
- wandb/vendor/promise-2.3.0/tests/test_benchmark.py +116 -0
- wandb/vendor/promise-2.3.0/tests/test_complex_threads.py +23 -0
- wandb/vendor/promise-2.3.0/tests/test_dataloader.py +452 -0
- wandb/vendor/promise-2.3.0/tests/test_dataloader_awaitable_35.py +99 -0
- wandb/vendor/promise-2.3.0/tests/test_dataloader_extra.py +65 -0
- wandb/vendor/promise-2.3.0/tests/test_extra.py +670 -0
- wandb/vendor/promise-2.3.0/tests/test_issues.py +132 -0
- wandb/vendor/promise-2.3.0/tests/test_promise_list.py +70 -0
- wandb/vendor/promise-2.3.0/tests/test_spec.py +584 -0
- wandb/vendor/promise-2.3.0/tests/test_thread_safety.py +115 -0
- wandb/vendor/promise-2.3.0/tests/utils.py +3 -0
- wandb/vendor/promise-2.3.0/wandb_promise/__init__.py +38 -0
- wandb/vendor/promise-2.3.0/wandb_promise/async_.py +135 -0
- wandb/vendor/promise-2.3.0/wandb_promise/compat.py +32 -0
- wandb/vendor/promise-2.3.0/wandb_promise/dataloader.py +326 -0
- wandb/vendor/promise-2.3.0/wandb_promise/iterate_promise.py +12 -0
- wandb/vendor/promise-2.3.0/wandb_promise/promise.py +848 -0
- wandb/vendor/promise-2.3.0/wandb_promise/promise_list.py +151 -0
- wandb/vendor/promise-2.3.0/wandb_promise/pyutils/__init__.py +0 -0
- wandb/vendor/promise-2.3.0/wandb_promise/pyutils/version.py +83 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/__init__.py +0 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/asyncio.py +22 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/gevent.py +21 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/immediate.py +27 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/thread.py +18 -0
- wandb/vendor/promise-2.3.0/wandb_promise/utils.py +56 -0
- wandb/vendor/pygments/__init__.py +90 -0
- wandb/vendor/pygments/cmdline.py +568 -0
- wandb/vendor/pygments/console.py +74 -0
- wandb/vendor/pygments/filter.py +74 -0
- wandb/vendor/pygments/filters/__init__.py +350 -0
- wandb/vendor/pygments/formatter.py +95 -0
- wandb/vendor/pygments/formatters/__init__.py +153 -0
- wandb/vendor/pygments/formatters/_mapping.py +85 -0
- wandb/vendor/pygments/formatters/bbcode.py +109 -0
- wandb/vendor/pygments/formatters/html.py +851 -0
- wandb/vendor/pygments/formatters/img.py +600 -0
- wandb/vendor/pygments/formatters/irc.py +182 -0
- wandb/vendor/pygments/formatters/latex.py +482 -0
- wandb/vendor/pygments/formatters/other.py +160 -0
- wandb/vendor/pygments/formatters/rtf.py +147 -0
- wandb/vendor/pygments/formatters/svg.py +153 -0
- wandb/vendor/pygments/formatters/terminal.py +136 -0
- wandb/vendor/pygments/formatters/terminal256.py +309 -0
- wandb/vendor/pygments/lexer.py +871 -0
- wandb/vendor/pygments/lexers/__init__.py +329 -0
- wandb/vendor/pygments/lexers/_asy_builtins.py +1645 -0
- wandb/vendor/pygments/lexers/_cl_builtins.py +232 -0
- wandb/vendor/pygments/lexers/_cocoa_builtins.py +72 -0
- wandb/vendor/pygments/lexers/_csound_builtins.py +1346 -0
- wandb/vendor/pygments/lexers/_lasso_builtins.py +5327 -0
- wandb/vendor/pygments/lexers/_lua_builtins.py +295 -0
- wandb/vendor/pygments/lexers/_mapping.py +500 -0
- wandb/vendor/pygments/lexers/_mql_builtins.py +1172 -0
- wandb/vendor/pygments/lexers/_openedge_builtins.py +2547 -0
- wandb/vendor/pygments/lexers/_php_builtins.py +4756 -0
- wandb/vendor/pygments/lexers/_postgres_builtins.py +621 -0
- wandb/vendor/pygments/lexers/_scilab_builtins.py +3094 -0
- wandb/vendor/pygments/lexers/_sourcemod_builtins.py +1163 -0
- wandb/vendor/pygments/lexers/_stan_builtins.py +532 -0
- wandb/vendor/pygments/lexers/_stata_builtins.py +419 -0
- wandb/vendor/pygments/lexers/_tsql_builtins.py +1004 -0
- wandb/vendor/pygments/lexers/_vim_builtins.py +1939 -0
- wandb/vendor/pygments/lexers/actionscript.py +240 -0
- wandb/vendor/pygments/lexers/agile.py +24 -0
- wandb/vendor/pygments/lexers/algebra.py +221 -0
- wandb/vendor/pygments/lexers/ambient.py +76 -0
- wandb/vendor/pygments/lexers/ampl.py +87 -0
- wandb/vendor/pygments/lexers/apl.py +101 -0
- wandb/vendor/pygments/lexers/archetype.py +318 -0
- wandb/vendor/pygments/lexers/asm.py +641 -0
- wandb/vendor/pygments/lexers/automation.py +374 -0
- wandb/vendor/pygments/lexers/basic.py +500 -0
- wandb/vendor/pygments/lexers/bibtex.py +160 -0
- wandb/vendor/pygments/lexers/business.py +612 -0
- wandb/vendor/pygments/lexers/c_cpp.py +252 -0
- wandb/vendor/pygments/lexers/c_like.py +541 -0
- wandb/vendor/pygments/lexers/capnproto.py +78 -0
- wandb/vendor/pygments/lexers/chapel.py +102 -0
- wandb/vendor/pygments/lexers/clean.py +288 -0
- wandb/vendor/pygments/lexers/compiled.py +34 -0
- wandb/vendor/pygments/lexers/configs.py +833 -0
- wandb/vendor/pygments/lexers/console.py +114 -0
- wandb/vendor/pygments/lexers/crystal.py +393 -0
- wandb/vendor/pygments/lexers/csound.py +366 -0
- wandb/vendor/pygments/lexers/css.py +689 -0
- wandb/vendor/pygments/lexers/d.py +251 -0
- wandb/vendor/pygments/lexers/dalvik.py +125 -0
- wandb/vendor/pygments/lexers/data.py +555 -0
- wandb/vendor/pygments/lexers/diff.py +165 -0
- wandb/vendor/pygments/lexers/dotnet.py +691 -0
- wandb/vendor/pygments/lexers/dsls.py +878 -0
- wandb/vendor/pygments/lexers/dylan.py +289 -0
- wandb/vendor/pygments/lexers/ecl.py +125 -0
- wandb/vendor/pygments/lexers/eiffel.py +65 -0
- wandb/vendor/pygments/lexers/elm.py +121 -0
- wandb/vendor/pygments/lexers/erlang.py +533 -0
- wandb/vendor/pygments/lexers/esoteric.py +277 -0
- wandb/vendor/pygments/lexers/ezhil.py +69 -0
- wandb/vendor/pygments/lexers/factor.py +344 -0
- wandb/vendor/pygments/lexers/fantom.py +250 -0
- wandb/vendor/pygments/lexers/felix.py +273 -0
- wandb/vendor/pygments/lexers/forth.py +177 -0
- wandb/vendor/pygments/lexers/fortran.py +205 -0
- wandb/vendor/pygments/lexers/foxpro.py +428 -0
- wandb/vendor/pygments/lexers/functional.py +21 -0
- wandb/vendor/pygments/lexers/go.py +101 -0
- wandb/vendor/pygments/lexers/grammar_notation.py +213 -0
- wandb/vendor/pygments/lexers/graph.py +80 -0
- wandb/vendor/pygments/lexers/graphics.py +553 -0
- wandb/vendor/pygments/lexers/haskell.py +843 -0
- wandb/vendor/pygments/lexers/haxe.py +936 -0
- wandb/vendor/pygments/lexers/hdl.py +382 -0
- wandb/vendor/pygments/lexers/hexdump.py +103 -0
- wandb/vendor/pygments/lexers/html.py +602 -0
- wandb/vendor/pygments/lexers/idl.py +270 -0
- wandb/vendor/pygments/lexers/igor.py +288 -0
- wandb/vendor/pygments/lexers/inferno.py +96 -0
- wandb/vendor/pygments/lexers/installers.py +322 -0
- wandb/vendor/pygments/lexers/int_fiction.py +1343 -0
- wandb/vendor/pygments/lexers/iolang.py +63 -0
- wandb/vendor/pygments/lexers/j.py +146 -0
- wandb/vendor/pygments/lexers/javascript.py +1525 -0
- wandb/vendor/pygments/lexers/julia.py +333 -0
- wandb/vendor/pygments/lexers/jvm.py +1573 -0
- wandb/vendor/pygments/lexers/lisp.py +2621 -0
- wandb/vendor/pygments/lexers/make.py +202 -0
- wandb/vendor/pygments/lexers/markup.py +595 -0
- wandb/vendor/pygments/lexers/math.py +21 -0
- wandb/vendor/pygments/lexers/matlab.py +663 -0
- wandb/vendor/pygments/lexers/ml.py +769 -0
- wandb/vendor/pygments/lexers/modeling.py +358 -0
- wandb/vendor/pygments/lexers/modula2.py +1561 -0
- wandb/vendor/pygments/lexers/monte.py +204 -0
- wandb/vendor/pygments/lexers/ncl.py +894 -0
- wandb/vendor/pygments/lexers/nimrod.py +159 -0
- wandb/vendor/pygments/lexers/nit.py +64 -0
- wandb/vendor/pygments/lexers/nix.py +136 -0
- wandb/vendor/pygments/lexers/oberon.py +105 -0
- wandb/vendor/pygments/lexers/objective.py +504 -0
- wandb/vendor/pygments/lexers/ooc.py +85 -0
- wandb/vendor/pygments/lexers/other.py +41 -0
- wandb/vendor/pygments/lexers/parasail.py +79 -0
- wandb/vendor/pygments/lexers/parsers.py +835 -0
- wandb/vendor/pygments/lexers/pascal.py +644 -0
- wandb/vendor/pygments/lexers/pawn.py +199 -0
- wandb/vendor/pygments/lexers/perl.py +620 -0
- wandb/vendor/pygments/lexers/php.py +267 -0
- wandb/vendor/pygments/lexers/praat.py +294 -0
- wandb/vendor/pygments/lexers/prolog.py +306 -0
- wandb/vendor/pygments/lexers/python.py +939 -0
- wandb/vendor/pygments/lexers/qvt.py +152 -0
- wandb/vendor/pygments/lexers/r.py +453 -0
- wandb/vendor/pygments/lexers/rdf.py +270 -0
- wandb/vendor/pygments/lexers/rebol.py +431 -0
- wandb/vendor/pygments/lexers/resource.py +85 -0
- wandb/vendor/pygments/lexers/rnc.py +67 -0
- wandb/vendor/pygments/lexers/roboconf.py +82 -0
- wandb/vendor/pygments/lexers/robotframework.py +560 -0
- wandb/vendor/pygments/lexers/ruby.py +519 -0
- wandb/vendor/pygments/lexers/rust.py +220 -0
- wandb/vendor/pygments/lexers/sas.py +228 -0
- wandb/vendor/pygments/lexers/scripting.py +1222 -0
- wandb/vendor/pygments/lexers/shell.py +794 -0
- wandb/vendor/pygments/lexers/smalltalk.py +195 -0
- wandb/vendor/pygments/lexers/smv.py +79 -0
- wandb/vendor/pygments/lexers/snobol.py +83 -0
- wandb/vendor/pygments/lexers/special.py +103 -0
- wandb/vendor/pygments/lexers/sql.py +681 -0
- wandb/vendor/pygments/lexers/stata.py +108 -0
- wandb/vendor/pygments/lexers/supercollider.py +90 -0
- wandb/vendor/pygments/lexers/tcl.py +145 -0
- wandb/vendor/pygments/lexers/templates.py +2283 -0
- wandb/vendor/pygments/lexers/testing.py +207 -0
- wandb/vendor/pygments/lexers/text.py +25 -0
- wandb/vendor/pygments/lexers/textedit.py +169 -0
- wandb/vendor/pygments/lexers/textfmts.py +297 -0
- wandb/vendor/pygments/lexers/theorem.py +458 -0
- wandb/vendor/pygments/lexers/trafficscript.py +54 -0
- wandb/vendor/pygments/lexers/typoscript.py +226 -0
- wandb/vendor/pygments/lexers/urbi.py +133 -0
- wandb/vendor/pygments/lexers/varnish.py +190 -0
- wandb/vendor/pygments/lexers/verification.py +111 -0
- wandb/vendor/pygments/lexers/web.py +24 -0
- wandb/vendor/pygments/lexers/webmisc.py +988 -0
- wandb/vendor/pygments/lexers/whiley.py +116 -0
- wandb/vendor/pygments/lexers/x10.py +69 -0
- wandb/vendor/pygments/modeline.py +44 -0
- wandb/vendor/pygments/plugin.py +68 -0
- wandb/vendor/pygments/regexopt.py +92 -0
- wandb/vendor/pygments/scanner.py +105 -0
- wandb/vendor/pygments/sphinxext.py +158 -0
- wandb/vendor/pygments/style.py +155 -0
- wandb/vendor/pygments/styles/__init__.py +80 -0
- wandb/vendor/pygments/styles/abap.py +29 -0
- wandb/vendor/pygments/styles/algol.py +63 -0
- wandb/vendor/pygments/styles/algol_nu.py +63 -0
- wandb/vendor/pygments/styles/arduino.py +98 -0
- wandb/vendor/pygments/styles/autumn.py +65 -0
- wandb/vendor/pygments/styles/borland.py +51 -0
- wandb/vendor/pygments/styles/bw.py +49 -0
- wandb/vendor/pygments/styles/colorful.py +81 -0
- wandb/vendor/pygments/styles/default.py +73 -0
- wandb/vendor/pygments/styles/emacs.py +72 -0
- wandb/vendor/pygments/styles/friendly.py +72 -0
- wandb/vendor/pygments/styles/fruity.py +42 -0
- wandb/vendor/pygments/styles/igor.py +29 -0
- wandb/vendor/pygments/styles/lovelace.py +97 -0
- wandb/vendor/pygments/styles/manni.py +75 -0
- wandb/vendor/pygments/styles/monokai.py +106 -0
- wandb/vendor/pygments/styles/murphy.py +80 -0
- wandb/vendor/pygments/styles/native.py +65 -0
- wandb/vendor/pygments/styles/paraiso_dark.py +125 -0
- wandb/vendor/pygments/styles/paraiso_light.py +125 -0
- wandb/vendor/pygments/styles/pastie.py +75 -0
- wandb/vendor/pygments/styles/perldoc.py +69 -0
- wandb/vendor/pygments/styles/rainbow_dash.py +89 -0
- wandb/vendor/pygments/styles/rrt.py +33 -0
- wandb/vendor/pygments/styles/sas.py +44 -0
- wandb/vendor/pygments/styles/stata.py +40 -0
- wandb/vendor/pygments/styles/tango.py +141 -0
- wandb/vendor/pygments/styles/trac.py +63 -0
- wandb/vendor/pygments/styles/vim.py +63 -0
- wandb/vendor/pygments/styles/vs.py +38 -0
- wandb/vendor/pygments/styles/xcode.py +51 -0
- wandb/vendor/pygments/token.py +213 -0
- wandb/vendor/pygments/unistring.py +217 -0
- wandb/vendor/pygments/util.py +388 -0
- wandb/vendor/pynvml/__init__.py +0 -0
- wandb/vendor/pynvml/pynvml.py +4779 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/__init__.py +17 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/events.py +615 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/__init__.py +98 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/api.py +369 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/fsevents.py +172 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/fsevents2.py +239 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/inotify.py +218 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/inotify_buffer.py +81 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/inotify_c.py +575 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/kqueue.py +730 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/polling.py +145 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/read_directory_changes.py +133 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/winapi.py +348 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/patterns.py +265 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/tricks/__init__.py +174 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/__init__.py +151 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/bricks.py +249 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/compat.py +29 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/decorators.py +198 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/delayed_queue.py +88 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/dirsnapshot.py +293 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/echo.py +157 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/event_backport.py +41 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/importlib2.py +40 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/platform.py +57 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/unicode_paths.py +64 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/win32stat.py +123 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/version.py +28 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/watchmedo.py +577 -0
- wandb/wandb_agent.py +588 -0
- wandb/wandb_controller.py +721 -0
- wandb/wandb_run.py +9 -0
- wandb-0.18.2.dist-info/METADATA +213 -0
- wandb-0.18.2.dist-info/RECORD +827 -0
- wandb-0.18.2.dist-info/WHEEL +5 -0
- wandb-0.18.2.dist-info/entry_points.txt +3 -0
- wandb-0.18.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,2001 @@
|
|
1
|
+
import collections.abc
|
2
|
+
import configparser
|
3
|
+
import enum
|
4
|
+
import getpass
|
5
|
+
import json
|
6
|
+
import logging
|
7
|
+
import multiprocessing
|
8
|
+
import os
|
9
|
+
import platform
|
10
|
+
import re
|
11
|
+
import shutil
|
12
|
+
import socket
|
13
|
+
import sys
|
14
|
+
import tempfile
|
15
|
+
import time
|
16
|
+
from dataclasses import dataclass
|
17
|
+
from datetime import datetime
|
18
|
+
from distutils.util import strtobool
|
19
|
+
from functools import reduce
|
20
|
+
from typing import (
|
21
|
+
Any,
|
22
|
+
Callable,
|
23
|
+
Dict,
|
24
|
+
FrozenSet,
|
25
|
+
ItemsView,
|
26
|
+
Iterable,
|
27
|
+
Mapping,
|
28
|
+
Optional,
|
29
|
+
Sequence,
|
30
|
+
Set,
|
31
|
+
Tuple,
|
32
|
+
Union,
|
33
|
+
no_type_check,
|
34
|
+
)
|
35
|
+
from urllib.parse import quote, unquote, urlencode, urlparse, urlsplit
|
36
|
+
|
37
|
+
from google.protobuf.wrappers_pb2 import BoolValue, DoubleValue, Int32Value, StringValue
|
38
|
+
|
39
|
+
import wandb
|
40
|
+
import wandb.env
|
41
|
+
from wandb import util
|
42
|
+
from wandb.apis.internal import Api
|
43
|
+
from wandb.errors import UsageError
|
44
|
+
from wandb.proto import wandb_settings_pb2
|
45
|
+
from wandb.sdk.internal.system.env_probe_helpers import is_aws_lambda
|
46
|
+
from wandb.sdk.lib import credentials, filesystem
|
47
|
+
from wandb.sdk.lib._settings_toposort_generated import SETTINGS_TOPOLOGICALLY_SORTED
|
48
|
+
from wandb.sdk.lib.run_moment import RunMoment
|
49
|
+
from wandb.sdk.wandb_setup import _EarlyLogger
|
50
|
+
|
51
|
+
from .lib import apikey
|
52
|
+
from .lib.gitlib import GitRepo
|
53
|
+
from .lib.ipython import _get_python_type
|
54
|
+
from .lib.runid import generate_id
|
55
|
+
|
56
|
+
if sys.version_info >= (3, 8):
|
57
|
+
from typing import get_args, get_origin, get_type_hints
|
58
|
+
else:
|
59
|
+
from typing_extensions import get_args, get_origin, get_type_hints
|
60
|
+
|
61
|
+
|
62
|
+
class SettingsPreprocessingError(UsageError):
|
63
|
+
"""Raised when the value supplied to a wandb.Settings() setting does not pass preprocessing."""
|
64
|
+
|
65
|
+
|
66
|
+
class SettingsValidationError(UsageError):
|
67
|
+
"""Raised when the value supplied to a wandb.Settings() setting does not pass validation."""
|
68
|
+
|
69
|
+
|
70
|
+
class SettingsUnexpectedArgsError(UsageError):
|
71
|
+
"""Raised when unexpected arguments are passed to wandb.Settings()."""
|
72
|
+
|
73
|
+
|
74
|
+
def _get_wandb_dir(root_dir: str) -> str:
|
75
|
+
"""Get the full path to the wandb directory.
|
76
|
+
|
77
|
+
The setting exposed to users as `dir=` or `WANDB_DIR` is the `root_dir`.
|
78
|
+
We add the `__stage_dir__` to it to get the full `wandb_dir`
|
79
|
+
"""
|
80
|
+
# We use the hidden version if it already exists, otherwise non-hidden.
|
81
|
+
if os.path.exists(os.path.join(root_dir, ".wandb")):
|
82
|
+
__stage_dir__ = ".wandb" + os.sep
|
83
|
+
else:
|
84
|
+
__stage_dir__ = "wandb" + os.sep
|
85
|
+
|
86
|
+
path = os.path.join(root_dir, __stage_dir__)
|
87
|
+
if not os.access(root_dir or ".", os.W_OK):
|
88
|
+
wandb.termwarn(
|
89
|
+
f"Path {path} wasn't writable, using system temp directory.",
|
90
|
+
repeat=False,
|
91
|
+
)
|
92
|
+
path = os.path.join(tempfile.gettempdir(), __stage_dir__ or ("wandb" + os.sep))
|
93
|
+
|
94
|
+
return os.path.expanduser(path)
|
95
|
+
|
96
|
+
|
97
|
+
def _str_as_bool(val: Union[str, bool]) -> bool:
|
98
|
+
"""Parse a string as a bool."""
|
99
|
+
if isinstance(val, bool):
|
100
|
+
return val
|
101
|
+
try:
|
102
|
+
ret_val = bool(strtobool(str(val)))
|
103
|
+
return ret_val
|
104
|
+
except (AttributeError, ValueError):
|
105
|
+
pass
|
106
|
+
|
107
|
+
raise UsageError(f"Could not parse value {val} as a bool.")
|
108
|
+
|
109
|
+
|
110
|
+
def _str_as_json(val: Union[str, Dict[str, Any]]) -> Any:
|
111
|
+
"""Parse a string as a json object."""
|
112
|
+
if not isinstance(val, str):
|
113
|
+
return val
|
114
|
+
try:
|
115
|
+
return json.loads(val)
|
116
|
+
except (AttributeError, ValueError):
|
117
|
+
pass
|
118
|
+
|
119
|
+
raise UsageError(f"Could not parse value {val} as JSON.")
|
120
|
+
|
121
|
+
|
122
|
+
def _str_as_tuple(val: Union[str, Sequence[str]]) -> Tuple[str, ...]:
|
123
|
+
"""Parse a (potentially comma-separated) string as a tuple."""
|
124
|
+
if isinstance(val, str):
|
125
|
+
return tuple(val.split(","))
|
126
|
+
return tuple(val)
|
127
|
+
|
128
|
+
|
129
|
+
def _datetime_as_str(val: Union[datetime, str]) -> str:
|
130
|
+
"""Parse a datetime object as a string."""
|
131
|
+
if isinstance(val, datetime):
|
132
|
+
return datetime.strftime(val, "%Y%m%d_%H%M%S")
|
133
|
+
return val
|
134
|
+
|
135
|
+
|
136
|
+
def _redact_dict(
|
137
|
+
d: Dict[str, Any],
|
138
|
+
unsafe_keys: Union[Set[str], FrozenSet[str]] = frozenset({"api_key"}),
|
139
|
+
redact_str: str = "***REDACTED***",
|
140
|
+
) -> Dict[str, Any]:
|
141
|
+
"""Redact a dict of unsafe values specified by their key."""
|
142
|
+
if not d or unsafe_keys.isdisjoint(d):
|
143
|
+
return d
|
144
|
+
safe_dict = d.copy()
|
145
|
+
safe_dict.update({k: redact_str for k in unsafe_keys.intersection(d)})
|
146
|
+
return safe_dict
|
147
|
+
|
148
|
+
|
149
|
+
def _get_program() -> Optional[str]:
|
150
|
+
program = os.getenv(wandb.env.PROGRAM)
|
151
|
+
if program is not None:
|
152
|
+
return program
|
153
|
+
try:
|
154
|
+
import __main__
|
155
|
+
|
156
|
+
if __main__.__spec__ is None:
|
157
|
+
return __main__.__file__
|
158
|
+
# likely run as `python -m ...`
|
159
|
+
return f"-m {__main__.__spec__.name}"
|
160
|
+
except (ImportError, AttributeError):
|
161
|
+
return None
|
162
|
+
|
163
|
+
|
164
|
+
def _runmoment_preprocessor(val: Any) -> Optional[RunMoment]:
|
165
|
+
if isinstance(val, RunMoment) or val is None:
|
166
|
+
return val
|
167
|
+
elif isinstance(val, str):
|
168
|
+
return RunMoment.from_uri(val)
|
169
|
+
raise UsageError(f"Could not parse value {val} as a RunMoment.")
|
170
|
+
|
171
|
+
|
172
|
+
def _get_program_relpath(
|
173
|
+
program: str, root: Optional[str] = None, _logger: Optional[_EarlyLogger] = None
|
174
|
+
) -> Optional[str]:
|
175
|
+
if not program:
|
176
|
+
if _logger is not None:
|
177
|
+
_logger.warning("Empty program passed to get_program_relpath")
|
178
|
+
return None
|
179
|
+
|
180
|
+
root = root or os.getcwd()
|
181
|
+
if not root:
|
182
|
+
return None
|
183
|
+
|
184
|
+
full_path_to_program = os.path.join(
|
185
|
+
root, os.path.relpath(os.getcwd(), root), program
|
186
|
+
)
|
187
|
+
if os.path.exists(full_path_to_program):
|
188
|
+
relative_path = os.path.relpath(full_path_to_program, start=root)
|
189
|
+
if "../" in relative_path:
|
190
|
+
if _logger is not None:
|
191
|
+
_logger.warning(f"Could not save program above cwd: {program}")
|
192
|
+
return None
|
193
|
+
return relative_path
|
194
|
+
|
195
|
+
if _logger is not None:
|
196
|
+
_logger.warning(f"Could not find program at {program}")
|
197
|
+
return None
|
198
|
+
|
199
|
+
|
200
|
+
def is_instance_recursive(obj: Any, type_hint: Any) -> bool: # noqa: C901
|
201
|
+
if type_hint is Any:
|
202
|
+
return True
|
203
|
+
|
204
|
+
origin = get_origin(type_hint)
|
205
|
+
args = get_args(type_hint)
|
206
|
+
|
207
|
+
if origin is None:
|
208
|
+
return isinstance(obj, type_hint)
|
209
|
+
|
210
|
+
if origin is Union:
|
211
|
+
return any(is_instance_recursive(obj, arg) for arg in args)
|
212
|
+
|
213
|
+
if issubclass(origin, collections.abc.Mapping):
|
214
|
+
if not isinstance(obj, collections.abc.Mapping):
|
215
|
+
return False
|
216
|
+
key_type, value_type = args
|
217
|
+
|
218
|
+
for key, value in obj.items():
|
219
|
+
if not is_instance_recursive(key, key_type) or not is_instance_recursive(
|
220
|
+
value, value_type
|
221
|
+
):
|
222
|
+
return False
|
223
|
+
|
224
|
+
return True
|
225
|
+
|
226
|
+
if issubclass(origin, collections.abc.Sequence):
|
227
|
+
if not isinstance(obj, collections.abc.Sequence) or isinstance(
|
228
|
+
obj, (str, bytes, bytearray)
|
229
|
+
):
|
230
|
+
return False
|
231
|
+
|
232
|
+
if len(args) == 1 and args[0] != ...:
|
233
|
+
(item_type,) = args
|
234
|
+
for item in obj:
|
235
|
+
if not is_instance_recursive(item, item_type):
|
236
|
+
return False
|
237
|
+
elif len(args) == 2 and args[-1] == ...:
|
238
|
+
item_type = args[0]
|
239
|
+
for item in obj:
|
240
|
+
if not is_instance_recursive(item, item_type):
|
241
|
+
return False
|
242
|
+
elif len(args) == len(obj):
|
243
|
+
for item, item_type in zip(obj, args):
|
244
|
+
if not is_instance_recursive(item, item_type):
|
245
|
+
return False
|
246
|
+
else:
|
247
|
+
return False
|
248
|
+
|
249
|
+
return True
|
250
|
+
|
251
|
+
if issubclass(origin, collections.abc.Set):
|
252
|
+
if not isinstance(obj, collections.abc.Set):
|
253
|
+
return False
|
254
|
+
|
255
|
+
(item_type,) = args
|
256
|
+
for item in obj:
|
257
|
+
if not is_instance_recursive(item, item_type):
|
258
|
+
return False
|
259
|
+
|
260
|
+
return True
|
261
|
+
|
262
|
+
return False
|
263
|
+
|
264
|
+
|
265
|
+
@enum.unique
|
266
|
+
class Source(enum.IntEnum):
|
267
|
+
OVERRIDE: int = 0
|
268
|
+
BASE: int = 1 # todo: audit this
|
269
|
+
ORG: int = 2
|
270
|
+
ENTITY: int = 3
|
271
|
+
PROJECT: int = 4
|
272
|
+
USER: int = 5
|
273
|
+
SYSTEM: int = 6
|
274
|
+
WORKSPACE: int = 7
|
275
|
+
ENV: int = 8
|
276
|
+
SETUP: int = 9
|
277
|
+
LOGIN: int = 10
|
278
|
+
INIT: int = 11
|
279
|
+
SETTINGS: int = 12
|
280
|
+
ARGS: int = 13
|
281
|
+
RUN: int = 14
|
282
|
+
|
283
|
+
|
284
|
+
ConsoleValue = {
|
285
|
+
"auto",
|
286
|
+
"off",
|
287
|
+
"wrap",
|
288
|
+
"redirect",
|
289
|
+
# internal console states
|
290
|
+
"wrap_raw",
|
291
|
+
"wrap_emu",
|
292
|
+
}
|
293
|
+
|
294
|
+
|
295
|
+
@dataclass()
|
296
|
+
class SettingsData:
|
297
|
+
"""Settings for the W&B SDK."""
|
298
|
+
|
299
|
+
_args: Sequence[str]
|
300
|
+
_aws_lambda: bool
|
301
|
+
_cli_only_mode: bool # Avoid running any code specific for runs
|
302
|
+
_code_path_local: str
|
303
|
+
_colab: bool
|
304
|
+
# _config_dict: Config
|
305
|
+
_cuda: str
|
306
|
+
_disable_meta: bool # Do not collect system metadata
|
307
|
+
_disable_service: (
|
308
|
+
bool # Disable wandb-service, spin up internal process the old way
|
309
|
+
)
|
310
|
+
_disable_setproctitle: bool # Do not use setproctitle on internal process
|
311
|
+
_disable_stats: bool # Do not collect system metrics
|
312
|
+
_disable_update_check: bool # Disable version check
|
313
|
+
_disable_viewer: bool # Prevent early viewer query
|
314
|
+
_disable_machine_info: bool # Disable automatic machine info collection
|
315
|
+
_executable: str
|
316
|
+
_extra_http_headers: Mapping[str, str]
|
317
|
+
_file_stream_max_bytes: int # max size for filestream requests in core
|
318
|
+
_file_stream_transmit_interval: float # tx interval for filestream requests in core
|
319
|
+
# file stream retry client configuration
|
320
|
+
_file_stream_retry_max: int # max number of retries
|
321
|
+
_file_stream_retry_wait_min_seconds: float # min wait time between retries
|
322
|
+
_file_stream_retry_wait_max_seconds: float # max wait time between retries
|
323
|
+
_file_stream_timeout_seconds: float # timeout for individual HTTP requests
|
324
|
+
# file transfer retry client configuration
|
325
|
+
_file_transfer_retry_max: int
|
326
|
+
_file_transfer_retry_wait_min_seconds: float
|
327
|
+
_file_transfer_retry_wait_max_seconds: float
|
328
|
+
_file_transfer_timeout_seconds: float
|
329
|
+
_flow_control_custom: bool
|
330
|
+
_flow_control_disabled: bool
|
331
|
+
# graphql retry client configuration
|
332
|
+
_graphql_retry_max: int
|
333
|
+
_graphql_retry_wait_min_seconds: float
|
334
|
+
_graphql_retry_wait_max_seconds: float
|
335
|
+
_graphql_timeout_seconds: float
|
336
|
+
_internal_check_process: float
|
337
|
+
_internal_queue_timeout: float
|
338
|
+
_ipython: bool
|
339
|
+
_jupyter: bool
|
340
|
+
_jupyter_name: str
|
341
|
+
_jupyter_path: str
|
342
|
+
_jupyter_root: str
|
343
|
+
_kaggle: bool
|
344
|
+
_live_policy_rate_limit: int
|
345
|
+
_live_policy_wait_time: int
|
346
|
+
_log_level: int
|
347
|
+
_network_buffer: int
|
348
|
+
_noop: bool
|
349
|
+
_notebook: bool
|
350
|
+
_offline: bool
|
351
|
+
_sync: bool
|
352
|
+
_os: str
|
353
|
+
_platform: str
|
354
|
+
_proxies: Mapping[
|
355
|
+
str, str
|
356
|
+
] # custom proxy servers for the requests to W&B [scheme -> url]
|
357
|
+
_python: str
|
358
|
+
_runqueue_item_id: str
|
359
|
+
_require_legacy_service: bool
|
360
|
+
_save_requirements: bool
|
361
|
+
_service_transport: str
|
362
|
+
_service_wait: float
|
363
|
+
_shared: bool
|
364
|
+
_start_datetime: str
|
365
|
+
_start_time: float
|
366
|
+
_stats_pid: int # (internal) base pid for system stats
|
367
|
+
_stats_sampling_interval: float # sampling interval for system stats
|
368
|
+
_stats_sample_rate_seconds: float # badly-named sampling interval, deprecated
|
369
|
+
_stats_samples_to_average: (
|
370
|
+
int # number of samples to average before reporting, deprecated
|
371
|
+
)
|
372
|
+
_stats_join_assets: (
|
373
|
+
bool # join metrics from different assets before sending to backend
|
374
|
+
)
|
375
|
+
_stats_neuron_monitor_config_path: (
|
376
|
+
str # path to place config file for neuron-monitor (AWS Trainium)
|
377
|
+
)
|
378
|
+
_stats_open_metrics_endpoints: Mapping[str, str] # open metrics endpoint names/urls
|
379
|
+
# open metrics filters in one of the two formats:
|
380
|
+
# - {"metric regex pattern, including endpoint name as prefix": {"label": "label value regex pattern"}}
|
381
|
+
# - ("metric regex pattern 1", "metric regex pattern 2", ...)
|
382
|
+
_stats_open_metrics_filters: Union[Sequence[str], Mapping[str, Mapping[str, str]]]
|
383
|
+
_stats_disk_paths: Sequence[str] # paths to monitor disk usage
|
384
|
+
_stats_buffer_size: int # number of consolidated samples to buffer before flushing, available in run obj
|
385
|
+
_tmp_code_dir: str
|
386
|
+
_tracelog: str
|
387
|
+
_unsaved_keys: Sequence[str]
|
388
|
+
_windows: bool
|
389
|
+
allow_val_change: bool
|
390
|
+
anonymous: str
|
391
|
+
api_key: str
|
392
|
+
azure_account_url_to_access_key: Dict[str, str]
|
393
|
+
base_url: str # The base url for the wandb api
|
394
|
+
code_dir: str
|
395
|
+
colab_url: str
|
396
|
+
config_paths: Sequence[str]
|
397
|
+
console: str
|
398
|
+
console_multipart: bool # whether to produce multipart console log files
|
399
|
+
credentials_file: str # file path to write access tokens
|
400
|
+
deployment: str
|
401
|
+
disable_code: bool
|
402
|
+
disable_git: bool
|
403
|
+
disable_hints: bool
|
404
|
+
disable_job_creation: bool
|
405
|
+
disabled: bool # Alias for mode=dryrun, not supported yet
|
406
|
+
docker: str
|
407
|
+
email: str
|
408
|
+
entity: str
|
409
|
+
files_dir: str
|
410
|
+
force: bool
|
411
|
+
fork_from: RunMoment
|
412
|
+
resume_from: RunMoment
|
413
|
+
git_commit: str
|
414
|
+
git_remote: str
|
415
|
+
git_remote_url: str
|
416
|
+
git_root: str
|
417
|
+
heartbeat_seconds: int
|
418
|
+
host: str
|
419
|
+
http_proxy: str # proxy server for the http requests to W&B
|
420
|
+
https_proxy: str # proxy server for the https requests to W&B
|
421
|
+
identity_token_file: str # file path to supply a jwt for authentication
|
422
|
+
ignore_globs: Tuple[str]
|
423
|
+
init_timeout: float
|
424
|
+
is_local: bool
|
425
|
+
job_name: str
|
426
|
+
job_source: str
|
427
|
+
label_disable: bool
|
428
|
+
launch: bool
|
429
|
+
launch_config_path: str
|
430
|
+
log_dir: str
|
431
|
+
log_internal: str
|
432
|
+
log_symlink_internal: str
|
433
|
+
log_symlink_user: str
|
434
|
+
log_user: str
|
435
|
+
login_timeout: float
|
436
|
+
# magic: Union[str, bool, dict] # never used in code, deprecated
|
437
|
+
mode: str
|
438
|
+
notebook_name: str
|
439
|
+
program: str
|
440
|
+
program_abspath: str
|
441
|
+
program_relpath: str
|
442
|
+
project: str
|
443
|
+
project_url: str
|
444
|
+
quiet: bool
|
445
|
+
reinit: bool
|
446
|
+
relogin: bool
|
447
|
+
# todo: add a preprocessing step to convert this to string
|
448
|
+
resume: Union[str, bool]
|
449
|
+
resume_fname: str
|
450
|
+
resumed: bool # indication from the server about the state of the run (different from resume - user provided flag)
|
451
|
+
root_dir: str
|
452
|
+
run_group: str
|
453
|
+
run_id: str
|
454
|
+
run_job_type: str
|
455
|
+
run_mode: str
|
456
|
+
run_name: str
|
457
|
+
run_notes: str
|
458
|
+
run_tags: Tuple[str]
|
459
|
+
run_url: str
|
460
|
+
sagemaker_disable: bool
|
461
|
+
save_code: bool
|
462
|
+
settings_system: str
|
463
|
+
settings_workspace: str
|
464
|
+
show_colors: bool
|
465
|
+
show_emoji: bool
|
466
|
+
show_errors: bool
|
467
|
+
show_info: bool
|
468
|
+
show_warnings: bool
|
469
|
+
silent: bool
|
470
|
+
start_method: str
|
471
|
+
strict: bool
|
472
|
+
summary_errors: int
|
473
|
+
summary_timeout: int
|
474
|
+
summary_warnings: int
|
475
|
+
sweep_id: str
|
476
|
+
sweep_param_path: str
|
477
|
+
sweep_url: str
|
478
|
+
symlink: bool
|
479
|
+
sync_dir: str
|
480
|
+
sync_file: str
|
481
|
+
sync_symlink_latest: str
|
482
|
+
table_raise_on_max_row_limit_exceeded: bool
|
483
|
+
timespec: str
|
484
|
+
tmp_dir: str
|
485
|
+
username: str
|
486
|
+
wandb_dir: str
|
487
|
+
|
488
|
+
|
489
|
+
class Property:
|
490
|
+
"""A class to represent attributes (individual settings) of the Settings object.
|
491
|
+
|
492
|
+
- Encapsulates the logic of how to preprocess and validate values of settings
|
493
|
+
throughout the lifetime of a class instance.
|
494
|
+
- Allows for runtime modification of settings with hooks, e.g. in the case when
|
495
|
+
a setting depends on another setting.
|
496
|
+
- The update() method is used to update the value of a setting.
|
497
|
+
- The `is_policy` attribute determines the source priority when updating the property value.
|
498
|
+
E.g. if `is_policy` is True, the smallest `Source` value takes precedence.
|
499
|
+
"""
|
500
|
+
|
501
|
+
def __init__( # pylint: disable=unused-argument
|
502
|
+
self,
|
503
|
+
name: str,
|
504
|
+
value: Optional[Any] = None,
|
505
|
+
preprocessor: Union[Callable, Sequence[Callable], None] = None,
|
506
|
+
# validators allow programming by contract
|
507
|
+
validator: Union[Callable, Sequence[Callable], None] = None,
|
508
|
+
# runtime converter (hook): properties can be e.g. tied to other properties
|
509
|
+
hook: Union[Callable, Sequence[Callable], None] = None,
|
510
|
+
# always apply hook even if value is None. can be used to replace @property's
|
511
|
+
auto_hook: bool = False,
|
512
|
+
is_policy: bool = False,
|
513
|
+
frozen: bool = False,
|
514
|
+
source: int = Source.BASE,
|
515
|
+
**kwargs: Any,
|
516
|
+
):
|
517
|
+
self.name = name
|
518
|
+
self._preprocessor = preprocessor
|
519
|
+
self._validator = validator
|
520
|
+
self._hook = hook
|
521
|
+
self._auto_hook = auto_hook
|
522
|
+
self._is_policy = is_policy
|
523
|
+
self._source = source
|
524
|
+
|
525
|
+
# preprocess and validate value
|
526
|
+
self._value = self._validate(self._preprocess(value))
|
527
|
+
|
528
|
+
self.__frozen = frozen
|
529
|
+
|
530
|
+
@property
|
531
|
+
def value(self) -> Any:
|
532
|
+
"""Apply the runtime modifier(s) (if any) and return the value."""
|
533
|
+
_value = self._value
|
534
|
+
if (_value is not None or self._auto_hook) and self._hook is not None:
|
535
|
+
_hook = [self._hook] if callable(self._hook) else self._hook
|
536
|
+
for h in _hook:
|
537
|
+
_value = h(_value)
|
538
|
+
return _value
|
539
|
+
|
540
|
+
@property
|
541
|
+
def is_policy(self) -> bool:
|
542
|
+
return self._is_policy
|
543
|
+
|
544
|
+
@property
|
545
|
+
def source(self) -> int:
|
546
|
+
return self._source
|
547
|
+
|
548
|
+
def _preprocess(self, value: Any) -> Any:
|
549
|
+
if value is not None and self._preprocessor is not None:
|
550
|
+
_preprocessor = (
|
551
|
+
[self._preprocessor]
|
552
|
+
if callable(self._preprocessor)
|
553
|
+
else self._preprocessor
|
554
|
+
)
|
555
|
+
for p in _preprocessor:
|
556
|
+
try:
|
557
|
+
value = p(value)
|
558
|
+
except Exception:
|
559
|
+
raise SettingsPreprocessingError(
|
560
|
+
f"Unable to preprocess value for property {self.name}: {value}."
|
561
|
+
)
|
562
|
+
return value
|
563
|
+
|
564
|
+
def _validate(self, value: Any) -> Any:
|
565
|
+
if value is not None and self._validator is not None:
|
566
|
+
_validator = (
|
567
|
+
[self._validator] if callable(self._validator) else self._validator
|
568
|
+
)
|
569
|
+
for v in _validator:
|
570
|
+
if not v(value):
|
571
|
+
# failed validation will likely cause a downstream error
|
572
|
+
# when trying to convert to protobuf, so we raise a hard error
|
573
|
+
raise SettingsValidationError(
|
574
|
+
f"Invalid value for property {self.name}: {value}."
|
575
|
+
)
|
576
|
+
return value
|
577
|
+
|
578
|
+
def update(self, value: Any, source: int = Source.OVERRIDE) -> None:
|
579
|
+
"""Update the value of the property."""
|
580
|
+
if self.__frozen:
|
581
|
+
raise TypeError("Property object is frozen")
|
582
|
+
# - always update value if source == Source.OVERRIDE
|
583
|
+
# - if not previously overridden:
|
584
|
+
# - update value if source is lower than or equal to current source and property is policy
|
585
|
+
# - update value if source is higher than or equal to current source and property is not policy
|
586
|
+
if (
|
587
|
+
(source == Source.OVERRIDE)
|
588
|
+
or (
|
589
|
+
self._is_policy
|
590
|
+
and self._source != Source.OVERRIDE
|
591
|
+
and source <= self._source
|
592
|
+
)
|
593
|
+
or (
|
594
|
+
not self._is_policy
|
595
|
+
and self._source != Source.OVERRIDE
|
596
|
+
and source >= self._source
|
597
|
+
)
|
598
|
+
):
|
599
|
+
# self.__dict__["_value"] = self._validate(self._preprocess(value))
|
600
|
+
self._value = self._validate(self._preprocess(value))
|
601
|
+
self._source = source
|
602
|
+
|
603
|
+
def __setattr__(self, key: str, value: Any) -> None:
|
604
|
+
if "_Property__frozen" in self.__dict__ and self.__frozen:
|
605
|
+
raise TypeError(f"Property object {self.name} is frozen")
|
606
|
+
if key == "value":
|
607
|
+
raise AttributeError("Use update() to update property value")
|
608
|
+
self.__dict__[key] = value
|
609
|
+
|
610
|
+
def __str__(self) -> str:
|
611
|
+
return f"{self.value!r}" if isinstance(self.value, str) else f"{self.value}"
|
612
|
+
|
613
|
+
def __repr__(self) -> str:
|
614
|
+
return (
|
615
|
+
f"<Property {self.name}: value={self.value} "
|
616
|
+
f"_value={self._value} source={self._source} is_policy={self._is_policy}>"
|
617
|
+
)
|
618
|
+
# return f"<Property {self.name}: value={self.value}>"
|
619
|
+
# return self.__dict__.__repr__()
|
620
|
+
|
621
|
+
|
622
|
+
class Settings(SettingsData):
|
623
|
+
"""Settings for the W&B SDK."""
|
624
|
+
|
625
|
+
def _default_props(self) -> Dict[str, Dict[str, Any]]:
|
626
|
+
"""Initialize instance attributes (individual settings) as Property objects.
|
627
|
+
|
628
|
+
Helper method that is used in `__init__` together with the class attributes.
|
629
|
+
Note that key names must be the same as the class attribute names.
|
630
|
+
"""
|
631
|
+
props: Dict[str, Dict[str, Any]] = dict(
|
632
|
+
_aws_lambda={
|
633
|
+
"hook": lambda _: is_aws_lambda(),
|
634
|
+
"auto_hook": True,
|
635
|
+
},
|
636
|
+
_code_path_local={
|
637
|
+
"hook": lambda _: _get_program_relpath(self.program),
|
638
|
+
"auto_hook": True,
|
639
|
+
},
|
640
|
+
_colab={
|
641
|
+
"hook": lambda _: "google.colab" in sys.modules,
|
642
|
+
"auto_hook": True,
|
643
|
+
},
|
644
|
+
_disable_machine_info={
|
645
|
+
"value": False,
|
646
|
+
"preprocessor": _str_as_bool,
|
647
|
+
},
|
648
|
+
_disable_meta={
|
649
|
+
"value": False,
|
650
|
+
"preprocessor": _str_as_bool,
|
651
|
+
"hook": lambda x: self._disable_machine_info or x,
|
652
|
+
},
|
653
|
+
_disable_service={
|
654
|
+
"value": False,
|
655
|
+
"preprocessor": self._process_disable_service,
|
656
|
+
"is_policy": True,
|
657
|
+
},
|
658
|
+
_disable_setproctitle={"value": False, "preprocessor": _str_as_bool},
|
659
|
+
_disable_stats={
|
660
|
+
"value": False,
|
661
|
+
"preprocessor": _str_as_bool,
|
662
|
+
"hook": lambda x: self._disable_machine_info or x,
|
663
|
+
},
|
664
|
+
_disable_update_check={"preprocessor": _str_as_bool},
|
665
|
+
_disable_viewer={"preprocessor": _str_as_bool},
|
666
|
+
_extra_http_headers={"preprocessor": _str_as_json},
|
667
|
+
_file_stream_max_bytes={"preprocessor": int},
|
668
|
+
_file_stream_transmit_interval={"preprocessor": float},
|
669
|
+
_file_stream_retry_max={"preprocessor": int},
|
670
|
+
_file_stream_retry_wait_min_seconds={"preprocessor": float},
|
671
|
+
_file_stream_retry_wait_max_seconds={"preprocessor": float},
|
672
|
+
_file_stream_timeout_seconds={"preprocessor": float},
|
673
|
+
_file_transfer_retry_max={"preprocessor": int},
|
674
|
+
_file_transfer_retry_wait_min_seconds={"preprocessor": float},
|
675
|
+
_file_transfer_retry_wait_max_seconds={"preprocessor": float},
|
676
|
+
_file_transfer_timeout_seconds={"preprocessor": float},
|
677
|
+
_flow_control_disabled={
|
678
|
+
"hook": lambda _: self._network_buffer == 0,
|
679
|
+
"auto_hook": True,
|
680
|
+
},
|
681
|
+
_flow_control_custom={
|
682
|
+
"hook": lambda _: bool(self._network_buffer),
|
683
|
+
"auto_hook": True,
|
684
|
+
},
|
685
|
+
_graphql_retry_max={"preprocessor": int},
|
686
|
+
_graphql_retry_wait_min_seconds={"preprocessor": float},
|
687
|
+
_graphql_retry_wait_max_seconds={"preprocessor": float},
|
688
|
+
_graphql_timeout_seconds={"preprocessor": float},
|
689
|
+
_internal_check_process={"value": 8, "preprocessor": float},
|
690
|
+
_internal_queue_timeout={"value": 2, "preprocessor": float},
|
691
|
+
_ipython={
|
692
|
+
"hook": lambda _: _get_python_type() == "ipython",
|
693
|
+
"auto_hook": True,
|
694
|
+
},
|
695
|
+
_jupyter={
|
696
|
+
"hook": lambda _: _get_python_type() == "jupyter",
|
697
|
+
"auto_hook": True,
|
698
|
+
},
|
699
|
+
_kaggle={"hook": lambda _: util._is_likely_kaggle(), "auto_hook": True},
|
700
|
+
_log_level={"value": logging.DEBUG},
|
701
|
+
_network_buffer={"preprocessor": int},
|
702
|
+
_noop={"hook": lambda _: self.mode == "disabled", "auto_hook": True},
|
703
|
+
_notebook={
|
704
|
+
"hook": lambda _: self._ipython
|
705
|
+
or self._jupyter
|
706
|
+
or self._colab
|
707
|
+
or self._kaggle,
|
708
|
+
"auto_hook": True,
|
709
|
+
},
|
710
|
+
_offline={
|
711
|
+
"hook": (
|
712
|
+
lambda _: True
|
713
|
+
if self.disabled or (self.mode in ("dryrun", "offline"))
|
714
|
+
else False
|
715
|
+
),
|
716
|
+
"auto_hook": True,
|
717
|
+
},
|
718
|
+
_platform={"value": util.get_platform_name()},
|
719
|
+
_proxies={
|
720
|
+
# TODO: deprecate and ask the user to use http_proxy and https_proxy instead
|
721
|
+
"preprocessor": _str_as_json,
|
722
|
+
},
|
723
|
+
_require_legacy_service={"value": False, "preprocessor": _str_as_bool},
|
724
|
+
_save_requirements={"value": True, "preprocessor": _str_as_bool},
|
725
|
+
_service_wait={
|
726
|
+
"value": 30,
|
727
|
+
"preprocessor": float,
|
728
|
+
"validator": self._validate__service_wait,
|
729
|
+
},
|
730
|
+
_shared={
|
731
|
+
"hook": lambda _: self.mode == "shared",
|
732
|
+
"auto_hook": True,
|
733
|
+
},
|
734
|
+
_start_datetime={"preprocessor": _datetime_as_str},
|
735
|
+
_stats_sampling_interval={
|
736
|
+
"value": 10.0,
|
737
|
+
"preprocessor": float,
|
738
|
+
"validator": self._validate__stats_sampling_interval,
|
739
|
+
},
|
740
|
+
_stats_sample_rate_seconds={
|
741
|
+
"value": 2.0,
|
742
|
+
"preprocessor": float,
|
743
|
+
"validator": self._validate__stats_sample_rate_seconds,
|
744
|
+
},
|
745
|
+
_stats_samples_to_average={
|
746
|
+
"value": 15,
|
747
|
+
"preprocessor": int,
|
748
|
+
"validator": self._validate__stats_samples_to_average,
|
749
|
+
},
|
750
|
+
_stats_join_assets={"value": True, "preprocessor": _str_as_bool},
|
751
|
+
_stats_neuron_monitor_config_path={
|
752
|
+
"hook": lambda x: self._path_convert(x),
|
753
|
+
},
|
754
|
+
_stats_open_metrics_endpoints={
|
755
|
+
"preprocessor": _str_as_json,
|
756
|
+
},
|
757
|
+
_stats_open_metrics_filters={
|
758
|
+
# capture all metrics on all endpoints by default
|
759
|
+
"value": (".*",),
|
760
|
+
"preprocessor": _str_as_json,
|
761
|
+
},
|
762
|
+
_stats_disk_paths={
|
763
|
+
"value": ("/",),
|
764
|
+
"preprocessor": _str_as_json,
|
765
|
+
},
|
766
|
+
_stats_buffer_size={
|
767
|
+
"value": 0,
|
768
|
+
"preprocessor": int,
|
769
|
+
},
|
770
|
+
_sync={"value": False},
|
771
|
+
_tmp_code_dir={
|
772
|
+
"value": "code",
|
773
|
+
"hook": lambda x: self._path_convert(self.tmp_dir, x),
|
774
|
+
},
|
775
|
+
_windows={
|
776
|
+
"hook": lambda _: platform.system() == "Windows",
|
777
|
+
"auto_hook": True,
|
778
|
+
},
|
779
|
+
anonymous={"validator": self._validate_anonymous},
|
780
|
+
api_key={"validator": self._validate_api_key},
|
781
|
+
base_url={
|
782
|
+
"value": "https://api.wandb.ai",
|
783
|
+
"preprocessor": lambda x: str(x).strip().rstrip("/"),
|
784
|
+
"validator": self._validate_base_url,
|
785
|
+
},
|
786
|
+
colab_url={
|
787
|
+
"hook": lambda _: self._get_colab_url(),
|
788
|
+
"auto_hook": True,
|
789
|
+
},
|
790
|
+
config_paths={"preprocessor": _str_as_tuple},
|
791
|
+
console={
|
792
|
+
"value": "auto",
|
793
|
+
"validator": self._validate_console,
|
794
|
+
"hook": lambda x: self._convert_console(x),
|
795
|
+
"auto_hook": True,
|
796
|
+
},
|
797
|
+
console_multipart={"value": False, "preprocessor": _str_as_bool},
|
798
|
+
credentials_file={
|
799
|
+
"value": str(credentials.DEFAULT_WANDB_CREDENTIALS_FILE),
|
800
|
+
"preprocessor": str,
|
801
|
+
},
|
802
|
+
deployment={
|
803
|
+
"hook": lambda _: "local" if self.is_local else "cloud",
|
804
|
+
"auto_hook": True,
|
805
|
+
},
|
806
|
+
disable_code={
|
807
|
+
"value": False,
|
808
|
+
"preprocessor": _str_as_bool,
|
809
|
+
"hook": lambda x: self._disable_machine_info or x,
|
810
|
+
},
|
811
|
+
disable_hints={"preprocessor": _str_as_bool},
|
812
|
+
disable_git={
|
813
|
+
"value": False,
|
814
|
+
"preprocessor": _str_as_bool,
|
815
|
+
"hook": lambda x: self._disable_machine_info or x,
|
816
|
+
},
|
817
|
+
disable_job_creation={
|
818
|
+
"value": False,
|
819
|
+
"preprocessor": _str_as_bool,
|
820
|
+
"hook": lambda x: self._disable_machine_info or x,
|
821
|
+
},
|
822
|
+
disabled={"value": False, "preprocessor": _str_as_bool},
|
823
|
+
files_dir={
|
824
|
+
"value": "files",
|
825
|
+
"hook": lambda x: self._path_convert(
|
826
|
+
self.wandb_dir, f"{self.run_mode}-{self.timespec}-{self.run_id}", x
|
827
|
+
),
|
828
|
+
},
|
829
|
+
force={"preprocessor": _str_as_bool},
|
830
|
+
fork_from={
|
831
|
+
"value": None,
|
832
|
+
"preprocessor": _runmoment_preprocessor,
|
833
|
+
},
|
834
|
+
resume_from={
|
835
|
+
"value": None,
|
836
|
+
"preprocessor": _runmoment_preprocessor,
|
837
|
+
},
|
838
|
+
git_remote={"value": "origin"},
|
839
|
+
heartbeat_seconds={"value": 30},
|
840
|
+
http_proxy={
|
841
|
+
"hook": lambda x: self._proxies and self._proxies.get("http") or x,
|
842
|
+
"auto_hook": True,
|
843
|
+
},
|
844
|
+
https_proxy={
|
845
|
+
"hook": lambda x: self._proxies and self._proxies.get("https") or x,
|
846
|
+
"auto_hook": True,
|
847
|
+
},
|
848
|
+
identity_token_file={"value": None, "preprocessor": str},
|
849
|
+
ignore_globs={
|
850
|
+
"value": tuple(),
|
851
|
+
"preprocessor": lambda x: tuple(x) if not isinstance(x, tuple) else x,
|
852
|
+
},
|
853
|
+
init_timeout={"value": 90, "preprocessor": lambda x: float(x)},
|
854
|
+
is_local={
|
855
|
+
"hook": (
|
856
|
+
lambda _: self.base_url != "https://api.wandb.ai"
|
857
|
+
if self.base_url is not None
|
858
|
+
else False
|
859
|
+
),
|
860
|
+
"auto_hook": True,
|
861
|
+
},
|
862
|
+
job_name={"preprocessor": str},
|
863
|
+
job_source={"validator": self._validate_job_source},
|
864
|
+
label_disable={"preprocessor": _str_as_bool},
|
865
|
+
launch={"preprocessor": _str_as_bool},
|
866
|
+
log_dir={
|
867
|
+
"value": "logs",
|
868
|
+
"hook": lambda x: self._path_convert(
|
869
|
+
self.wandb_dir, f"{self.run_mode}-{self.timespec}-{self.run_id}", x
|
870
|
+
),
|
871
|
+
},
|
872
|
+
log_internal={
|
873
|
+
"value": "debug-internal.log",
|
874
|
+
"hook": lambda x: self._path_convert(self.log_dir, x),
|
875
|
+
},
|
876
|
+
log_symlink_internal={
|
877
|
+
"value": "debug-internal.log",
|
878
|
+
"hook": lambda x: self._path_convert(self.wandb_dir, x),
|
879
|
+
},
|
880
|
+
log_symlink_user={
|
881
|
+
"value": "debug.log",
|
882
|
+
"hook": lambda x: self._path_convert(self.wandb_dir, x),
|
883
|
+
},
|
884
|
+
log_user={
|
885
|
+
"value": "debug.log",
|
886
|
+
"hook": lambda x: self._path_convert(self.log_dir, x),
|
887
|
+
},
|
888
|
+
login_timeout={"preprocessor": lambda x: float(x)},
|
889
|
+
mode={"value": "online", "validator": self._validate_mode},
|
890
|
+
program={
|
891
|
+
"hook": lambda x: self._get_program(x),
|
892
|
+
},
|
893
|
+
project={
|
894
|
+
"validator": self._validate_project,
|
895
|
+
},
|
896
|
+
project_url={"hook": lambda _: self._project_url(), "auto_hook": True},
|
897
|
+
quiet={"preprocessor": _str_as_bool},
|
898
|
+
reinit={"preprocessor": _str_as_bool},
|
899
|
+
relogin={"preprocessor": _str_as_bool},
|
900
|
+
# todo: hack to make to_proto() always happy
|
901
|
+
resume={"preprocessor": lambda x: None if x is False else x},
|
902
|
+
resume_fname={
|
903
|
+
"value": "wandb-resume.json",
|
904
|
+
"hook": lambda x: self._path_convert(self.wandb_dir, x),
|
905
|
+
},
|
906
|
+
resumed={"value": "False", "preprocessor": _str_as_bool},
|
907
|
+
root_dir={
|
908
|
+
"preprocessor": lambda x: str(x),
|
909
|
+
"value": os.path.abspath(os.getcwd()),
|
910
|
+
},
|
911
|
+
run_id={
|
912
|
+
"validator": self._validate_run_id,
|
913
|
+
},
|
914
|
+
run_mode={
|
915
|
+
"hook": lambda _: "offline-run" if self._offline else "run",
|
916
|
+
"auto_hook": True,
|
917
|
+
},
|
918
|
+
run_tags={
|
919
|
+
"preprocessor": lambda x: tuple(x) if not isinstance(x, tuple) else x,
|
920
|
+
},
|
921
|
+
run_url={"hook": lambda _: self._run_url(), "auto_hook": True},
|
922
|
+
sagemaker_disable={"preprocessor": _str_as_bool},
|
923
|
+
save_code={"preprocessor": _str_as_bool},
|
924
|
+
settings_system={
|
925
|
+
"value": os.path.join("~", ".config", "wandb", "settings"),
|
926
|
+
"hook": lambda x: self._path_convert(x),
|
927
|
+
},
|
928
|
+
settings_workspace={
|
929
|
+
"value": "settings",
|
930
|
+
"hook": lambda x: self._path_convert(self.wandb_dir, x),
|
931
|
+
},
|
932
|
+
show_colors={"preprocessor": _str_as_bool},
|
933
|
+
show_emoji={"preprocessor": _str_as_bool},
|
934
|
+
show_errors={"value": "True", "preprocessor": _str_as_bool},
|
935
|
+
show_info={"value": "True", "preprocessor": _str_as_bool},
|
936
|
+
show_warnings={"value": "True", "preprocessor": _str_as_bool},
|
937
|
+
silent={"value": "False", "preprocessor": _str_as_bool},
|
938
|
+
start_method={"validator": self._validate_start_method},
|
939
|
+
strict={"preprocessor": _str_as_bool},
|
940
|
+
summary_timeout={"value": 60, "preprocessor": lambda x: int(x)},
|
941
|
+
summary_warnings={
|
942
|
+
"value": 5,
|
943
|
+
"preprocessor": lambda x: int(x),
|
944
|
+
"is_policy": True,
|
945
|
+
},
|
946
|
+
sweep_url={"hook": lambda _: self._sweep_url(), "auto_hook": True},
|
947
|
+
symlink={"preprocessor": _str_as_bool},
|
948
|
+
sync_dir={
|
949
|
+
"hook": [
|
950
|
+
lambda _: self._path_convert(
|
951
|
+
self.wandb_dir, f"{self.run_mode}-{self.timespec}-{self.run_id}"
|
952
|
+
)
|
953
|
+
],
|
954
|
+
"auto_hook": True,
|
955
|
+
},
|
956
|
+
sync_file={
|
957
|
+
"hook": lambda _: self._path_convert(
|
958
|
+
self.sync_dir, f"run-{self.run_id}.wandb"
|
959
|
+
),
|
960
|
+
"auto_hook": True,
|
961
|
+
},
|
962
|
+
sync_symlink_latest={
|
963
|
+
"value": "latest-run",
|
964
|
+
"hook": lambda x: self._path_convert(self.wandb_dir, x),
|
965
|
+
},
|
966
|
+
table_raise_on_max_row_limit_exceeded={
|
967
|
+
"value": False,
|
968
|
+
"preprocessor": _str_as_bool,
|
969
|
+
},
|
970
|
+
timespec={
|
971
|
+
"hook": lambda _: self._start_datetime,
|
972
|
+
"auto_hook": True,
|
973
|
+
},
|
974
|
+
tmp_dir={
|
975
|
+
"value": "tmp",
|
976
|
+
"hook": lambda x: (
|
977
|
+
self._path_convert(
|
978
|
+
self.wandb_dir,
|
979
|
+
f"{self.run_mode}-{self.timespec}-{self.run_id}",
|
980
|
+
x,
|
981
|
+
)
|
982
|
+
or tempfile.gettempdir()
|
983
|
+
),
|
984
|
+
},
|
985
|
+
wandb_dir={
|
986
|
+
"hook": lambda _: _get_wandb_dir(self.root_dir or ""),
|
987
|
+
"auto_hook": True,
|
988
|
+
},
|
989
|
+
)
|
990
|
+
return props
|
991
|
+
|
992
|
+
# helper methods for validating values
|
993
|
+
@staticmethod
|
994
|
+
def _validator_factory(hint: Any) -> Callable[[Any], bool]: # noqa: C901
|
995
|
+
"""Return a factory for setting type validators."""
|
996
|
+
|
997
|
+
def helper(value: Any) -> bool:
|
998
|
+
try:
|
999
|
+
is_valid = is_instance_recursive(value, hint)
|
1000
|
+
except Exception:
|
1001
|
+
# instance check failed, but let's not crash and only print a warning
|
1002
|
+
is_valid = False
|
1003
|
+
|
1004
|
+
return is_valid
|
1005
|
+
|
1006
|
+
return helper
|
1007
|
+
|
1008
|
+
@staticmethod
|
1009
|
+
def _validate_mode(value: str) -> bool:
|
1010
|
+
choices: Set[str] = {"dryrun", "run", "offline", "online", "disabled", "shared"}
|
1011
|
+
if value not in choices:
|
1012
|
+
raise UsageError(f"Settings field `mode`: {value!r} not in {choices}")
|
1013
|
+
return True
|
1014
|
+
|
1015
|
+
@staticmethod
|
1016
|
+
def _validate_project(value: Optional[str]) -> bool:
|
1017
|
+
invalid_chars_list = list("/\\#?%:")
|
1018
|
+
if value is not None:
|
1019
|
+
if len(value) > 128:
|
1020
|
+
raise UsageError(
|
1021
|
+
f"Invalid project name {value!r}: exceeded 128 characters"
|
1022
|
+
)
|
1023
|
+
invalid_chars = {char for char in invalid_chars_list if char in value}
|
1024
|
+
if invalid_chars:
|
1025
|
+
raise UsageError(
|
1026
|
+
f"Invalid project name {value!r}: "
|
1027
|
+
f"cannot contain characters {','.join(invalid_chars_list)!r}, "
|
1028
|
+
f"found {','.join(invalid_chars)!r}"
|
1029
|
+
)
|
1030
|
+
return True
|
1031
|
+
|
1032
|
+
@staticmethod
|
1033
|
+
def _validate_start_method(value: str) -> bool:
|
1034
|
+
available_methods = ["thread"]
|
1035
|
+
if hasattr(multiprocessing, "get_all_start_methods"):
|
1036
|
+
available_methods += multiprocessing.get_all_start_methods()
|
1037
|
+
if value not in available_methods:
|
1038
|
+
raise UsageError(
|
1039
|
+
f"Settings field `start_method`: {value!r} not in {available_methods}"
|
1040
|
+
)
|
1041
|
+
return True
|
1042
|
+
|
1043
|
+
@staticmethod
|
1044
|
+
def _validate_console(value: str) -> bool:
|
1045
|
+
choices = ConsoleValue
|
1046
|
+
if value not in choices:
|
1047
|
+
# do not advertise internal console states
|
1048
|
+
choices -= {"wrap_emu", "wrap_raw"}
|
1049
|
+
raise UsageError(f"Settings field `console`: {value!r} not in {choices}")
|
1050
|
+
return True
|
1051
|
+
|
1052
|
+
@staticmethod
|
1053
|
+
def _validate_anonymous(value: str) -> bool:
|
1054
|
+
choices: Set[str] = {"allow", "must", "never", "false", "true"}
|
1055
|
+
if value not in choices:
|
1056
|
+
raise UsageError(f"Settings field `anonymous`: {value!r} not in {choices}")
|
1057
|
+
return True
|
1058
|
+
|
1059
|
+
@staticmethod
|
1060
|
+
def _validate_run_id(value: str) -> bool:
|
1061
|
+
# if len(value) > len(value.strip()):
|
1062
|
+
# raise UsageError("Run ID cannot start or end with whitespace")
|
1063
|
+
return bool(value.strip())
|
1064
|
+
|
1065
|
+
@staticmethod
|
1066
|
+
def _validate_api_key(value: str) -> bool:
|
1067
|
+
if len(value) > len(value.strip()):
|
1068
|
+
raise UsageError("API key cannot start or end with whitespace")
|
1069
|
+
|
1070
|
+
# todo: move this check to the post-init validation step
|
1071
|
+
# if value.startswith("local") and not self.is_local:
|
1072
|
+
# raise UsageError(
|
1073
|
+
# "Attempting to use a local API key to connect to https://api.wandb.ai"
|
1074
|
+
# )
|
1075
|
+
# todo: move here the logic from sdk/lib/apikey.py
|
1076
|
+
|
1077
|
+
return True
|
1078
|
+
|
1079
|
+
@staticmethod
|
1080
|
+
def _validate_base_url(value: Optional[str]) -> bool:
|
1081
|
+
"""Validate the base url of the wandb server.
|
1082
|
+
|
1083
|
+
param value: URL to validate
|
1084
|
+
|
1085
|
+
Based on the Django URLValidator, but with a few additional checks.
|
1086
|
+
|
1087
|
+
Copyright (c) Django Software Foundation and individual contributors.
|
1088
|
+
All rights reserved.
|
1089
|
+
|
1090
|
+
Redistribution and use in source and binary forms, with or without modification,
|
1091
|
+
are permitted provided that the following conditions are met:
|
1092
|
+
|
1093
|
+
1. Redistributions of source code must retain the above copyright notice,
|
1094
|
+
this list of conditions and the following disclaimer.
|
1095
|
+
|
1096
|
+
2. Redistributions in binary form must reproduce the above copyright
|
1097
|
+
notice, this list of conditions and the following disclaimer in the
|
1098
|
+
documentation and/or other materials provided with the distribution.
|
1099
|
+
|
1100
|
+
3. Neither the name of Django nor the names of its contributors may be used
|
1101
|
+
to endorse or promote products derived from this software without
|
1102
|
+
specific prior written permission.
|
1103
|
+
|
1104
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
1105
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
1106
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
1107
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
1108
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
1109
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
1110
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
1111
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
1112
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
1113
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1114
|
+
"""
|
1115
|
+
if value is None:
|
1116
|
+
return True
|
1117
|
+
|
1118
|
+
ul = "\u00a1-\uffff" # Unicode letters range (must not be a raw string).
|
1119
|
+
|
1120
|
+
# IP patterns
|
1121
|
+
ipv4_re = (
|
1122
|
+
r"(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)"
|
1123
|
+
r"(?:\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}"
|
1124
|
+
)
|
1125
|
+
ipv6_re = r"\[[0-9a-f:.]+\]" # (simple regex, validated later)
|
1126
|
+
|
1127
|
+
# Host patterns
|
1128
|
+
hostname_re = (
|
1129
|
+
r"[a-z" + ul + r"0-9](?:[a-z" + ul + r"0-9-]{0,61}[a-z" + ul + r"0-9])?"
|
1130
|
+
)
|
1131
|
+
# Max length for domain name labels is 63 characters per RFC 1034 sec. 3.1
|
1132
|
+
domain_re = r"(?:\.(?!-)[a-z" + ul + r"0-9-]{1,63}(?<!-))*"
|
1133
|
+
tld_re = (
|
1134
|
+
r"\." # dot
|
1135
|
+
r"(?!-)" # can't start with a dash
|
1136
|
+
r"(?:[a-z" + ul + "-]{2,63}" # domain label
|
1137
|
+
r"|xn--[a-z0-9]{1,59})" # or punycode label
|
1138
|
+
r"(?<!-)" # can't end with a dash
|
1139
|
+
r"\.?" # may have a trailing dot
|
1140
|
+
)
|
1141
|
+
# host_re = "(" + hostname_re + domain_re + tld_re + "|localhost)"
|
1142
|
+
# todo?: allow hostname to be just a hostname (no tld)?
|
1143
|
+
host_re = "(" + hostname_re + domain_re + f"({tld_re})?" + "|localhost)"
|
1144
|
+
|
1145
|
+
regex = re.compile(
|
1146
|
+
r"^(?:[a-z0-9.+-]*)://" # scheme is validated separately
|
1147
|
+
r"(?:[^\s:@/]+(?::[^\s:@/]*)?@)?" # user:pass authentication
|
1148
|
+
r"(?:" + ipv4_re + "|" + ipv6_re + "|" + host_re + ")"
|
1149
|
+
r"(?::[0-9]{1,5})?" # port
|
1150
|
+
r"(?:[/?#][^\s]*)?" # resource path
|
1151
|
+
r"\Z",
|
1152
|
+
re.IGNORECASE,
|
1153
|
+
)
|
1154
|
+
schemes = {"http", "https"}
|
1155
|
+
unsafe_chars = frozenset("\t\r\n")
|
1156
|
+
|
1157
|
+
scheme = value.split("://")[0].lower()
|
1158
|
+
split_url = urlsplit(value)
|
1159
|
+
parsed_url = urlparse(value)
|
1160
|
+
|
1161
|
+
if re.match(r".*wandb\.ai[^\.]*$", value) and "api." not in value:
|
1162
|
+
# user might guess app.wandb.ai or wandb.ai is the default cloud server
|
1163
|
+
raise UsageError(
|
1164
|
+
f"{value} is not a valid server address, did you mean https://api.wandb.ai?"
|
1165
|
+
)
|
1166
|
+
elif re.match(r".*wandb\.ai[^\.]*$", value) and scheme != "https":
|
1167
|
+
raise UsageError("http is not secure, please use https://api.wandb.ai")
|
1168
|
+
elif parsed_url.netloc == "":
|
1169
|
+
raise UsageError(f"Invalid URL: {value}")
|
1170
|
+
elif unsafe_chars.intersection(value):
|
1171
|
+
raise UsageError("URL cannot contain unsafe characters")
|
1172
|
+
elif scheme not in schemes:
|
1173
|
+
raise UsageError("URL must start with `http(s)://`")
|
1174
|
+
elif not regex.search(value):
|
1175
|
+
raise UsageError(f"{value} is not a valid server address")
|
1176
|
+
elif split_url.hostname is None or len(split_url.hostname) > 253:
|
1177
|
+
raise UsageError("hostname is invalid")
|
1178
|
+
|
1179
|
+
return True
|
1180
|
+
|
1181
|
+
@staticmethod
|
1182
|
+
def _process_disable_service(value: Union[str, bool]) -> bool:
|
1183
|
+
value = _str_as_bool(value)
|
1184
|
+
if value:
|
1185
|
+
wandb.termwarn(
|
1186
|
+
"Disabling the wandb service is deprecated as of version 0.18.0 and will be removed in future versions. ",
|
1187
|
+
repeat=False,
|
1188
|
+
)
|
1189
|
+
return value
|
1190
|
+
|
1191
|
+
@staticmethod
|
1192
|
+
def _validate__service_wait(value: float) -> bool:
|
1193
|
+
if value <= 0:
|
1194
|
+
raise UsageError("_service_wait must be a positive number")
|
1195
|
+
return True
|
1196
|
+
|
1197
|
+
@staticmethod
|
1198
|
+
def _validate__stats_sampling_interval(value: float) -> bool:
|
1199
|
+
if value < 0.1:
|
1200
|
+
raise UsageError("sampling interval must be >= 0.1 seconds")
|
1201
|
+
return True
|
1202
|
+
|
1203
|
+
@staticmethod
|
1204
|
+
def _validate__stats_sample_rate_seconds(value: float) -> bool:
|
1205
|
+
if value < 0.1:
|
1206
|
+
raise UsageError("_stats_sample_rate_seconds must be >= 0.1")
|
1207
|
+
return True
|
1208
|
+
|
1209
|
+
@staticmethod
|
1210
|
+
def _validate__stats_samples_to_average(value: int) -> bool:
|
1211
|
+
if value < 1 or value > 30:
|
1212
|
+
raise UsageError("_stats_samples_to_average must be between 1 and 30")
|
1213
|
+
return True
|
1214
|
+
|
1215
|
+
@staticmethod
|
1216
|
+
def _validate_job_source(value: str) -> bool:
|
1217
|
+
valid_sources = ["repo", "artifact", "image"]
|
1218
|
+
if value not in valid_sources:
|
1219
|
+
raise UsageError(
|
1220
|
+
f"Settings field `job_source`: {value!r} not in {valid_sources}"
|
1221
|
+
)
|
1222
|
+
return True
|
1223
|
+
|
1224
|
+
# other helper methods
|
1225
|
+
@staticmethod
|
1226
|
+
def _path_convert(*args: str) -> str:
|
1227
|
+
"""Join path and apply os.path.expanduser to it."""
|
1228
|
+
return os.path.expanduser(os.path.join(*args))
|
1229
|
+
|
1230
|
+
def _convert_console(self, console: str) -> str:
|
1231
|
+
if console == "auto":
|
1232
|
+
if (
|
1233
|
+
self._jupyter
|
1234
|
+
or (self.start_method == "thread")
|
1235
|
+
or not self._disable_service
|
1236
|
+
or self._windows
|
1237
|
+
):
|
1238
|
+
console = "wrap"
|
1239
|
+
else:
|
1240
|
+
console = "redirect"
|
1241
|
+
return console
|
1242
|
+
|
1243
|
+
def _get_colab_url(self) -> Optional[str]:
|
1244
|
+
if not self._colab:
|
1245
|
+
return None
|
1246
|
+
if self._jupyter_path and self._jupyter_path.startswith("fileId="):
|
1247
|
+
unescaped = unquote(self._jupyter_path)
|
1248
|
+
return "https://colab.research.google.com/notebook#" + unescaped
|
1249
|
+
return None
|
1250
|
+
|
1251
|
+
def _get_program(self, program: Optional[str]) -> Optional[str]:
|
1252
|
+
if program is not None and program != "<python with no main file>":
|
1253
|
+
return program
|
1254
|
+
|
1255
|
+
if not self._jupyter:
|
1256
|
+
return program
|
1257
|
+
|
1258
|
+
if self.notebook_name:
|
1259
|
+
return self.notebook_name
|
1260
|
+
|
1261
|
+
if not self._jupyter_path:
|
1262
|
+
return program
|
1263
|
+
|
1264
|
+
if self._jupyter_path.startswith("fileId="):
|
1265
|
+
return self._jupyter_name
|
1266
|
+
else:
|
1267
|
+
return self._jupyter_path
|
1268
|
+
|
1269
|
+
def _get_url_query_string(self) -> str:
|
1270
|
+
# TODO(settings) use `wandb_setting` (if self.anonymous != "true":)
|
1271
|
+
if Api().settings().get("anonymous") != "true":
|
1272
|
+
return ""
|
1273
|
+
|
1274
|
+
api_key = apikey.api_key(settings=self)
|
1275
|
+
|
1276
|
+
return f"?{urlencode({'apiKey': api_key})}"
|
1277
|
+
|
1278
|
+
def _project_url_base(self) -> str:
|
1279
|
+
if not all([self.entity, self.project]):
|
1280
|
+
return ""
|
1281
|
+
|
1282
|
+
app_url = wandb.util.app_url(self.base_url)
|
1283
|
+
return f"{app_url}/{quote(self.entity)}/{quote(self.project)}"
|
1284
|
+
|
1285
|
+
def _project_url(self) -> str:
|
1286
|
+
project_url = self._project_url_base()
|
1287
|
+
if not project_url:
|
1288
|
+
return ""
|
1289
|
+
|
1290
|
+
query = self._get_url_query_string()
|
1291
|
+
|
1292
|
+
return f"{project_url}{query}"
|
1293
|
+
|
1294
|
+
def _run_url(self) -> str:
|
1295
|
+
"""Return the run url."""
|
1296
|
+
project_url = self._project_url_base()
|
1297
|
+
if not all([project_url, self.run_id]):
|
1298
|
+
return ""
|
1299
|
+
|
1300
|
+
query = self._get_url_query_string()
|
1301
|
+
return f"{project_url}/runs/{quote(self.run_id)}{query}"
|
1302
|
+
|
1303
|
+
def _set_run_start_time(self, source: int = Source.BASE) -> None:
|
1304
|
+
"""Set the time stamps for the settings.
|
1305
|
+
|
1306
|
+
Called once the run is initialized.
|
1307
|
+
"""
|
1308
|
+
time_stamp: float = time.time()
|
1309
|
+
datetime_now: datetime = datetime.fromtimestamp(time_stamp)
|
1310
|
+
datetime_now_str = _datetime_as_str(datetime_now)
|
1311
|
+
object.__setattr__(self, "_Settings_start_datetime", datetime_now_str)
|
1312
|
+
object.__setattr__(self, "_Settings_start_time", time_stamp)
|
1313
|
+
self.update(
|
1314
|
+
_start_datetime=datetime_now_str,
|
1315
|
+
_start_time=time_stamp,
|
1316
|
+
source=source,
|
1317
|
+
)
|
1318
|
+
|
1319
|
+
def _sweep_url(self) -> str:
|
1320
|
+
"""Return the sweep url."""
|
1321
|
+
project_url = self._project_url_base()
|
1322
|
+
if not all([project_url, self.sweep_id]):
|
1323
|
+
return ""
|
1324
|
+
|
1325
|
+
query = self._get_url_query_string()
|
1326
|
+
return f"{project_url}/sweeps/{quote(self.sweep_id)}{query}"
|
1327
|
+
|
1328
|
+
def __init__(self, **kwargs: Any) -> None:
|
1329
|
+
self.__frozen: bool = False
|
1330
|
+
self.__initialized: bool = False
|
1331
|
+
|
1332
|
+
self.__modification_order = SETTINGS_TOPOLOGICALLY_SORTED
|
1333
|
+
|
1334
|
+
# Set default settings values
|
1335
|
+
# We start off with the class attributes and `default_props` dicts
|
1336
|
+
# and then create Property objects.
|
1337
|
+
# Once initialized, attributes are to only be updated using the `update` method
|
1338
|
+
default_props = self._default_props()
|
1339
|
+
|
1340
|
+
# Init instance attributes as Property objects.
|
1341
|
+
# Type hints of class attributes are used to generate a type validator function
|
1342
|
+
# for runtime checks for each attribute.
|
1343
|
+
# These are defaults, using Source.BASE for non-policy attributes and Source.RUN for policies.
|
1344
|
+
for prop, type_hint in get_type_hints(SettingsData).items():
|
1345
|
+
validators = [self._validator_factory(type_hint)]
|
1346
|
+
|
1347
|
+
if prop in default_props:
|
1348
|
+
validator = default_props[prop].pop("validator", [])
|
1349
|
+
# Property validator could be either Callable or Sequence[Callable]
|
1350
|
+
if callable(validator):
|
1351
|
+
validators.append(validator)
|
1352
|
+
elif isinstance(validator, Sequence):
|
1353
|
+
validators.extend(list(validator))
|
1354
|
+
object.__setattr__(
|
1355
|
+
self,
|
1356
|
+
prop,
|
1357
|
+
Property(
|
1358
|
+
name=prop,
|
1359
|
+
**default_props[prop],
|
1360
|
+
validator=validators,
|
1361
|
+
# todo: double-check this logic:
|
1362
|
+
source=Source.RUN
|
1363
|
+
if default_props[prop].get("is_policy", False)
|
1364
|
+
else Source.BASE,
|
1365
|
+
),
|
1366
|
+
)
|
1367
|
+
else:
|
1368
|
+
object.__setattr__(
|
1369
|
+
self,
|
1370
|
+
prop,
|
1371
|
+
Property(
|
1372
|
+
name=prop,
|
1373
|
+
validator=validators,
|
1374
|
+
source=Source.BASE,
|
1375
|
+
),
|
1376
|
+
)
|
1377
|
+
|
1378
|
+
# update overridden defaults from kwargs
|
1379
|
+
unexpected_arguments = [k for k in kwargs.keys() if k not in self.__dict__]
|
1380
|
+
# allow only explicitly defined arguments
|
1381
|
+
if unexpected_arguments:
|
1382
|
+
raise SettingsUnexpectedArgsError(
|
1383
|
+
f"Got unexpected arguments: {unexpected_arguments}. "
|
1384
|
+
)
|
1385
|
+
|
1386
|
+
# automatically inspect setting validators and runtime hooks and topologically sort them
|
1387
|
+
# so that we can safely update them. throw error if there are cycles.
|
1388
|
+
for prop in self.__modification_order:
|
1389
|
+
if prop in kwargs:
|
1390
|
+
source = Source.RUN if self.__dict__[prop].is_policy else Source.BASE
|
1391
|
+
self.update({prop: kwargs[prop]}, source=source)
|
1392
|
+
kwargs.pop(prop)
|
1393
|
+
|
1394
|
+
for k, v in kwargs.items():
|
1395
|
+
# todo: double-check this logic:
|
1396
|
+
source = Source.RUN if self.__dict__[k].is_policy else Source.BASE
|
1397
|
+
self.update({k: v}, source=source)
|
1398
|
+
|
1399
|
+
# setup private attributes
|
1400
|
+
object.__setattr__(self, "_Settings_start_datetime", None)
|
1401
|
+
object.__setattr__(self, "_Settings_start_time", None)
|
1402
|
+
|
1403
|
+
# done with init, use self.update() to update attributes from now on
|
1404
|
+
self.__initialized = True
|
1405
|
+
|
1406
|
+
# todo? freeze settings to prevent accidental changes
|
1407
|
+
# self.freeze()
|
1408
|
+
|
1409
|
+
def __str__(self) -> str:
|
1410
|
+
# get attributes that are instances of the Property class:
|
1411
|
+
representation = {
|
1412
|
+
k: v.value for k, v in self.__dict__.items() if isinstance(v, Property)
|
1413
|
+
}
|
1414
|
+
return f"<Settings {_redact_dict(representation)}>"
|
1415
|
+
|
1416
|
+
def __repr__(self) -> str:
|
1417
|
+
# private attributes
|
1418
|
+
private = {k: v for k, v in self.__dict__.items() if k.startswith("_Settings")}
|
1419
|
+
# get attributes that are instances of the Property class:
|
1420
|
+
attributes = {
|
1421
|
+
k: f"<Property value={v.value} source={v.source}>"
|
1422
|
+
for k, v in self.__dict__.items()
|
1423
|
+
if isinstance(v, Property)
|
1424
|
+
}
|
1425
|
+
representation = {**private, **attributes}
|
1426
|
+
return f"<Settings {representation}>"
|
1427
|
+
|
1428
|
+
def __copy__(self) -> "Settings":
|
1429
|
+
"""Ensure that a copy of the settings object is a truly deep copy.
|
1430
|
+
|
1431
|
+
Note that the copied object will not be frozen todo? why is this needed?
|
1432
|
+
"""
|
1433
|
+
# get attributes that are instances of the Property class:
|
1434
|
+
attributes = {k: v for k, v in self.__dict__.items() if isinstance(v, Property)}
|
1435
|
+
new = Settings()
|
1436
|
+
# update properties that have deps or are dependent on in the topologically-sorted order
|
1437
|
+
for prop in self.__modification_order:
|
1438
|
+
new.update({prop: attributes[prop]._value}, source=attributes[prop].source)
|
1439
|
+
attributes.pop(prop)
|
1440
|
+
|
1441
|
+
# update the remaining attributes
|
1442
|
+
for k, v in attributes.items():
|
1443
|
+
# make sure to use the raw property value (v._value),
|
1444
|
+
# not the potential result of runtime hooks applied to it (v.value)
|
1445
|
+
new.update({k: v._value}, source=v.source)
|
1446
|
+
new.unfreeze()
|
1447
|
+
|
1448
|
+
return new
|
1449
|
+
|
1450
|
+
def __deepcopy__(self, memo: dict) -> "Settings":
|
1451
|
+
return self.__copy__()
|
1452
|
+
|
1453
|
+
# attribute access methods
|
1454
|
+
@no_type_check # this is a hack to make mypy happy
|
1455
|
+
def __getattribute__(self, name: str) -> Any:
|
1456
|
+
"""Expose `attribute.value` if `attribute` is a Property."""
|
1457
|
+
item = object.__getattribute__(self, name)
|
1458
|
+
if isinstance(item, Property):
|
1459
|
+
return item.value
|
1460
|
+
return item
|
1461
|
+
|
1462
|
+
def __setattr__(self, key: str, value: Any) -> None:
|
1463
|
+
if "_Settings__initialized" in self.__dict__ and self.__initialized:
|
1464
|
+
raise TypeError(f"Please use update() to update attribute `{key}` value")
|
1465
|
+
object.__setattr__(self, key, value)
|
1466
|
+
|
1467
|
+
def __iter__(self) -> Iterable:
|
1468
|
+
return iter(self.to_dict())
|
1469
|
+
|
1470
|
+
def copy(self) -> "Settings":
|
1471
|
+
return self.__copy__()
|
1472
|
+
|
1473
|
+
# implement the Mapping interface
|
1474
|
+
def keys(self) -> Iterable[str]:
|
1475
|
+
return self.to_dict().keys()
|
1476
|
+
|
1477
|
+
@no_type_check # this is a hack to make mypy happy
|
1478
|
+
def __getitem__(self, name: str) -> Any:
|
1479
|
+
"""Expose attribute.value if attribute is a Property."""
|
1480
|
+
item = object.__getattribute__(self, name)
|
1481
|
+
if isinstance(item, Property):
|
1482
|
+
return item.value
|
1483
|
+
return item
|
1484
|
+
|
1485
|
+
def update(
|
1486
|
+
self,
|
1487
|
+
settings: Optional[Union[Dict[str, Any], "Settings"]] = None,
|
1488
|
+
source: int = Source.OVERRIDE,
|
1489
|
+
**kwargs: Any,
|
1490
|
+
) -> None:
|
1491
|
+
"""Update individual settings."""
|
1492
|
+
if "_Settings__frozen" in self.__dict__ and self.__frozen:
|
1493
|
+
raise TypeError("Settings object is frozen")
|
1494
|
+
|
1495
|
+
if isinstance(settings, Settings):
|
1496
|
+
# If a Settings object is passed, detect the settings that differ
|
1497
|
+
# from defaults, collect them into a dict, and apply them using `source`.
|
1498
|
+
# This comes up in `wandb.init(settings=wandb.Settings(...))` and
|
1499
|
+
# seems like the behavior that the user would expect when calling init that way.
|
1500
|
+
defaults = Settings()
|
1501
|
+
settings_dict = dict()
|
1502
|
+
for k, v in settings.__dict__.items():
|
1503
|
+
if isinstance(v, Property):
|
1504
|
+
if v._value != defaults.__dict__[k]._value:
|
1505
|
+
settings_dict[k] = v._value
|
1506
|
+
# replace with the generated dict
|
1507
|
+
settings = settings_dict
|
1508
|
+
|
1509
|
+
# add kwargs to settings
|
1510
|
+
settings = settings or dict()
|
1511
|
+
# explicit kwargs take precedence over settings
|
1512
|
+
settings = {**settings, **kwargs}
|
1513
|
+
unknown_properties = []
|
1514
|
+
for key in settings.keys():
|
1515
|
+
# only allow updating known Properties
|
1516
|
+
if key not in self.__dict__ or not isinstance(self.__dict__[key], Property):
|
1517
|
+
unknown_properties.append(key)
|
1518
|
+
if unknown_properties:
|
1519
|
+
raise KeyError(f"Unknown settings: {unknown_properties}")
|
1520
|
+
# only if all keys are valid, update them
|
1521
|
+
|
1522
|
+
# store settings to be updated in a dict to preserve stats on preprocessing and validation errors
|
1523
|
+
settings.copy()
|
1524
|
+
|
1525
|
+
# update properties that have deps or are dependent on in the topologically-sorted order
|
1526
|
+
for key in self.__modification_order:
|
1527
|
+
if key in settings:
|
1528
|
+
self.__dict__[key].update(settings.pop(key), source=source)
|
1529
|
+
|
1530
|
+
# update the remaining properties
|
1531
|
+
for key, value in settings.items():
|
1532
|
+
self.__dict__[key].update(value, source)
|
1533
|
+
|
1534
|
+
def items(self) -> ItemsView[str, Any]:
|
1535
|
+
return self.to_dict().items()
|
1536
|
+
|
1537
|
+
def get(self, key: str, default: Optional[Any] = None) -> Any:
|
1538
|
+
return self.to_dict().get(key, default)
|
1539
|
+
|
1540
|
+
def freeze(self) -> None:
|
1541
|
+
object.__setattr__(self, "_Settings__frozen", True)
|
1542
|
+
|
1543
|
+
def unfreeze(self) -> None:
|
1544
|
+
object.__setattr__(self, "_Settings__frozen", False)
|
1545
|
+
|
1546
|
+
def is_frozen(self) -> bool:
|
1547
|
+
return self.__frozen
|
1548
|
+
|
1549
|
+
def to_dict(self) -> Dict[str, Any]:
|
1550
|
+
"""Return a dict representation of the settings."""
|
1551
|
+
# get attributes that are instances of the Property class:
|
1552
|
+
attributes = {
|
1553
|
+
k: v.value for k, v in self.__dict__.items() if isinstance(v, Property)
|
1554
|
+
}
|
1555
|
+
return attributes
|
1556
|
+
|
1557
|
+
def to_proto(self) -> wandb_settings_pb2.Settings:
|
1558
|
+
"""Generate a protobuf representation of the settings."""
|
1559
|
+
from dataclasses import fields
|
1560
|
+
|
1561
|
+
settings = wandb_settings_pb2.Settings()
|
1562
|
+
for field in fields(SettingsData):
|
1563
|
+
k = field.name
|
1564
|
+
v = getattr(self, k)
|
1565
|
+
# special case for _stats_open_metrics_filters
|
1566
|
+
if k == "_stats_open_metrics_filters":
|
1567
|
+
if isinstance(v, (list, set, tuple)):
|
1568
|
+
setting = getattr(settings, k)
|
1569
|
+
setting.sequence.value.extend(v)
|
1570
|
+
elif isinstance(v, dict):
|
1571
|
+
setting = getattr(settings, k)
|
1572
|
+
for key, value in v.items():
|
1573
|
+
for kk, vv in value.items():
|
1574
|
+
setting.mapping.value[key].value[kk] = vv
|
1575
|
+
else:
|
1576
|
+
raise TypeError(f"Unsupported type {type(v)} for setting {k}")
|
1577
|
+
continue
|
1578
|
+
|
1579
|
+
if isinstance(v, bool):
|
1580
|
+
getattr(settings, k).CopyFrom(BoolValue(value=v))
|
1581
|
+
elif isinstance(v, int):
|
1582
|
+
getattr(settings, k).CopyFrom(Int32Value(value=v))
|
1583
|
+
elif isinstance(v, float):
|
1584
|
+
getattr(settings, k).CopyFrom(DoubleValue(value=v))
|
1585
|
+
elif isinstance(v, str):
|
1586
|
+
getattr(settings, k).CopyFrom(StringValue(value=v))
|
1587
|
+
elif isinstance(v, (list, set, tuple)):
|
1588
|
+
# we only support sequences of strings for now
|
1589
|
+
sequence = getattr(settings, k)
|
1590
|
+
sequence.value.extend(v)
|
1591
|
+
elif isinstance(v, dict):
|
1592
|
+
mapping = getattr(settings, k)
|
1593
|
+
for key, value in v.items():
|
1594
|
+
# we only support dicts with string values for now
|
1595
|
+
mapping.value[key] = value
|
1596
|
+
elif isinstance(v, RunMoment):
|
1597
|
+
getattr(settings, k).CopyFrom(
|
1598
|
+
wandb_settings_pb2.RunMoment(
|
1599
|
+
run=v.run,
|
1600
|
+
value=v.value,
|
1601
|
+
metric=v.metric,
|
1602
|
+
)
|
1603
|
+
)
|
1604
|
+
elif v is None:
|
1605
|
+
# None is the default value for all settings, so we don't need to set it,
|
1606
|
+
# i.e. None means that the value was not set.
|
1607
|
+
pass
|
1608
|
+
else:
|
1609
|
+
raise TypeError(f"Unsupported type {type(v)} for setting {k}")
|
1610
|
+
# TODO: store property sources in the protobuf so that we can reconstruct the
|
1611
|
+
# settings object from the protobuf
|
1612
|
+
return settings
|
1613
|
+
|
1614
|
+
# apply settings from different sources
|
1615
|
+
# TODO(dd): think about doing some|all of that at init
|
1616
|
+
def _apply_settings(
|
1617
|
+
self,
|
1618
|
+
settings: "Settings",
|
1619
|
+
_logger: Optional[_EarlyLogger] = None,
|
1620
|
+
) -> None:
|
1621
|
+
"""Apply settings from a Settings object."""
|
1622
|
+
if _logger is not None:
|
1623
|
+
_logger.info(f"Applying settings from {settings}")
|
1624
|
+
attributes = {
|
1625
|
+
k: v for k, v in settings.__dict__.items() if isinstance(v, Property)
|
1626
|
+
}
|
1627
|
+
# update properties that have deps or are dependent on in the topologically-sorted order
|
1628
|
+
for prop in self.__modification_order:
|
1629
|
+
self.update({prop: attributes[prop]._value}, source=attributes[prop].source)
|
1630
|
+
attributes.pop(prop)
|
1631
|
+
# update the remaining properties
|
1632
|
+
for k, v in attributes.items():
|
1633
|
+
# note that only the same/higher priority settings are propagated
|
1634
|
+
self.update({k: v._value}, source=v.source)
|
1635
|
+
|
1636
|
+
@staticmethod
|
1637
|
+
def _load_config_file(file_name: str, section: str = "default") -> dict:
|
1638
|
+
parser = configparser.ConfigParser()
|
1639
|
+
parser.add_section(section)
|
1640
|
+
parser.read(file_name)
|
1641
|
+
config: Dict[str, Any] = dict()
|
1642
|
+
for k in parser[section]:
|
1643
|
+
config[k] = parser[section][k]
|
1644
|
+
# TODO (cvp): we didn't do this in the old cli, but it seems necessary
|
1645
|
+
if k == "ignore_globs":
|
1646
|
+
config[k] = config[k].split(",")
|
1647
|
+
return config
|
1648
|
+
|
1649
|
+
def _apply_base(self, pid: int, _logger: Optional[_EarlyLogger] = None) -> None:
|
1650
|
+
if _logger is not None:
|
1651
|
+
_logger.info(f"Current SDK version is {wandb.__version__}")
|
1652
|
+
_logger.info(f"Configure stats pid to {pid}")
|
1653
|
+
self.update({"_stats_pid": pid}, source=Source.SETUP)
|
1654
|
+
|
1655
|
+
def _apply_config_files(self, _logger: Optional[_EarlyLogger] = None) -> None:
|
1656
|
+
# TODO(jhr): permit setting of config in system and workspace
|
1657
|
+
if self.settings_system is not None:
|
1658
|
+
if _logger is not None:
|
1659
|
+
_logger.info(f"Loading settings from {self.settings_system}")
|
1660
|
+
self.update(
|
1661
|
+
self._load_config_file(self.settings_system),
|
1662
|
+
source=Source.SYSTEM,
|
1663
|
+
)
|
1664
|
+
if self.settings_workspace is not None:
|
1665
|
+
if _logger is not None:
|
1666
|
+
_logger.info(f"Loading settings from {self.settings_workspace}")
|
1667
|
+
self.update(
|
1668
|
+
self._load_config_file(self.settings_workspace),
|
1669
|
+
source=Source.WORKSPACE,
|
1670
|
+
)
|
1671
|
+
|
1672
|
+
def _apply_env_vars(
|
1673
|
+
self,
|
1674
|
+
environ: Mapping[str, Any],
|
1675
|
+
_logger: Optional[_EarlyLogger] = None,
|
1676
|
+
) -> None:
|
1677
|
+
env_prefix: str = "WANDB_"
|
1678
|
+
special_env_var_names = {
|
1679
|
+
"WANDB_TRACELOG": "_tracelog",
|
1680
|
+
"WANDB_DISABLE_SERVICE": "_disable_service",
|
1681
|
+
"WANDB_SERVICE_TRANSPORT": "_service_transport",
|
1682
|
+
"WANDB_DIR": "root_dir",
|
1683
|
+
"WANDB_NAME": "run_name",
|
1684
|
+
"WANDB_NOTES": "run_notes",
|
1685
|
+
"WANDB_TAGS": "run_tags",
|
1686
|
+
"WANDB_JOB_TYPE": "run_job_type",
|
1687
|
+
"WANDB_HTTP_TIMEOUT": "_graphql_timeout_seconds",
|
1688
|
+
"WANDB_FILE_PUSHER_TIMEOUT": "_file_transfer_timeout_seconds",
|
1689
|
+
"WANDB_USER_EMAIL": "email",
|
1690
|
+
}
|
1691
|
+
env = dict()
|
1692
|
+
for setting, value in environ.items():
|
1693
|
+
if not setting.startswith(env_prefix):
|
1694
|
+
continue
|
1695
|
+
|
1696
|
+
if setting in special_env_var_names:
|
1697
|
+
key = special_env_var_names[setting]
|
1698
|
+
else:
|
1699
|
+
# otherwise, strip the prefix and convert to lowercase
|
1700
|
+
key = setting[len(env_prefix) :].lower()
|
1701
|
+
|
1702
|
+
if key in self.__dict__:
|
1703
|
+
if key in ("ignore_globs", "run_tags"):
|
1704
|
+
value = value.split(",")
|
1705
|
+
env[key] = value
|
1706
|
+
elif _logger is not None:
|
1707
|
+
_logger.warning(f"Unknown environment variable: {setting}")
|
1708
|
+
|
1709
|
+
if _logger is not None:
|
1710
|
+
_logger.info(
|
1711
|
+
f"Loading settings from environment variables: {_redact_dict(env)}"
|
1712
|
+
)
|
1713
|
+
self.update(env, source=Source.ENV)
|
1714
|
+
|
1715
|
+
def _infer_settings_from_environment(
|
1716
|
+
self, _logger: Optional[_EarlyLogger] = None
|
1717
|
+
) -> None:
|
1718
|
+
"""Modify settings based on environment (for runs and cli)."""
|
1719
|
+
settings: Dict[str, Union[bool, str, Sequence, None]] = dict()
|
1720
|
+
# disable symlinks if on windows (requires admin or developer setup)
|
1721
|
+
settings["symlink"] = True
|
1722
|
+
if self._windows:
|
1723
|
+
settings["symlink"] = False
|
1724
|
+
|
1725
|
+
# TODO(jhr): this needs to be moved last in setting up settings ?
|
1726
|
+
# (dd): loading order does not matter as long as source is set correctly
|
1727
|
+
|
1728
|
+
# For code saving, only allow env var override if value from server is true, or
|
1729
|
+
# if no preference was specified.
|
1730
|
+
if (self.save_code is True or self.save_code is None) and (
|
1731
|
+
os.getenv(wandb.env.SAVE_CODE) is not None
|
1732
|
+
or os.getenv(wandb.env.DISABLE_CODE) is not None
|
1733
|
+
):
|
1734
|
+
settings["save_code"] = wandb.env.should_save_code()
|
1735
|
+
|
1736
|
+
settings["disable_git"] = wandb.env.disable_git()
|
1737
|
+
|
1738
|
+
# Attempt to get notebook information if not already set by the user
|
1739
|
+
if self._jupyter and (self.notebook_name is None or self.notebook_name == ""):
|
1740
|
+
meta = wandb.jupyter.notebook_metadata(self.silent) # type: ignore
|
1741
|
+
settings["_jupyter_path"] = meta.get("path")
|
1742
|
+
settings["_jupyter_name"] = meta.get("name")
|
1743
|
+
settings["_jupyter_root"] = meta.get("root")
|
1744
|
+
elif (
|
1745
|
+
self._jupyter
|
1746
|
+
and self.notebook_name is not None
|
1747
|
+
and os.path.exists(self.notebook_name)
|
1748
|
+
):
|
1749
|
+
settings["_jupyter_path"] = self.notebook_name
|
1750
|
+
settings["_jupyter_name"] = self.notebook_name
|
1751
|
+
settings["_jupyter_root"] = os.getcwd()
|
1752
|
+
elif self._jupyter:
|
1753
|
+
wandb.termwarn(
|
1754
|
+
"WANDB_NOTEBOOK_NAME should be a path to a notebook file, "
|
1755
|
+
f"couldn't find {self.notebook_name}.",
|
1756
|
+
)
|
1757
|
+
|
1758
|
+
# host and username are populated by apply_env_vars if corresponding env
|
1759
|
+
# vars exist -- but if they don't, we'll fill them in here
|
1760
|
+
if self.host is None:
|
1761
|
+
settings["host"] = socket.gethostname() # type: ignore
|
1762
|
+
|
1763
|
+
if self.username is None:
|
1764
|
+
try: # type: ignore
|
1765
|
+
settings["username"] = getpass.getuser()
|
1766
|
+
except KeyError:
|
1767
|
+
# getuser() could raise KeyError in restricted environments like
|
1768
|
+
# chroot jails or docker containers. Return user id in these cases.
|
1769
|
+
settings["username"] = str(os.getuid())
|
1770
|
+
|
1771
|
+
_executable = (
|
1772
|
+
self._executable
|
1773
|
+
or os.environ.get(wandb.env._EXECUTABLE)
|
1774
|
+
or sys.executable
|
1775
|
+
or shutil.which("python3")
|
1776
|
+
or "python3"
|
1777
|
+
)
|
1778
|
+
settings["_executable"] = _executable
|
1779
|
+
|
1780
|
+
settings["docker"] = wandb.env.get_docker(wandb.util.image_id_from_k8s())
|
1781
|
+
|
1782
|
+
# TODO: we should use the cuda library to collect this
|
1783
|
+
if os.path.exists("/usr/local/cuda/version.txt"):
|
1784
|
+
with open("/usr/local/cuda/version.txt") as f:
|
1785
|
+
settings["_cuda"] = f.read().split(" ")[-1].strip()
|
1786
|
+
if not self._jupyter:
|
1787
|
+
settings["_args"] = sys.argv[1:]
|
1788
|
+
settings["_os"] = platform.platform(aliased=True)
|
1789
|
+
settings["_python"] = platform.python_version()
|
1790
|
+
|
1791
|
+
if _logger is not None:
|
1792
|
+
_logger.info(
|
1793
|
+
f"Inferring settings from compute environment: {_redact_dict(settings)}"
|
1794
|
+
)
|
1795
|
+
|
1796
|
+
self.update(settings, source=Source.ENV)
|
1797
|
+
|
1798
|
+
def _infer_run_settings_from_environment(
|
1799
|
+
self,
|
1800
|
+
_logger: Optional[_EarlyLogger] = None,
|
1801
|
+
) -> None:
|
1802
|
+
"""Modify settings based on environment (for runs only)."""
|
1803
|
+
# If there's not already a program file, infer it now.
|
1804
|
+
settings: Dict[str, Union[bool, str, None]] = dict()
|
1805
|
+
program = self.program or _get_program()
|
1806
|
+
if program is not None:
|
1807
|
+
repo = GitRepo()
|
1808
|
+
root = repo.root or os.getcwd()
|
1809
|
+
|
1810
|
+
program_relpath = self.program_relpath or _get_program_relpath(
|
1811
|
+
program, repo.root, _logger=_logger
|
1812
|
+
)
|
1813
|
+
settings["program_relpath"] = program_relpath
|
1814
|
+
program_abspath = os.path.abspath(
|
1815
|
+
os.path.join(root, os.path.relpath(os.getcwd(), root), program)
|
1816
|
+
)
|
1817
|
+
if os.path.exists(program_abspath):
|
1818
|
+
settings["program_abspath"] = program_abspath
|
1819
|
+
else:
|
1820
|
+
program = "<python with no main file>"
|
1821
|
+
|
1822
|
+
settings["program"] = program
|
1823
|
+
|
1824
|
+
if _logger is not None:
|
1825
|
+
_logger.info(
|
1826
|
+
f"Inferring run settings from compute environment: {_redact_dict(settings)}"
|
1827
|
+
)
|
1828
|
+
|
1829
|
+
self.update(settings, source=Source.ENV)
|
1830
|
+
|
1831
|
+
def _apply_setup(
|
1832
|
+
self, setup_settings: Dict[str, Any], _logger: Optional[_EarlyLogger] = None
|
1833
|
+
) -> None:
|
1834
|
+
if _logger:
|
1835
|
+
_logger.info(f"Applying setup settings: {_redact_dict(setup_settings)}")
|
1836
|
+
self.update(setup_settings, source=Source.SETUP)
|
1837
|
+
|
1838
|
+
def _apply_user(
|
1839
|
+
self, user_settings: Dict[str, Any], _logger: Optional[_EarlyLogger] = None
|
1840
|
+
) -> None:
|
1841
|
+
if _logger:
|
1842
|
+
_logger.info(f"Applying user settings: {_redact_dict(user_settings)}")
|
1843
|
+
self.update(user_settings, source=Source.USER)
|
1844
|
+
|
1845
|
+
def _apply_init(self, init_settings: Dict[str, Union[str, int, None]]) -> None:
|
1846
|
+
# pop magic from init settings
|
1847
|
+
init_settings.pop("magic", None)
|
1848
|
+
|
1849
|
+
# prevent setting project, entity if in sweep
|
1850
|
+
# TODO(jhr): these should be locked elements in the future
|
1851
|
+
if self.sweep_id:
|
1852
|
+
for key in ("project", "entity", "id"):
|
1853
|
+
val = init_settings.pop(key, None)
|
1854
|
+
if val:
|
1855
|
+
wandb.termwarn(
|
1856
|
+
f"Ignored wandb.init() arg {key} when running a sweep."
|
1857
|
+
)
|
1858
|
+
if self.launch:
|
1859
|
+
if self.project is not None and init_settings.pop("project", None):
|
1860
|
+
wandb.termwarn(
|
1861
|
+
"Project is ignored when running from wandb launch context. "
|
1862
|
+
"Ignored wandb.init() arg project when running running from launch.",
|
1863
|
+
)
|
1864
|
+
for key in ("entity", "id"):
|
1865
|
+
# Init settings cannot override launch settings.
|
1866
|
+
if init_settings.pop(key, None):
|
1867
|
+
wandb.termwarn(
|
1868
|
+
"Project, entity and id are ignored when running from wandb launch context. "
|
1869
|
+
f"Ignored wandb.init() arg {key} when running running from launch.",
|
1870
|
+
)
|
1871
|
+
|
1872
|
+
# strip out items where value is None
|
1873
|
+
param_map = dict(
|
1874
|
+
name="run_name",
|
1875
|
+
id="run_id",
|
1876
|
+
tags="run_tags",
|
1877
|
+
group="run_group",
|
1878
|
+
job_type="run_job_type",
|
1879
|
+
notes="run_notes",
|
1880
|
+
dir="root_dir",
|
1881
|
+
sweep_id="sweep_id",
|
1882
|
+
)
|
1883
|
+
init_settings = {
|
1884
|
+
param_map.get(k, k): v for k, v in init_settings.items() if v is not None
|
1885
|
+
}
|
1886
|
+
# fun logic to convert the resume init arg
|
1887
|
+
if init_settings.get("resume"):
|
1888
|
+
if isinstance(init_settings["resume"], str):
|
1889
|
+
if init_settings["resume"] not in ("allow", "must", "never", "auto"):
|
1890
|
+
if init_settings.get("run_id") is None:
|
1891
|
+
# TODO: deprecate or don't support
|
1892
|
+
init_settings["run_id"] = init_settings["resume"]
|
1893
|
+
init_settings["resume"] = "allow"
|
1894
|
+
elif init_settings["resume"] is True:
|
1895
|
+
# todo: add deprecation warning, switch to literal strings for resume
|
1896
|
+
init_settings["resume"] = "auto"
|
1897
|
+
|
1898
|
+
# update settings
|
1899
|
+
self.update(init_settings, source=Source.INIT)
|
1900
|
+
self._handle_fork_logic()
|
1901
|
+
self._handle_rewind_logic()
|
1902
|
+
self._handle_resume_logic()
|
1903
|
+
|
1904
|
+
def _handle_fork_logic(self) -> None:
|
1905
|
+
if self.fork_from is None:
|
1906
|
+
return
|
1907
|
+
|
1908
|
+
if self.run_id is not None and (self.fork_from.run == self.run_id):
|
1909
|
+
raise ValueError(
|
1910
|
+
"Provided `run_id` is the same as the run to `fork_from`. "
|
1911
|
+
"Please provide a different `run_id` or remove the `run_id` argument. "
|
1912
|
+
"If you want to rewind the current run, please use `resume_from` instead."
|
1913
|
+
)
|
1914
|
+
|
1915
|
+
def _handle_rewind_logic(self) -> None:
|
1916
|
+
if self.resume_from is None:
|
1917
|
+
return
|
1918
|
+
|
1919
|
+
if self.run_id is not None and (self.resume_from.run != self.run_id):
|
1920
|
+
wandb.termwarn(
|
1921
|
+
"Both `run_id` and `resume_from` have been specified with different ids. "
|
1922
|
+
"`run_id` will be ignored."
|
1923
|
+
)
|
1924
|
+
self.update({"run_id": self.resume_from.run}, source=Source.INIT)
|
1925
|
+
|
1926
|
+
def _handle_resume_logic(self) -> None:
|
1927
|
+
# handle auto resume logic
|
1928
|
+
if self.resume == "auto":
|
1929
|
+
if os.path.exists(self.resume_fname):
|
1930
|
+
with open(self.resume_fname) as f:
|
1931
|
+
resume_run_id = json.load(f)["run_id"]
|
1932
|
+
if self.run_id is None:
|
1933
|
+
self.update({"run_id": resume_run_id}, source=Source.INIT) # type: ignore
|
1934
|
+
elif self.run_id != resume_run_id:
|
1935
|
+
wandb.termwarn(
|
1936
|
+
"Tried to auto resume run with "
|
1937
|
+
f"id {resume_run_id} but id {self.run_id} is set.",
|
1938
|
+
)
|
1939
|
+
|
1940
|
+
self.update({"run_id": self.run_id or generate_id()}, source=Source.INIT)
|
1941
|
+
# persist our run id in case of failure
|
1942
|
+
# check None for mypy
|
1943
|
+
if self.resume == "auto" and self.resume_fname is not None:
|
1944
|
+
filesystem.mkdir_exists_ok(self.wandb_dir)
|
1945
|
+
with open(self.resume_fname, "w") as f:
|
1946
|
+
f.write(json.dumps({"run_id": self.run_id}))
|
1947
|
+
|
1948
|
+
def _apply_login(
|
1949
|
+
self,
|
1950
|
+
login_settings: Dict[str, Any],
|
1951
|
+
_logger: Optional[_EarlyLogger] = None,
|
1952
|
+
) -> None:
|
1953
|
+
key_map = {
|
1954
|
+
"key": "api_key",
|
1955
|
+
"host": "base_url",
|
1956
|
+
"timeout": "login_timeout",
|
1957
|
+
}
|
1958
|
+
|
1959
|
+
# Rename keys and keep only the non-None values.
|
1960
|
+
#
|
1961
|
+
# The input keys are parameters to wandb.login(), but we use different
|
1962
|
+
# names for some of them in Settings.
|
1963
|
+
login_settings = {
|
1964
|
+
key_map.get(key, key): value
|
1965
|
+
for key, value in login_settings.items()
|
1966
|
+
if value is not None
|
1967
|
+
}
|
1968
|
+
|
1969
|
+
if _logger:
|
1970
|
+
_logger.info(f"Applying login settings: {_redact_dict(login_settings)}")
|
1971
|
+
|
1972
|
+
self.update(
|
1973
|
+
login_settings,
|
1974
|
+
source=Source.LOGIN,
|
1975
|
+
)
|
1976
|
+
|
1977
|
+
def _apply_run_start(self, run_start_settings: Dict[str, Any]) -> None:
|
1978
|
+
# This dictionary maps from the "run message dict" to relevant fields in settings
|
1979
|
+
# Note: that config is missing
|
1980
|
+
param_map = {
|
1981
|
+
"run_id": "run_id",
|
1982
|
+
"entity": "entity",
|
1983
|
+
"project": "project",
|
1984
|
+
"run_group": "run_group",
|
1985
|
+
"job_type": "run_job_type",
|
1986
|
+
"display_name": "run_name",
|
1987
|
+
"notes": "run_notes",
|
1988
|
+
"tags": "run_tags",
|
1989
|
+
"sweep_id": "sweep_id",
|
1990
|
+
"host": "host",
|
1991
|
+
"resumed": "resumed",
|
1992
|
+
"git.remote_url": "git_remote_url",
|
1993
|
+
"git.commit": "git_commit",
|
1994
|
+
}
|
1995
|
+
run_settings = {
|
1996
|
+
name: reduce(lambda d, k: d.get(k, {}), attr.split("."), run_start_settings)
|
1997
|
+
for attr, name in param_map.items()
|
1998
|
+
}
|
1999
|
+
run_settings = {key: value for key, value in run_settings.items() if value}
|
2000
|
+
if run_settings:
|
2001
|
+
self.update(run_settings, source=Source.RUN)
|