wandb 0.21.0__py3-none-win_amd64.whl → 0.21.1__py3-none-win_amd64.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.
- wandb/__init__.py +16 -14
- wandb/__init__.pyi +427 -450
- wandb/agents/pyagent.py +41 -12
- wandb/analytics/sentry.py +7 -2
- wandb/apis/importers/mlflow.py +1 -1
- wandb/apis/public/__init__.py +1 -1
- wandb/apis/public/api.py +526 -360
- wandb/apis/public/artifacts.py +204 -8
- wandb/apis/public/automations.py +19 -3
- wandb/apis/public/files.py +172 -33
- wandb/apis/public/history.py +67 -15
- wandb/apis/public/integrations.py +25 -2
- wandb/apis/public/jobs.py +90 -2
- wandb/apis/public/projects.py +130 -79
- wandb/apis/public/query_generator.py +11 -1
- wandb/apis/public/registries/registries_search.py +7 -15
- wandb/apis/public/reports.py +83 -5
- wandb/apis/public/runs.py +299 -105
- wandb/apis/public/sweeps.py +222 -22
- wandb/apis/public/teams.py +41 -4
- wandb/apis/public/users.py +45 -4
- wandb/beta/workflows.py +66 -30
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +80 -1
- wandb/env.py +8 -0
- wandb/errors/errors.py +4 -1
- wandb/integration/lightning/fabric/logger.py +3 -4
- wandb/integration/metaflow/__init__.py +6 -0
- wandb/integration/metaflow/data_pandas.py +74 -0
- wandb/integration/metaflow/errors.py +13 -0
- wandb/integration/metaflow/metaflow.py +205 -190
- wandb/integration/openai/fine_tuning.py +1 -2
- wandb/jupyter.py +5 -5
- wandb/plot/custom_chart.py +30 -7
- wandb/proto/v3/wandb_internal_pb2.py +280 -280
- wandb/proto/v3/wandb_telemetry_pb2.py +4 -4
- wandb/proto/v4/wandb_internal_pb2.py +280 -280
- wandb/proto/v4/wandb_telemetry_pb2.py +4 -4
- wandb/proto/v5/wandb_internal_pb2.py +280 -280
- wandb/proto/v5/wandb_telemetry_pb2.py +4 -4
- wandb/proto/v6/wandb_internal_pb2.py +280 -280
- wandb/proto/v6/wandb_telemetry_pb2.py +4 -4
- wandb/proto/wandb_deprecated.py +6 -0
- wandb/sdk/artifacts/_internal_artifact.py +19 -8
- wandb/sdk/artifacts/_validators.py +8 -0
- wandb/sdk/artifacts/artifact.py +106 -75
- wandb/sdk/data_types/audio.py +38 -10
- wandb/sdk/data_types/base_types/media.py +6 -56
- wandb/sdk/data_types/graph.py +48 -14
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +1 -3
- wandb/sdk/data_types/helper_types/image_mask.py +1 -3
- wandb/sdk/data_types/histogram.py +34 -21
- wandb/sdk/data_types/html.py +35 -12
- wandb/sdk/data_types/image.py +104 -68
- wandb/sdk/data_types/molecule.py +32 -19
- wandb/sdk/data_types/object_3d.py +36 -17
- wandb/sdk/data_types/plotly.py +18 -5
- wandb/sdk/data_types/saved_model.py +4 -6
- wandb/sdk/data_types/table.py +59 -30
- wandb/sdk/data_types/video.py +53 -26
- wandb/sdk/integration_utils/auto_logging.py +2 -2
- wandb/sdk/internal/internal_api.py +6 -0
- wandb/sdk/internal/job_builder.py +6 -0
- wandb/sdk/launch/agent/agent.py +8 -1
- wandb/sdk/launch/agent/run_queue_item_file_saver.py +2 -2
- wandb/sdk/launch/create_job.py +3 -1
- wandb/sdk/launch/inputs/internal.py +3 -4
- wandb/sdk/launch/inputs/schema.py +1 -0
- wandb/sdk/launch/runner/kubernetes_monitor.py +1 -0
- wandb/sdk/launch/runner/kubernetes_runner.py +328 -1
- wandb/sdk/launch/sweeps/scheduler.py +2 -3
- wandb/sdk/lib/asyncio_compat.py +3 -0
- wandb/sdk/lib/deprecate.py +1 -7
- wandb/sdk/lib/disabled.py +1 -1
- wandb/sdk/lib/hashutil.py +14 -1
- wandb/sdk/lib/module.py +7 -13
- wandb/sdk/lib/progress.py +0 -19
- wandb/sdk/lib/sock_client.py +0 -4
- wandb/sdk/wandb_init.py +66 -91
- wandb/sdk/wandb_login.py +18 -14
- wandb/sdk/wandb_metric.py +2 -0
- wandb/sdk/wandb_run.py +406 -414
- wandb/sdk/wandb_settings.py +130 -2
- wandb/sdk/wandb_setup.py +28 -28
- wandb/sdk/wandb_sweep.py +14 -13
- wandb/sdk/wandb_watch.py +4 -6
- wandb/sync/sync.py +10 -0
- wandb/util.py +57 -0
- wandb/wandb_run.py +1 -2
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/METADATA +1 -1
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/RECORD +95 -95
- wandb/vendor/pynvml/__init__.py +0 -0
- wandb/vendor/pynvml/pynvml.py +0 -4779
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/WHEEL +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/entry_points.txt +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/licenses/LICENSE +0 -0
wandb/apis/public/jobs.py
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Public API
|
1
|
+
"""W&B Public API for management Launch Jobs and Launch Queues.
|
2
|
+
|
3
|
+
This module provides classes for managing W&B jobs, queued runs, and run
|
4
|
+
queues.
|
5
|
+
"""
|
2
6
|
|
3
7
|
import json
|
4
8
|
import os
|
@@ -78,6 +82,7 @@ class Job:
|
|
78
82
|
|
79
83
|
@property
|
80
84
|
def name(self):
|
85
|
+
"""The name of the job."""
|
81
86
|
return self._name
|
82
87
|
|
83
88
|
def _set_configure_launch_project(self, func):
|
@@ -162,6 +167,7 @@ class Job:
|
|
162
167
|
launch_project.set_job_entry_point(self._entrypoint)
|
163
168
|
|
164
169
|
def set_entrypoint(self, entrypoint: List[str]):
|
170
|
+
"""Set the entrypoint for the job."""
|
165
171
|
self._entrypoint = entrypoint
|
166
172
|
|
167
173
|
def call(
|
@@ -176,6 +182,29 @@ class Job:
|
|
176
182
|
project_queue=None,
|
177
183
|
priority=None,
|
178
184
|
):
|
185
|
+
"""Call the job with the given configuration.
|
186
|
+
|
187
|
+
Args:
|
188
|
+
config (dict): The configuration to pass to the job.
|
189
|
+
This should be a dictionary containing key-value pairs that
|
190
|
+
match the input types defined in the job.
|
191
|
+
project (str, optional): The project to log the run to. Defaults
|
192
|
+
to the job's project.
|
193
|
+
entity (str, optional): The entity to log the run under. Defaults
|
194
|
+
to the job's entity.
|
195
|
+
queue (str, optional): The name of the queue to enqueue the job to.
|
196
|
+
Defaults to None.
|
197
|
+
resource (str, optional): The resource type to use for execution.
|
198
|
+
Defaults to "local-container".
|
199
|
+
resource_args (dict, optional): Additional arguments for the
|
200
|
+
resource type. Defaults to None.
|
201
|
+
template_variables (dict, optional): Template variables to use for
|
202
|
+
the job. Defaults to None.
|
203
|
+
project_queue (str, optional): The project that manages the queue.
|
204
|
+
Defaults to None.
|
205
|
+
priority (int, optional): The priority of the queued run.
|
206
|
+
Defaults to None.
|
207
|
+
"""
|
179
208
|
from wandb.sdk.launch import _launch_add
|
180
209
|
|
181
210
|
run_config = {}
|
@@ -212,7 +241,19 @@ class Job:
|
|
212
241
|
|
213
242
|
|
214
243
|
class QueuedRun:
|
215
|
-
"""A single queued run associated with an entity and project.
|
244
|
+
"""A single queued run associated with an entity and project.
|
245
|
+
|
246
|
+
Args:
|
247
|
+
entity: The entity associated with the queued run.
|
248
|
+
project (str): The project where runs executed by the queue are logged to.
|
249
|
+
queue_name (str): The name of the queue.
|
250
|
+
run_queue_item_id (int): The id of the run queue item.
|
251
|
+
project_queue (str): The project that manages the queue.
|
252
|
+
priority (str): The priority of the queued run.
|
253
|
+
|
254
|
+
Call `run = queued_run.wait_until_running()` or
|
255
|
+
`run = queued_run.wait_until_finished()` to access the run.
|
256
|
+
"""
|
216
257
|
|
217
258
|
def __init__(
|
218
259
|
self,
|
@@ -236,22 +277,27 @@ class QueuedRun:
|
|
236
277
|
|
237
278
|
@property
|
238
279
|
def queue_name(self):
|
280
|
+
"""The name of the queue."""
|
239
281
|
return self._queue_name
|
240
282
|
|
241
283
|
@property
|
242
284
|
def id(self):
|
285
|
+
"""The id of the queued run."""
|
243
286
|
return self._run_queue_item_id
|
244
287
|
|
245
288
|
@property
|
246
289
|
def project(self):
|
290
|
+
"""The project associated with the queued run."""
|
247
291
|
return self._project
|
248
292
|
|
249
293
|
@property
|
250
294
|
def entity(self):
|
295
|
+
"""The entity associated with the queued run."""
|
251
296
|
return self._entity
|
252
297
|
|
253
298
|
@property
|
254
299
|
def state(self):
|
300
|
+
"""The state of the queued run."""
|
255
301
|
item = self._get_item()
|
256
302
|
if item:
|
257
303
|
return item["state"].lower()
|
@@ -327,6 +373,7 @@ class QueuedRun:
|
|
327
373
|
|
328
374
|
@normalize_exceptions
|
329
375
|
def wait_until_finished(self):
|
376
|
+
"""Wait for the queued run to complete and return the finished run."""
|
330
377
|
if not self._run:
|
331
378
|
self.wait_until_running()
|
332
379
|
|
@@ -388,6 +435,7 @@ class QueuedRun:
|
|
388
435
|
|
389
436
|
@normalize_exceptions
|
390
437
|
def wait_until_running(self):
|
438
|
+
"""Wait until the queued run is running and return the run."""
|
391
439
|
if self._run is not None:
|
392
440
|
return self._run
|
393
441
|
|
@@ -426,6 +474,20 @@ RunQueuePrioritizationMode = Literal["DISABLED", "V0"]
|
|
426
474
|
|
427
475
|
|
428
476
|
class RunQueue:
|
477
|
+
"""Class that represents a run queue in W&B.
|
478
|
+
|
479
|
+
Args:
|
480
|
+
client: W&B API client instance.
|
481
|
+
name: Name of the run queue
|
482
|
+
entity: The entity (user or team) that owns this queue
|
483
|
+
prioritization_mode: Queue priority mode
|
484
|
+
Can be "DISABLED" or "V0". Defaults to `None`.
|
485
|
+
_access: Access level for the queue
|
486
|
+
Can be "project" or "user". Defaults to `None`.
|
487
|
+
_default_resource_config_id: ID of default resource config
|
488
|
+
_default_resource_config: Default resource configuration
|
489
|
+
"""
|
490
|
+
|
429
491
|
def __init__(
|
430
492
|
self,
|
431
493
|
client: "RetryingClient",
|
@@ -450,32 +512,41 @@ class RunQueue:
|
|
450
512
|
|
451
513
|
@property
|
452
514
|
def name(self):
|
515
|
+
"""The name of the queue."""
|
453
516
|
return self._name
|
454
517
|
|
455
518
|
@property
|
456
519
|
def entity(self):
|
520
|
+
"""The entity that owns the queue."""
|
457
521
|
return self._entity
|
458
522
|
|
459
523
|
@property
|
460
524
|
def prioritization_mode(self) -> RunQueuePrioritizationMode:
|
525
|
+
"""The prioritization mode of the queue.
|
526
|
+
|
527
|
+
Can be set to "DISABLED" or "V0".
|
528
|
+
"""
|
461
529
|
if self._prioritization_mode is None:
|
462
530
|
self._get_metadata()
|
463
531
|
return self._prioritization_mode
|
464
532
|
|
465
533
|
@property
|
466
534
|
def access(self) -> RunQueueAccessType:
|
535
|
+
"""The access level of the queue."""
|
467
536
|
if self._access is None:
|
468
537
|
self._get_metadata()
|
469
538
|
return self._access
|
470
539
|
|
471
540
|
@property
|
472
541
|
def external_links(self) -> Dict[str, str]:
|
542
|
+
"""External resource links for the queue."""
|
473
543
|
if self._external_links is None:
|
474
544
|
self._get_metadata()
|
475
545
|
return self._external_links
|
476
546
|
|
477
547
|
@property
|
478
548
|
def type(self) -> RunQueueResourceType:
|
549
|
+
"""The resource type for execution."""
|
479
550
|
if self._type is None:
|
480
551
|
if self._default_resource_config_id is None:
|
481
552
|
self._get_metadata()
|
@@ -484,6 +555,7 @@ class RunQueue:
|
|
484
555
|
|
485
556
|
@property
|
486
557
|
def default_resource_config(self):
|
558
|
+
"""The default configuration for resources."""
|
487
559
|
if self._default_resource_config is None:
|
488
560
|
if self._default_resource_config_id is None:
|
489
561
|
self._get_metadata()
|
@@ -492,6 +564,7 @@ class RunQueue:
|
|
492
564
|
|
493
565
|
@property
|
494
566
|
def template_variables(self):
|
567
|
+
"""Variables for resource templates."""
|
495
568
|
if self._template_variables is None:
|
496
569
|
if self._default_resource_config_id is None:
|
497
570
|
self._get_metadata()
|
@@ -500,6 +573,7 @@ class RunQueue:
|
|
500
573
|
|
501
574
|
@property
|
502
575
|
def id(self) -> str:
|
576
|
+
"""The id of the queue."""
|
503
577
|
if self._id is None:
|
504
578
|
self._get_metadata()
|
505
579
|
return self._id
|
@@ -648,6 +722,20 @@ class RunQueue:
|
|
648
722
|
config: Optional[dict] = None,
|
649
723
|
template_variables: Optional[dict] = None,
|
650
724
|
) -> "RunQueue":
|
725
|
+
"""Create a RunQueue.
|
726
|
+
|
727
|
+
Args:
|
728
|
+
name: The name of the run queue to create.
|
729
|
+
resource: The resource type for execution.
|
730
|
+
entity: The entity (user or team) that will own the queue.
|
731
|
+
Defaults to the default entity of the API client.
|
732
|
+
prioritization_mode: The prioritization mode for the queue.
|
733
|
+
Can be "DISABLED" or "V0". Defaults to None.
|
734
|
+
config: Optional dictionary for the default resource
|
735
|
+
configuration. Defaults to None.
|
736
|
+
template_variables: Optional dictionary for template variables
|
737
|
+
used in the resource configuration.
|
738
|
+
"""
|
651
739
|
public_api = Api()
|
652
740
|
return public_api.create_run_queue(
|
653
741
|
name, resource, entity, prioritization_mode, config, template_variables
|
wandb/apis/public/projects.py
CHANGED
@@ -1,6 +1,35 @@
|
|
1
|
-
"""Public API
|
1
|
+
"""W&B Public API for Project objects.
|
2
2
|
|
3
|
-
|
3
|
+
This module provides classes for interacting with W&B projects and their
|
4
|
+
associated data.
|
5
|
+
|
6
|
+
Example:
|
7
|
+
```python
|
8
|
+
from wandb.apis.public import Api
|
9
|
+
|
10
|
+
# Get all projects for an entity
|
11
|
+
projects = Api().projects("entity")
|
12
|
+
|
13
|
+
# Access project data
|
14
|
+
for project in projects:
|
15
|
+
print(f"Project: {project.name}")
|
16
|
+
print(f"URL: {project.url}")
|
17
|
+
|
18
|
+
# Get artifact types
|
19
|
+
for artifact_type in project.artifacts_types():
|
20
|
+
print(f"Artifact Type: {artifact_type.name}")
|
21
|
+
|
22
|
+
# Get sweeps
|
23
|
+
for sweep in project.sweeps():
|
24
|
+
print(f"Sweep ID: {sweep.id}")
|
25
|
+
print(f"State: {sweep.state}")
|
26
|
+
```
|
27
|
+
|
28
|
+
Note:
|
29
|
+
This module is part of the W&B Public API and provides methods to access
|
30
|
+
and manage projects. For creating new projects, use wandb.init()
|
31
|
+
with a new project name.
|
32
|
+
"""
|
4
33
|
|
5
34
|
from requests import HTTPError
|
6
35
|
from wandb_gql import gql
|
@@ -10,6 +39,7 @@ from wandb.apis.attrs import Attrs
|
|
10
39
|
from wandb.apis.normalize import normalize_exceptions
|
11
40
|
from wandb.apis.paginator import Paginator
|
12
41
|
from wandb.apis.public.api import RetryingClient
|
42
|
+
from wandb.apis.public.sweeps import Sweeps
|
13
43
|
from wandb.sdk.lib import ipython
|
14
44
|
|
15
45
|
PROJECT_FRAGMENT = """fragment ProjectFragment on Project {
|
@@ -22,10 +52,32 @@ PROJECT_FRAGMENT = """fragment ProjectFragment on Project {
|
|
22
52
|
|
23
53
|
|
24
54
|
class Projects(Paginator["Project"]):
|
25
|
-
"""An
|
55
|
+
"""An lazy iterator of `Project` objects.
|
26
56
|
|
27
|
-
|
28
|
-
|
57
|
+
An iterable interface to access projects created and saved by the entity.
|
58
|
+
|
59
|
+
Args:
|
60
|
+
client (`wandb.apis.internal.Api`): The API client instance to use.
|
61
|
+
entity (str): The entity name (username or team) to fetch projects for.
|
62
|
+
per_page (int): Number of projects to fetch per request (default is 50).
|
63
|
+
|
64
|
+
Example:
|
65
|
+
```python
|
66
|
+
from wandb.apis.public.api import Api
|
67
|
+
|
68
|
+
# Find projects that belong to this entity
|
69
|
+
projects = Api().projects(entity="entity")
|
70
|
+
|
71
|
+
# Iterate over files
|
72
|
+
for project in projects:
|
73
|
+
print(f"Project: {project.name}")
|
74
|
+
print(f"- URL: {project.url}")
|
75
|
+
print(f"- Created at: {project.created_at}")
|
76
|
+
print(f"- Is benchmark: {project.is_benchmark}")
|
77
|
+
```
|
78
|
+
"""
|
79
|
+
|
80
|
+
QUERY = gql(f"""#graphql
|
29
81
|
query Projects($entity: String, $cursor: String, $perPage: Int = 50) {{
|
30
82
|
models(entityName: $entity, after: $cursor, first: $perPage) {{
|
31
83
|
edges {{
|
@@ -40,9 +92,8 @@ class Projects(Paginator["Project"]):
|
|
40
92
|
}}
|
41
93
|
}}
|
42
94
|
}}
|
43
|
-
{}
|
44
|
-
|
45
|
-
)
|
95
|
+
{PROJECT_FRAGMENT}
|
96
|
+
""")
|
46
97
|
|
47
98
|
def __init__(
|
48
99
|
self,
|
@@ -66,11 +117,22 @@ class Projects(Paginator["Project"]):
|
|
66
117
|
|
67
118
|
@property
|
68
119
|
def length(self) -> None:
|
120
|
+
"""Returns the total number of projects.
|
121
|
+
|
122
|
+
Note: This property is not available for projects.
|
123
|
+
|
124
|
+
<!-- lazydoc-ignore: internal -->
|
125
|
+
"""
|
69
126
|
# For backwards compatibility, even though this isn't a SizedPaginator
|
70
127
|
return None
|
71
128
|
|
72
129
|
@property
|
73
130
|
def more(self):
|
131
|
+
"""Returns `True` if there are more projects to fetch. Returns
|
132
|
+
`False` if there are no more projects to fetch.
|
133
|
+
|
134
|
+
<!-- lazydoc-ignore: internal -->
|
135
|
+
"""
|
74
136
|
if self.last_response:
|
75
137
|
return self.last_response["models"]["pageInfo"]["hasNextPage"]
|
76
138
|
else:
|
@@ -78,12 +140,20 @@ class Projects(Paginator["Project"]):
|
|
78
140
|
|
79
141
|
@property
|
80
142
|
def cursor(self):
|
143
|
+
"""Returns the cursor position for pagination of project results.
|
144
|
+
|
145
|
+
<!-- lazydoc-ignore: internal -->
|
146
|
+
"""
|
81
147
|
if self.last_response:
|
82
148
|
return self.last_response["models"]["edges"][-1]["cursor"]
|
83
149
|
else:
|
84
150
|
return None
|
85
151
|
|
86
152
|
def convert_objects(self):
|
153
|
+
"""Converts GraphQL edges to File objects.
|
154
|
+
|
155
|
+
<!-- lazydoc-ignore: internal -->
|
156
|
+
"""
|
87
157
|
return [
|
88
158
|
Project(self.client, self.entity, p["node"]["name"], p["node"])
|
89
159
|
for p in self.last_response["models"]["edges"]
|
@@ -94,17 +164,22 @@ class Projects(Paginator["Project"]):
|
|
94
164
|
|
95
165
|
|
96
166
|
class Project(Attrs):
|
97
|
-
"""A project is a namespace for runs.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
167
|
+
"""A project is a namespace for runs.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
client: W&B API client instance.
|
171
|
+
name (str): The name of the project.
|
172
|
+
entity (str): The entity name that owns the project.
|
173
|
+
"""
|
174
|
+
|
175
|
+
QUERY = gql(f"""#graphql
|
176
|
+
query Project($project: String!, $entity: String!) {{
|
177
|
+
project(name: $project, entityName: $entity) {{
|
178
|
+
...ProjectFragment
|
179
|
+
}}
|
180
|
+
}}
|
181
|
+
{PROJECT_FRAGMENT}
|
182
|
+
""")
|
108
183
|
|
109
184
|
def __init__(
|
110
185
|
self,
|
@@ -122,20 +197,37 @@ class Project(Attrs):
|
|
122
197
|
attrs: The attributes of the project.
|
123
198
|
"""
|
124
199
|
super().__init__(dict(attrs))
|
200
|
+
self._is_loaded = bool(attrs)
|
125
201
|
self.client = client
|
126
202
|
self.name = project
|
127
203
|
self.entity = entity
|
128
204
|
|
205
|
+
def _load(self):
|
206
|
+
variable_values = {"project": self.name, "entity": self.entity}
|
207
|
+
try:
|
208
|
+
response = self.client.execute(self.QUERY, variable_values)
|
209
|
+
except HTTPError as e:
|
210
|
+
raise ValueError(f"Unable to fetch project ID: {variable_values!r}") from e
|
211
|
+
|
212
|
+
self._attrs = response["project"]
|
213
|
+
self._is_loaded = True
|
214
|
+
|
129
215
|
@property
|
130
216
|
def path(self):
|
217
|
+
"""Returns the path of the project. The path is a list containing the
|
218
|
+
entity and project name."""
|
131
219
|
return [self.entity, self.name]
|
132
220
|
|
133
221
|
@property
|
134
222
|
def url(self):
|
223
|
+
"""Returns the URL of the project."""
|
135
224
|
return self.client.app_url + "/".join(self.path + ["workspace"])
|
136
225
|
|
137
226
|
def to_html(self, height=420, hidden=False):
|
138
|
-
"""Generate HTML containing an iframe displaying this project.
|
227
|
+
"""Generate HTML containing an iframe displaying this project.
|
228
|
+
|
229
|
+
<!-- lazydoc-ignore: internal -->
|
230
|
+
"""
|
139
231
|
url = self.url + "?jupyter=true"
|
140
232
|
style = f"border:none;width:100%;height:{height}px;"
|
141
233
|
prefix = ""
|
@@ -152,74 +244,33 @@ class Project(Attrs):
|
|
152
244
|
|
153
245
|
@normalize_exceptions
|
154
246
|
def artifacts_types(self, per_page=50):
|
247
|
+
"""Returns all artifact types associated with this project."""
|
155
248
|
return public.ArtifactTypes(self.client, self.entity, self.name)
|
156
249
|
|
157
250
|
@normalize_exceptions
|
158
|
-
def sweeps(self):
|
159
|
-
|
160
|
-
"""
|
161
|
-
query GetSweeps($project: String!, $entity: String!) {{
|
162
|
-
project(name: $project, entityName: $entity) {{
|
163
|
-
totalSweeps
|
164
|
-
sweeps {{
|
165
|
-
edges {{
|
166
|
-
node {{
|
167
|
-
...SweepFragment
|
168
|
-
}}
|
169
|
-
cursor
|
170
|
-
}}
|
171
|
-
pageInfo {{
|
172
|
-
endCursor
|
173
|
-
hasNextPage
|
174
|
-
}}
|
175
|
-
}}
|
176
|
-
}}
|
177
|
-
}}
|
178
|
-
{}
|
179
|
-
""".format(public.SWEEP_FRAGMENT)
|
180
|
-
)
|
181
|
-
variable_values = {"project": self.name, "entity": self.entity}
|
182
|
-
ret = self.client.execute(query, variable_values)
|
183
|
-
if not ret.get("project") or ret["project"]["totalSweeps"] < 1:
|
184
|
-
return []
|
251
|
+
def sweeps(self, per_page=50):
|
252
|
+
"""Return a paginated collection of sweeps in this project.
|
185
253
|
|
186
|
-
|
187
|
-
|
188
|
-
public.Sweep(
|
189
|
-
self.client,
|
190
|
-
self.entity,
|
191
|
-
self.name,
|
192
|
-
e["node"]["name"],
|
193
|
-
)
|
194
|
-
for e in ret["project"]["sweeps"]["edges"]
|
195
|
-
]
|
254
|
+
Args:
|
255
|
+
per_page: The number of sweeps to fetch per request to the API.
|
196
256
|
|
197
|
-
|
257
|
+
Returns:
|
258
|
+
A `Sweeps` object, which is an iterable collection of `Sweep` objects.
|
198
259
|
"""
|
199
|
-
|
200
|
-
project(name: $projectName, entityName: $entityName) {
|
201
|
-
id
|
202
|
-
}
|
203
|
-
}
|
204
|
-
"""
|
205
|
-
)
|
260
|
+
return Sweeps(self.client, self.entity, self.name, per_page=per_page)
|
206
261
|
|
207
262
|
@property
|
208
263
|
def id(self) -> str:
|
209
|
-
|
210
|
-
|
211
|
-
# This is necessary if using this project as the scope of a new Automation.
|
212
|
-
with suppress(LookupError):
|
213
|
-
return self._attrs["id"]
|
264
|
+
if not self._is_loaded:
|
265
|
+
self._load()
|
214
266
|
|
215
|
-
|
216
|
-
|
217
|
-
data = self.client.execute(self._PROJECT_ID, variable_values)
|
267
|
+
if "id" not in self._attrs:
|
268
|
+
raise ValueError(f"Project {self.name} not found")
|
218
269
|
|
219
|
-
|
220
|
-
raise ValueError(f"Project {self.name} not found")
|
270
|
+
return self._attrs["id"]
|
221
271
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
272
|
+
def __getattr__(self, name: str):
|
273
|
+
if not self._is_loaded:
|
274
|
+
self._load()
|
275
|
+
|
276
|
+
return super().__getattr__(name)
|
@@ -1,5 +1,8 @@
|
|
1
1
|
class QueryGenerator:
|
2
|
-
"""QueryGenerator is a helper object to write filters for runs.
|
2
|
+
"""QueryGenerator is a helper object to write filters for runs.
|
3
|
+
|
4
|
+
<!-- lazydoc-ignore-class: internal -->
|
5
|
+
"""
|
3
6
|
|
4
7
|
INDIVIDUAL_OP_TO_MONGO = {
|
5
8
|
"!=": "$ne",
|
@@ -21,6 +24,7 @@ class QueryGenerator:
|
|
21
24
|
|
22
25
|
@classmethod
|
23
26
|
def format_order_key(cls, key: str):
|
27
|
+
"""Format a key for sorting."""
|
24
28
|
if key.startswith(("+", "-")):
|
25
29
|
direction = key[0]
|
26
30
|
key = key[1:]
|
@@ -50,6 +54,7 @@ class QueryGenerator:
|
|
50
54
|
return {self.INDIVIDUAL_OP_TO_MONGO[op]: value}
|
51
55
|
|
52
56
|
def key_to_server_path(self, key):
|
57
|
+
"""Convert a key dictionary to the corresponding server path string."""
|
53
58
|
if key["section"] == "config":
|
54
59
|
return "config." + key["name"]
|
55
60
|
elif key["section"] == "summary":
|
@@ -63,6 +68,7 @@ class QueryGenerator:
|
|
63
68
|
raise ValueError("Invalid key: {}".format(key))
|
64
69
|
|
65
70
|
def server_path_to_key(self, path):
|
71
|
+
"""Convert a server path string to the corresponding key dictionary."""
|
66
72
|
if path.startswith("config."):
|
67
73
|
return {"section": "config", "name": path.split("config.", 1)[1]}
|
68
74
|
elif path.startswith("summary_metrics."):
|
@@ -75,6 +81,7 @@ class QueryGenerator:
|
|
75
81
|
return {"section": "run", "name": path}
|
76
82
|
|
77
83
|
def keys_to_order(self, keys):
|
84
|
+
"""Convert a list of key dictionaries to an order string."""
|
78
85
|
orders = []
|
79
86
|
for key in keys["keys"]:
|
80
87
|
order = self.key_to_server_path(key["key"])
|
@@ -87,6 +94,7 @@ class QueryGenerator:
|
|
87
94
|
return orders
|
88
95
|
|
89
96
|
def order_to_keys(self, order):
|
97
|
+
"""Convert an order string to a list of key dictionaries."""
|
90
98
|
keys = []
|
91
99
|
for k in order: # orderstr.split(","):
|
92
100
|
name = k[1:]
|
@@ -127,6 +135,7 @@ class QueryGenerator:
|
|
127
135
|
return {path: self._to_mongo_op_value(filter["op"], filter["value"])}
|
128
136
|
|
129
137
|
def filter_to_mongo(self, filter):
|
138
|
+
"""Returns dictionary with filter format converted to MongoDB filter."""
|
130
139
|
if self._is_individual(filter):
|
131
140
|
return self._to_mongo_individual(filter)
|
132
141
|
elif self._is_group(filter):
|
@@ -137,6 +146,7 @@ class QueryGenerator:
|
|
137
146
|
}
|
138
147
|
|
139
148
|
def mongo_to_filter(self, filter):
|
149
|
+
"""Returns dictionary with MongoDB filter converted to filter format."""
|
140
150
|
# Returns {"op": "OR", "filters": [{"op": "AND", "filters": []}]}
|
141
151
|
if filter is None:
|
142
152
|
return None # this covers the case where self.filter_to_mongo returns None.
|
@@ -14,12 +14,13 @@ from wandb.sdk.artifacts._graphql_fragments import (
|
|
14
14
|
_gql_artifact_fragment,
|
15
15
|
_gql_registry_fragment,
|
16
16
|
)
|
17
|
+
from wandb.sdk.artifacts._validators import remove_registry_prefix
|
17
18
|
|
18
19
|
from ._utils import ensure_registry_prefix_on_names
|
19
20
|
|
20
21
|
|
21
22
|
class Registries(Paginator):
|
22
|
-
"""
|
23
|
+
"""An lazy iterator of `Registry` objects."""
|
23
24
|
|
24
25
|
QUERY = gql(
|
25
26
|
"""
|
@@ -62,9 +63,6 @@ class Registries(Paginator):
|
|
62
63
|
|
63
64
|
super().__init__(client, variables, per_page)
|
64
65
|
|
65
|
-
def __bool__(self):
|
66
|
-
return bool(self.objects)
|
67
|
-
|
68
66
|
def __next__(self):
|
69
67
|
# Implement custom next since its possible to load empty pages because of auth
|
70
68
|
self.index += 1
|
@@ -135,7 +133,7 @@ class Registries(Paginator):
|
|
135
133
|
self.client,
|
136
134
|
self.organization,
|
137
135
|
self.last_response["organization"]["orgEntity"]["name"],
|
138
|
-
r["node"]["name"],
|
136
|
+
remove_registry_prefix(r["node"]["name"]),
|
139
137
|
r["node"],
|
140
138
|
)
|
141
139
|
for r in self.last_response["organization"]["orgEntity"]["projects"][
|
@@ -144,8 +142,8 @@ class Registries(Paginator):
|
|
144
142
|
]
|
145
143
|
|
146
144
|
|
147
|
-
class Collections(Paginator):
|
148
|
-
"""
|
145
|
+
class Collections(Paginator["ArtifactCollection"]):
|
146
|
+
"""An lazy iterator of `ArtifactCollection` objects in a Registry."""
|
149
147
|
|
150
148
|
QUERY = gql(
|
151
149
|
"""
|
@@ -238,9 +236,6 @@ class Collections(Paginator):
|
|
238
236
|
|
239
237
|
super().__init__(client, variables, per_page)
|
240
238
|
|
241
|
-
def __bool__(self):
|
242
|
-
return len(self) > 0 or len(self.objects) > 0
|
243
|
-
|
244
239
|
def __next__(self):
|
245
240
|
# Implement custom next since its possible to load empty pages because of auth
|
246
241
|
self.index += 1
|
@@ -315,8 +310,8 @@ class Collections(Paginator):
|
|
315
310
|
]
|
316
311
|
|
317
312
|
|
318
|
-
class Versions(Paginator):
|
319
|
-
"""
|
313
|
+
class Versions(Paginator["Artifact"]):
|
314
|
+
"""An lazy iterator of `Artifact` objects in a Registry."""
|
320
315
|
|
321
316
|
def __init__(
|
322
317
|
self,
|
@@ -407,9 +402,6 @@ class Versions(Paginator):
|
|
407
402
|
raise StopIteration
|
408
403
|
return self.objects[self.index]
|
409
404
|
|
410
|
-
def __bool__(self):
|
411
|
-
return len(self) > 0 or len(self.objects) > 0
|
412
|
-
|
413
405
|
@property
|
414
406
|
def length(self):
|
415
407
|
if self.last_response:
|