wandb 0.20.2rc20250616__py3-none-macosx_10_14_x86_64.whl → 0.21.0__py3-none-macosx_10_14_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.
- wandb/__init__.py +1 -1
- wandb/__init__.pyi +24 -23
- wandb/apis/internal.py +3 -0
- wandb/apis/paginator.py +17 -4
- wandb/apis/public/api.py +83 -2
- wandb/apis/public/artifacts.py +10 -8
- wandb/apis/public/files.py +5 -5
- wandb/apis/public/projects.py +44 -3
- wandb/apis/public/reports.py +64 -8
- wandb/apis/public/runs.py +16 -23
- wandb/automations/__init__.py +10 -10
- wandb/automations/_filters/run_metrics.py +0 -2
- wandb/automations/_utils.py +0 -2
- wandb/automations/actions.py +0 -2
- wandb/automations/automations.py +0 -2
- wandb/automations/events.py +0 -2
- wandb/bin/gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/integration/catboost/catboost.py +6 -2
- wandb/integration/kfp/kfp_patch.py +3 -1
- wandb/integration/sb3/sb3.py +3 -3
- wandb/integration/ultralytics/callback.py +6 -2
- wandb/plot/__init__.py +2 -0
- wandb/plot/bar.py +30 -29
- wandb/plot/confusion_matrix.py +75 -71
- wandb/plot/histogram.py +26 -25
- wandb/plot/line.py +33 -32
- wandb/plot/line_series.py +100 -103
- wandb/plot/pr_curve.py +33 -32
- wandb/plot/roc_curve.py +38 -38
- wandb/plot/scatter.py +27 -27
- wandb/proto/v3/wandb_internal_pb2.py +366 -385
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_internal_pb2.py +352 -356
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_internal_pb2.py +352 -356
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/proto/v6/wandb_internal_pb2.py +352 -356
- wandb/proto/v6/wandb_settings_pb2.py +2 -2
- wandb/sdk/artifacts/_generated/__init__.py +12 -1
- wandb/sdk/artifacts/_generated/input_types.py +20 -2
- wandb/sdk/artifacts/_generated/link_artifact.py +21 -0
- wandb/sdk/artifacts/_generated/operations.py +9 -0
- wandb/sdk/artifacts/_validators.py +40 -2
- wandb/sdk/artifacts/artifact.py +163 -21
- wandb/sdk/data_types/base_types/media.py +9 -7
- wandb/sdk/data_types/base_types/wb_value.py +6 -6
- wandb/sdk/data_types/saved_model.py +3 -3
- wandb/sdk/data_types/table.py +41 -41
- wandb/sdk/data_types/trace_tree.py +12 -12
- wandb/sdk/interface/interface.py +8 -19
- wandb/sdk/interface/interface_shared.py +7 -16
- wandb/sdk/internal/datastore.py +18 -18
- wandb/sdk/internal/handler.py +3 -5
- wandb/sdk/internal/internal_api.py +54 -0
- wandb/sdk/internal/sender.py +23 -3
- wandb/sdk/internal/sender_config.py +9 -0
- wandb/sdk/launch/_project_spec.py +3 -3
- wandb/sdk/launch/agent/agent.py +3 -3
- wandb/sdk/launch/agent/job_status_tracker.py +3 -1
- wandb/sdk/launch/utils.py +3 -3
- wandb/sdk/lib/console_capture.py +66 -19
- wandb/sdk/wandb_init.py +1 -2
- wandb/sdk/wandb_require.py +0 -1
- wandb/sdk/wandb_run.py +23 -113
- wandb/sdk/wandb_settings.py +234 -72
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/METADATA +1 -1
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/RECORD +71 -71
- wandb/sdk/wandb_metadata.py +0 -623
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/WHEEL +0 -0
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/entry_points.txt +0 -0
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/licenses/LICENSE +0 -0
wandb/__init__.py
CHANGED
wandb/__init__.pyi
CHANGED
@@ -12,20 +12,20 @@ For reference documentation, see https://docs.wandb.com/ref/python.
|
|
12
12
|
from __future__ import annotations
|
13
13
|
|
14
14
|
__all__ = (
|
15
|
-
"__version__",
|
15
|
+
"__version__", # doc:exclude
|
16
16
|
"init",
|
17
17
|
"finish",
|
18
18
|
"setup",
|
19
19
|
"login",
|
20
|
-
"save",
|
20
|
+
"save", # doc:exclude
|
21
21
|
"sweep",
|
22
22
|
"controller",
|
23
23
|
"agent",
|
24
|
-
"config",
|
25
|
-
"log",
|
26
|
-
"summary",
|
24
|
+
"config", # doc:exclude
|
25
|
+
"log", # doc:exclude
|
26
|
+
"summary", # doc:exclude
|
27
27
|
"Api",
|
28
|
-
"Graph",
|
28
|
+
"Graph", # doc:exclude
|
29
29
|
"Image",
|
30
30
|
"Plotly",
|
31
31
|
"Video",
|
@@ -36,26 +36,27 @@ __all__ = (
|
|
36
36
|
"Object3D",
|
37
37
|
"Molecule",
|
38
38
|
"Histogram",
|
39
|
-
"ArtifactTTL",
|
40
|
-
"log_artifact",
|
41
|
-
"use_artifact",
|
42
|
-
"log_model",
|
43
|
-
"use_model",
|
44
|
-
"link_model",
|
45
|
-
"define_metric",
|
46
|
-
"Error",
|
47
|
-
"termsetup",
|
48
|
-
"termlog",
|
49
|
-
"termerror",
|
50
|
-
"termwarn",
|
39
|
+
"ArtifactTTL", # doc:exclude
|
40
|
+
"log_artifact", # doc:exclude
|
41
|
+
"use_artifact", # doc:exclude
|
42
|
+
"log_model", # doc:exclude
|
43
|
+
"use_model", # doc:exclude
|
44
|
+
"link_model", # doc:exclude
|
45
|
+
"define_metric", # doc:exclude
|
46
|
+
"Error", # doc:exclude
|
47
|
+
"termsetup", # doc:exclude
|
48
|
+
"termlog", # doc:exclude
|
49
|
+
"termerror", # doc:exclude
|
50
|
+
"termwarn", # doc:exclude
|
51
51
|
"Artifact",
|
52
52
|
"Settings",
|
53
53
|
"teardown",
|
54
|
-
"watch",
|
55
|
-
"unwatch",
|
56
|
-
"plot",
|
54
|
+
"watch", # doc:exclude
|
55
|
+
"unwatch", # doc:exclude
|
56
|
+
"plot", # doc:exclude
|
57
57
|
"plot_table",
|
58
58
|
"restore",
|
59
|
+
"Run",
|
59
60
|
)
|
60
61
|
|
61
62
|
import os
|
@@ -106,7 +107,7 @@ if TYPE_CHECKING:
|
|
106
107
|
import wandb
|
107
108
|
from wandb.plot import CustomChart
|
108
109
|
|
109
|
-
__version__: str = "0.
|
110
|
+
__version__: str = "0.21.0"
|
110
111
|
|
111
112
|
run: Run | None
|
112
113
|
config: wandb_config.Config
|
@@ -325,7 +326,7 @@ def init(
|
|
325
326
|
the UI.
|
326
327
|
If resuming a run, the tags provided here will replace any existing
|
327
328
|
tags. To add tags to a resumed run without overwriting the current
|
328
|
-
tags, use `run.tags +=
|
329
|
+
tags, use `run.tags += ("new_tag",)` after calling `run = wandb.init()`.
|
329
330
|
config: Sets `wandb.config`, a dictionary-like object for storing input
|
330
331
|
parameters to your run, such as model hyperparameters or data
|
331
332
|
preprocessing settings.
|
wandb/apis/internal.py
CHANGED
@@ -211,6 +211,9 @@ class Api:
|
|
211
211
|
def upsert_run_queue(self, *args, **kwargs):
|
212
212
|
return self.api.upsert_run_queue(*args, **kwargs)
|
213
213
|
|
214
|
+
def create_custom_chart(self, *args, **kwargs):
|
215
|
+
return self.api.create_custom_chart(*args, **kwargs)
|
216
|
+
|
214
217
|
def update_launch_agent_status(self, *args, **kwargs):
|
215
218
|
return self.api.update_launch_agent_status(*args, **kwargs)
|
216
219
|
|
wandb/apis/paginator.py
CHANGED
@@ -13,6 +13,8 @@ from typing import (
|
|
13
13
|
overload,
|
14
14
|
)
|
15
15
|
|
16
|
+
import wandb
|
17
|
+
|
16
18
|
if TYPE_CHECKING:
|
17
19
|
from wandb_graphql.language.ast import Document
|
18
20
|
|
@@ -112,14 +114,25 @@ class Paginator(Iterator[T]):
|
|
112
114
|
class SizedPaginator(Paginator[T], Sized):
|
113
115
|
"""A Paginator for objects with a known total count."""
|
114
116
|
|
117
|
+
@property
|
118
|
+
def length(self) -> int | None:
|
119
|
+
wandb.termwarn(
|
120
|
+
(
|
121
|
+
"`.length` is deprecated and will be removed in a future version. "
|
122
|
+
"Use `len(...)` instead."
|
123
|
+
),
|
124
|
+
repeat=False,
|
125
|
+
)
|
126
|
+
return len(self)
|
127
|
+
|
115
128
|
def __len__(self) -> int:
|
116
|
-
if self.
|
129
|
+
if self._length is None:
|
117
130
|
self._load_page()
|
118
|
-
if self.
|
131
|
+
if self._length is None:
|
119
132
|
raise ValueError("Object doesn't provide length")
|
120
|
-
return self.
|
133
|
+
return self._length
|
121
134
|
|
122
135
|
@property
|
123
136
|
@abstractmethod
|
124
|
-
def
|
137
|
+
def _length(self) -> int | None:
|
125
138
|
raise NotImplementedError
|
wandb/apis/public/api.py
CHANGED
@@ -467,6 +467,85 @@ class Api:
|
|
467
467
|
_default_resource_config=config,
|
468
468
|
)
|
469
469
|
|
470
|
+
def create_custom_chart(
|
471
|
+
self,
|
472
|
+
entity: str,
|
473
|
+
name: str,
|
474
|
+
display_name: str,
|
475
|
+
spec_type: Literal["vega2"],
|
476
|
+
access: Literal["private", "public"],
|
477
|
+
spec: Union[str, dict],
|
478
|
+
) -> str:
|
479
|
+
"""Create a custom chart preset and return its id.
|
480
|
+
|
481
|
+
Args:
|
482
|
+
entity: The entity (user or team) that owns the chart
|
483
|
+
name: Unique identifier for the chart preset
|
484
|
+
display_name: Human-readable name shown in the UI
|
485
|
+
spec_type: Type of specification. Must be "vega2" for Vega-Lite v2 specifications.
|
486
|
+
access: Access level for the chart:
|
487
|
+
- "private": Chart is only accessible to the entity that created it
|
488
|
+
- "public": Chart is publicly accessible
|
489
|
+
spec: The Vega/Vega-Lite specification as a dictionary or JSON string
|
490
|
+
|
491
|
+
Returns:
|
492
|
+
The ID of the created chart preset in the format "entity/name"
|
493
|
+
|
494
|
+
Raises:
|
495
|
+
wandb.Error: If chart creation fails
|
496
|
+
UnsupportedError: If the server doesn't support custom charts
|
497
|
+
|
498
|
+
Example:
|
499
|
+
```python
|
500
|
+
import wandb
|
501
|
+
|
502
|
+
api = wandb.Api()
|
503
|
+
|
504
|
+
# Define a simple bar chart specification
|
505
|
+
vega_spec = {
|
506
|
+
"$schema": "https://vega.github.io/schema/vega-lite/v6.json",
|
507
|
+
"mark": "bar",
|
508
|
+
"data": {"name": "wandb"},
|
509
|
+
"encoding": {
|
510
|
+
"x": {"field": "${field:x}", "type": "ordinal"},
|
511
|
+
"y": {"field": "${field:y}", "type": "quantitative"},
|
512
|
+
},
|
513
|
+
}
|
514
|
+
|
515
|
+
# Create the custom chart
|
516
|
+
chart_id = api.create_custom_chart(
|
517
|
+
entity="my-team",
|
518
|
+
name="my-bar-chart",
|
519
|
+
display_name="My Custom Bar Chart",
|
520
|
+
spec_type="vega2",
|
521
|
+
access="private",
|
522
|
+
spec=vega_spec,
|
523
|
+
)
|
524
|
+
|
525
|
+
# Use with wandb.plot_table()
|
526
|
+
chart = wandb.plot_table(
|
527
|
+
vega_spec_name=chart_id,
|
528
|
+
data_table=my_table,
|
529
|
+
fields={"x": "category", "y": "value"},
|
530
|
+
)
|
531
|
+
```
|
532
|
+
"""
|
533
|
+
# Convert user-facing lowercase access to backend uppercase
|
534
|
+
backend_access = access.upper()
|
535
|
+
|
536
|
+
api = InternalApi(retry_timedelta=RETRY_TIMEDELTA)
|
537
|
+
result = api.create_custom_chart(
|
538
|
+
entity=entity,
|
539
|
+
name=name,
|
540
|
+
display_name=display_name,
|
541
|
+
spec_type=spec_type,
|
542
|
+
access=backend_access,
|
543
|
+
spec=spec,
|
544
|
+
)
|
545
|
+
if result is None or result.get("chart") is None:
|
546
|
+
raise wandb.Error("failed to create custom chart")
|
547
|
+
return result["chart"]["id"]
|
548
|
+
|
470
549
|
def upsert_run_queue(
|
471
550
|
self,
|
472
551
|
name: str,
|
@@ -713,7 +792,7 @@ class Api:
|
|
713
792
|
return public.BetaReport(
|
714
793
|
self.client,
|
715
794
|
{
|
716
|
-
"
|
795
|
+
"displayName": urllib.parse.unquote(name.replace("-", " ")),
|
717
796
|
"id": id,
|
718
797
|
"spec": "{}",
|
719
798
|
},
|
@@ -1514,7 +1593,9 @@ class Api:
|
|
1514
1593
|
|
1515
1594
|
Find all collections in the registries with the name "my_collection" and the tag "my_tag"
|
1516
1595
|
```python
|
1517
|
-
api.registries().collections(
|
1596
|
+
api.registries().collections(
|
1597
|
+
filter={"name": "my_collection", "tag": "my_tag"}
|
1598
|
+
)
|
1518
1599
|
```
|
1519
1600
|
|
1520
1601
|
Find all artifact versions in the registries with a collection name that contains "my_collection" and a version that has the alias "best"
|
wandb/apis/public/artifacts.py
CHANGED
@@ -100,7 +100,7 @@ class ArtifactTypes(Paginator["ArtifactType"]):
|
|
100
100
|
self.last_response = ArtifactTypesFragment.model_validate(conn)
|
101
101
|
|
102
102
|
@property
|
103
|
-
def
|
103
|
+
def _length(self) -> None:
|
104
104
|
# TODO
|
105
105
|
return None
|
106
106
|
|
@@ -240,9 +240,9 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]):
|
|
240
240
|
self.last_response = ArtifactCollectionsFragment.model_validate(conn)
|
241
241
|
|
242
242
|
@property
|
243
|
-
def
|
243
|
+
def _length(self) -> int:
|
244
244
|
if self.last_response is None:
|
245
|
-
|
245
|
+
self._load_page()
|
246
246
|
return self.last_response.total_count
|
247
247
|
|
248
248
|
@property
|
@@ -608,9 +608,9 @@ class Artifacts(SizedPaginator["Artifact"]):
|
|
608
608
|
self.last_response = ArtifactsFragment.model_validate(conn)
|
609
609
|
|
610
610
|
@property
|
611
|
-
def
|
611
|
+
def _length(self) -> int:
|
612
612
|
if self.last_response is None:
|
613
|
-
|
613
|
+
self._load_page()
|
614
614
|
return self.last_response.total_count
|
615
615
|
|
616
616
|
@property
|
@@ -698,9 +698,9 @@ class RunArtifacts(SizedPaginator["Artifact"]):
|
|
698
698
|
self.last_response = self._response_cls.model_validate(inner_data)
|
699
699
|
|
700
700
|
@property
|
701
|
-
def
|
701
|
+
def _length(self) -> int:
|
702
702
|
if self.last_response is None:
|
703
|
-
|
703
|
+
self._load_page()
|
704
704
|
return self.last_response.total_count
|
705
705
|
|
706
706
|
@property
|
@@ -799,7 +799,9 @@ class ArtifactFiles(SizedPaginator["public.File"]):
|
|
799
799
|
return [self.artifact.entity, self.artifact.project, self.artifact.name]
|
800
800
|
|
801
801
|
@property
|
802
|
-
def
|
802
|
+
def _length(self) -> int:
|
803
|
+
if self.last_response is None:
|
804
|
+
self._load_page()
|
803
805
|
return self.artifact.file_count
|
804
806
|
|
805
807
|
@property
|
wandb/apis/public/files.py
CHANGED
@@ -72,11 +72,11 @@ class Files(SizedPaginator["File"]):
|
|
72
72
|
super().__init__(client, variables, per_page)
|
73
73
|
|
74
74
|
@property
|
75
|
-
def
|
76
|
-
if self.last_response:
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
def _length(self):
|
76
|
+
if not self.last_response:
|
77
|
+
self._load_page()
|
78
|
+
|
79
|
+
return self.last_response["project"]["run"]["fileCount"]
|
80
80
|
|
81
81
|
@property
|
82
82
|
def more(self):
|
wandb/apis/public/projects.py
CHANGED
@@ -9,6 +9,7 @@ from wandb.apis import public
|
|
9
9
|
from wandb.apis.attrs import Attrs
|
10
10
|
from wandb.apis.normalize import normalize_exceptions
|
11
11
|
from wandb.apis.paginator import Paginator
|
12
|
+
from wandb.apis.public.api import RetryingClient
|
12
13
|
from wandb.sdk.lib import ipython
|
13
14
|
|
14
15
|
PROJECT_FRAGMENT = """fragment ProjectFragment on Project {
|
@@ -43,7 +44,19 @@ class Projects(Paginator["Project"]):
|
|
43
44
|
""".format(PROJECT_FRAGMENT)
|
44
45
|
)
|
45
46
|
|
46
|
-
def __init__(
|
47
|
+
def __init__(
|
48
|
+
self,
|
49
|
+
client: RetryingClient,
|
50
|
+
entity: str,
|
51
|
+
per_page: int = 50,
|
52
|
+
) -> "Projects":
|
53
|
+
"""An iterable collection of `Project` objects.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
client: The API client used to query W&B.
|
57
|
+
entity: The entity which owns the projects.
|
58
|
+
per_page: The number of projects to fetch per request to the API.
|
59
|
+
"""
|
47
60
|
self.client = client
|
48
61
|
self.entity = entity
|
49
62
|
variables = {
|
@@ -83,7 +96,31 @@ class Projects(Paginator["Project"]):
|
|
83
96
|
class Project(Attrs):
|
84
97
|
"""A project is a namespace for runs."""
|
85
98
|
|
86
|
-
|
99
|
+
QUERY = gql(
|
100
|
+
"""
|
101
|
+
query Project($project: String!, $entity: String!) {
|
102
|
+
project(name: $project, entityName: $entity) {
|
103
|
+
id
|
104
|
+
}
|
105
|
+
}
|
106
|
+
"""
|
107
|
+
)
|
108
|
+
|
109
|
+
def __init__(
|
110
|
+
self,
|
111
|
+
client: RetryingClient,
|
112
|
+
entity: str,
|
113
|
+
project: str,
|
114
|
+
attrs: dict,
|
115
|
+
) -> "Project":
|
116
|
+
"""A single project associated with an entity.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
client: The API client used to query W&B.
|
120
|
+
entity: The entity which owns the project.
|
121
|
+
project: The name of the project to query.
|
122
|
+
attrs: The attributes of the project.
|
123
|
+
"""
|
87
124
|
super().__init__(dict(attrs))
|
88
125
|
self.client = client
|
89
126
|
self.name = project
|
@@ -143,7 +180,7 @@ class Project(Attrs):
|
|
143
180
|
)
|
144
181
|
variable_values = {"project": self.name, "entity": self.entity}
|
145
182
|
ret = self.client.execute(query, variable_values)
|
146
|
-
if ret["project"]["totalSweeps"] < 1:
|
183
|
+
if not ret.get("project") or ret["project"]["totalSweeps"] < 1:
|
147
184
|
return []
|
148
185
|
|
149
186
|
return [
|
@@ -178,6 +215,10 @@ class Project(Attrs):
|
|
178
215
|
variable_values = {"projectName": self.name, "entityName": self.entity}
|
179
216
|
try:
|
180
217
|
data = self.client.execute(self._PROJECT_ID, variable_values)
|
218
|
+
|
219
|
+
if not data.get("project") or not data["project"].get("id"):
|
220
|
+
raise ValueError(f"Project {self.name} not found")
|
221
|
+
|
181
222
|
self._attrs["id"] = data["project"]["id"]
|
182
223
|
return self._attrs["id"]
|
183
224
|
except (HTTPError, LookupError, TypeError) as e:
|
wandb/apis/public/reports.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
import ast
|
4
4
|
import json
|
5
|
+
import re
|
5
6
|
import urllib
|
6
7
|
|
7
8
|
from wandb_gql import gql
|
@@ -32,9 +33,11 @@ class Reports(SizedPaginator["BetaReport"]):
|
|
32
33
|
user {
|
33
34
|
username
|
34
35
|
photoUrl
|
36
|
+
email
|
35
37
|
}
|
36
38
|
spec
|
37
39
|
updatedAt
|
40
|
+
createdAt
|
38
41
|
}
|
39
42
|
cursor
|
40
43
|
}
|
@@ -60,7 +63,7 @@ class Reports(SizedPaginator["BetaReport"]):
|
|
60
63
|
super().__init__(client, variables, per_page)
|
61
64
|
|
62
65
|
@property
|
63
|
-
def
|
66
|
+
def _length(self):
|
64
67
|
# TODO: Add the count the backend
|
65
68
|
if self.last_response:
|
66
69
|
return len(self.objects)
|
@@ -111,11 +114,15 @@ class BetaReport(Attrs):
|
|
111
114
|
WARNING: this API will likely change in a future release
|
112
115
|
|
113
116
|
Attributes:
|
117
|
+
id (string): unique identifier of the report
|
114
118
|
name (string): report name
|
115
|
-
|
116
|
-
|
117
|
-
|
119
|
+
display_name (string): display name of the report
|
120
|
+
description (string): report description
|
121
|
+
user (User): the user that created the report (contains username and email)
|
122
|
+
spec (dict): the spec of the report
|
123
|
+
url (string): the url of the report
|
118
124
|
updated_at (string): timestamp of last update
|
125
|
+
created_at (string): timestamp when the report was created
|
119
126
|
"""
|
120
127
|
|
121
128
|
def __init__(self, client, attrs, entity=None, project=None):
|
@@ -124,7 +131,16 @@ class BetaReport(Attrs):
|
|
124
131
|
self.entity = entity
|
125
132
|
self.query_generator = public.QueryGenerator()
|
126
133
|
super().__init__(dict(attrs))
|
127
|
-
|
134
|
+
|
135
|
+
if "spec" in self._attrs:
|
136
|
+
if isinstance(self._attrs["spec"], str):
|
137
|
+
self._attrs["spec"] = json.loads(self._attrs["spec"])
|
138
|
+
else:
|
139
|
+
self._attrs["spec"] = {}
|
140
|
+
|
141
|
+
@property
|
142
|
+
def spec(self):
|
143
|
+
return self._attrs["spec"]
|
128
144
|
|
129
145
|
@property
|
130
146
|
def sections(self):
|
@@ -153,12 +169,44 @@ class BetaReport(Attrs):
|
|
153
169
|
per_page=per_page,
|
154
170
|
)
|
155
171
|
|
172
|
+
@property
|
173
|
+
def id(self):
|
174
|
+
return self._attrs.get("id")
|
175
|
+
|
176
|
+
@property
|
177
|
+
def name(self):
|
178
|
+
return self._attrs.get("name")
|
179
|
+
|
180
|
+
@property
|
181
|
+
def display_name(self):
|
182
|
+
return self._attrs.get("displayName")
|
183
|
+
|
184
|
+
@property
|
185
|
+
def description(self):
|
186
|
+
return self._attrs.get("description")
|
187
|
+
|
188
|
+
@property
|
189
|
+
def user(self):
|
190
|
+
return self._attrs.get("user")
|
191
|
+
|
156
192
|
@property
|
157
193
|
def updated_at(self):
|
158
|
-
return self._attrs
|
194
|
+
return self._attrs.get("updatedAt")
|
195
|
+
|
196
|
+
@property
|
197
|
+
def created_at(self):
|
198
|
+
return self._attrs.get("createdAt")
|
159
199
|
|
160
200
|
@property
|
161
201
|
def url(self):
|
202
|
+
if (
|
203
|
+
not self.client
|
204
|
+
or not self.entity
|
205
|
+
or not self.project
|
206
|
+
or not self.display_name
|
207
|
+
or not self.id
|
208
|
+
):
|
209
|
+
return None
|
162
210
|
return self.client.app_url + "/".join(
|
163
211
|
[
|
164
212
|
self.entity,
|
@@ -166,7 +214,12 @@ class BetaReport(Attrs):
|
|
166
214
|
"reports",
|
167
215
|
"--".join(
|
168
216
|
[
|
169
|
-
|
217
|
+
# made this more closely match the url creation in the frontend (https://github.com/wandb/core/blob/76943979c8e967f7a62dae8bef0a001a2672584c/frontends/app/src/util/report/urls.ts#L19)
|
218
|
+
urllib.parse.quote(
|
219
|
+
re.sub(
|
220
|
+
r"-+", "-", re.sub(r"\W", "-", self.display_name)
|
221
|
+
).strip("-")
|
222
|
+
),
|
170
223
|
self.id.replace("=", ""),
|
171
224
|
]
|
172
225
|
),
|
@@ -175,7 +228,10 @@ class BetaReport(Attrs):
|
|
175
228
|
|
176
229
|
def to_html(self, height=1024, hidden=False):
|
177
230
|
"""Generate HTML containing an iframe displaying this report."""
|
178
|
-
url = self.url
|
231
|
+
url = self.url
|
232
|
+
if url is None:
|
233
|
+
return "<div>Report URL not available</div>"
|
234
|
+
url = url + "?jupyter=true"
|
179
235
|
style = f"border:none;width:100%;height:{height}px;"
|
180
236
|
prefix = ""
|
181
237
|
if hidden:
|
wandb/apis/public/runs.py
CHANGED
@@ -111,7 +111,7 @@ class Runs(SizedPaginator["Run"]):
|
|
111
111
|
runs(filters: $filters, after: $cursor, first: $perPage, order: $order) {{
|
112
112
|
edges {{
|
113
113
|
node {{
|
114
|
-
{"" if _server_provides_internal_id_for_project(client) else "
|
114
|
+
{"projectId" if _server_provides_internal_id_for_project(client) else ""}
|
115
115
|
...RunFragment
|
116
116
|
}}
|
117
117
|
cursor
|
@@ -143,11 +143,10 @@ class Runs(SizedPaginator["Run"]):
|
|
143
143
|
super().__init__(client, variables, per_page)
|
144
144
|
|
145
145
|
@property
|
146
|
-
def
|
147
|
-
if self.last_response:
|
148
|
-
|
149
|
-
|
150
|
-
return None
|
146
|
+
def _length(self):
|
147
|
+
if not self.last_response:
|
148
|
+
self._load_page()
|
149
|
+
return self.last_response["project"]["runCount"]
|
151
150
|
|
152
151
|
@property
|
153
152
|
def more(self):
|
@@ -454,25 +453,19 @@ class Run(Attrs):
|
|
454
453
|
)
|
455
454
|
|
456
455
|
def load(self, force=False):
|
457
|
-
|
458
|
-
"""
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
456
|
+
if force or not self._attrs:
|
457
|
+
query = gql(f"""#graphql
|
458
|
+
query Run($project: String!, $entity: String!, $name: String!) {{
|
459
|
+
project(name: $project, entityName: $entity) {{
|
460
|
+
run(name: $name) {{
|
461
|
+
{"projectId" if _server_provides_internal_id_for_project(self.client) else ""}
|
462
|
+
...RunFragment
|
463
|
+
}}
|
464
464
|
}}
|
465
465
|
}}
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
"projectId"
|
470
|
-
if _server_provides_internal_id_for_project(self.client)
|
471
|
-
else "",
|
472
|
-
RUN_FRAGMENT,
|
473
|
-
)
|
474
|
-
)
|
475
|
-
if force or not self._attrs:
|
466
|
+
{RUN_FRAGMENT}
|
467
|
+
""")
|
468
|
+
|
476
469
|
response = self._exec(query)
|
477
470
|
if (
|
478
471
|
response is None
|
wandb/automations/__init__.py
CHANGED
@@ -45,21 +45,21 @@ else:
|
|
45
45
|
|
46
46
|
__all__ = [
|
47
47
|
# Scopes
|
48
|
-
"ScopeType",
|
49
|
-
"ArtifactCollectionScope",
|
50
|
-
"ProjectScope",
|
48
|
+
"ScopeType", # doc:exclude
|
49
|
+
"ArtifactCollectionScope", # doc:exclude
|
50
|
+
"ProjectScope", # doc:exclude
|
51
51
|
# Events
|
52
|
-
"EventType",
|
52
|
+
"EventType", # doc:exclude
|
53
53
|
"OnAddArtifactAlias",
|
54
54
|
"OnCreateArtifact",
|
55
55
|
"OnLinkArtifact",
|
56
56
|
"OnRunMetric",
|
57
|
-
"ArtifactEvent",
|
58
|
-
"RunEvent",
|
57
|
+
"ArtifactEvent", # doc:exclude
|
58
|
+
"RunEvent", # doc:exclude
|
59
59
|
"MetricThresholdFilter",
|
60
60
|
"MetricChangeFilter",
|
61
61
|
# Actions
|
62
|
-
"ActionType",
|
62
|
+
"ActionType", # doc:exclude
|
63
63
|
"SendNotification",
|
64
64
|
"SendWebhook",
|
65
65
|
"DoNothing",
|
@@ -67,7 +67,7 @@ __all__ = [
|
|
67
67
|
"Automation",
|
68
68
|
"NewAutomation",
|
69
69
|
# Integrations
|
70
|
-
"Integration",
|
71
|
-
"SlackIntegration",
|
72
|
-
"WebhookIntegration",
|
70
|
+
"Integration", # doc:exclude
|
71
|
+
"SlackIntegration", # doc:exclude
|
72
|
+
"WebhookIntegration", # doc:exclude
|
73
73
|
]
|
wandb/automations/_utils.py
CHANGED
wandb/automations/actions.py
CHANGED