wandb 0.17.6__py3-none-win32.whl → 0.17.7__py3-none-win32.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 +3 -16
- wandb/agents/pyagent.py +1 -2
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +21 -0
- wandb/data_types.py +3 -3
- wandb/integration/kfp/wandb_logging.py +1 -1
- wandb/integration/lightning/fabric/logger.py +1 -1
- wandb/integration/openai/fine_tuning.py +13 -5
- wandb/integration/ultralytics/pose_utils.py +0 -1
- wandb/sdk/artifacts/artifact.py +1 -1
- wandb/sdk/data_types/_dtypes.py +5 -5
- wandb/sdk/data_types/base_types/media.py +3 -1
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +3 -1
- wandb/sdk/data_types/helper_types/image_mask.py +3 -1
- wandb/sdk/data_types/image.py +3 -1
- wandb/sdk/data_types/saved_model.py +3 -1
- wandb/sdk/interface/interface.py +17 -16
- wandb/sdk/interface/interface_shared.py +6 -9
- wandb/sdk/internal/datastore.py +1 -1
- wandb/sdk/internal/handler.py +0 -2
- wandb/sdk/internal/internal.py +1 -1
- wandb/sdk/internal/job_builder.py +5 -2
- wandb/sdk/internal/tb_watcher.py +2 -2
- wandb/sdk/internal/update.py +2 -2
- wandb/sdk/launch/builder/kaniko_builder.py +13 -5
- wandb/sdk/launch/create_job.py +2 -0
- wandb/sdk/lib/apikey.py +1 -1
- wandb/sdk/service/streams.py +2 -4
- wandb/sdk/wandb_config.py +1 -1
- wandb/sdk/wandb_init.py +55 -7
- wandb/sdk/wandb_run.py +109 -68
- wandb/sdk/wandb_settings.py +1 -1
- wandb/sdk/wandb_setup.py +66 -3
- wandb/sdk/wandb_sweep.py +5 -2
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/METADATA +1 -1
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/RECORD +39 -39
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/WHEEL +0 -0
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/entry_points.txt +0 -0
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/licenses/LICENSE +0 -0
wandb/__init__.py
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
"""Use wandb to track machine learning work.
|
2
2
|
|
3
|
-
|
4
|
-
- wandb.init — initialize a new run at the top of your training script
|
5
|
-
- wandb.config — track hyperparameters and metadata
|
6
|
-
- wandb.log — log metrics and media over time within your training loop
|
3
|
+
Train and fine-tune models, manage models from experimentation to production.
|
7
4
|
|
8
5
|
For guides and examples, see https://docs.wandb.ai.
|
9
6
|
|
@@ -11,11 +8,7 @@ For scripts and interactive notebooks, see https://github.com/wandb/examples.
|
|
11
8
|
|
12
9
|
For reference documentation, see https://docs.wandb.com/ref/python.
|
13
10
|
"""
|
14
|
-
__version__ = "0.17.
|
15
|
-
|
16
|
-
|
17
|
-
# Used with pypi checks and other messages related to pip
|
18
|
-
_wandb_module = "wandb"
|
11
|
+
__version__ = "0.17.7"
|
19
12
|
|
20
13
|
from typing import Optional
|
21
14
|
|
@@ -118,13 +111,6 @@ def _assert_is_user_process():
|
|
118
111
|
assert not _IS_INTERNAL_PROCESS
|
119
112
|
|
120
113
|
|
121
|
-
# toplevel:
|
122
|
-
# save()
|
123
|
-
# restore()
|
124
|
-
# login()
|
125
|
-
# sweep()
|
126
|
-
# agent()
|
127
|
-
|
128
114
|
# globals
|
129
115
|
Api = PublicApi
|
130
116
|
api = InternalApi()
|
@@ -254,4 +240,5 @@ __all__ = (
|
|
254
240
|
"log_model",
|
255
241
|
"use_model",
|
256
242
|
"link_model",
|
243
|
+
"define_metric",
|
257
244
|
)
|
wandb/agents/pyagent.py
CHANGED
@@ -14,7 +14,6 @@ import time
|
|
14
14
|
import traceback
|
15
15
|
|
16
16
|
import wandb
|
17
|
-
from wandb import wandb_sdk
|
18
17
|
from wandb.apis import InternalApi
|
19
18
|
from wandb.sdk.launch.sweeps import utils as sweep_utils
|
20
19
|
|
@@ -298,7 +297,7 @@ class Agent:
|
|
298
297
|
sweep_param_path, job.config
|
299
298
|
)
|
300
299
|
os.environ[wandb.env.SWEEP_ID] = self._sweep_id
|
301
|
-
|
300
|
+
wandb.sdk.wandb_setup._setup(_reset=True)
|
302
301
|
|
303
302
|
wandb.termlog(f"Agent Starting Run: {run_id} with config:")
|
304
303
|
for k, v in job.config.items():
|
wandb/bin/wandb-core
CHANGED
Binary file
|
wandb/cli/cli.py
CHANGED
@@ -1417,6 +1417,13 @@ def launch_sweep(
|
|
1417
1417
|
help="""Specific docker image you'd like to use. In the form name:tag.
|
1418
1418
|
If passed in, will override the docker image value passed in using a config file.""",
|
1419
1419
|
)
|
1420
|
+
@click.option(
|
1421
|
+
"--base-image",
|
1422
|
+
"-B",
|
1423
|
+
default=None,
|
1424
|
+
metavar="BASE IMAGE",
|
1425
|
+
help="""Docker image to run job code in. Incompatible with --docker-image.""",
|
1426
|
+
)
|
1420
1427
|
@click.option(
|
1421
1428
|
"--config",
|
1422
1429
|
"-c",
|
@@ -1508,6 +1515,7 @@ def launch(
|
|
1508
1515
|
entity,
|
1509
1516
|
project,
|
1510
1517
|
docker_image,
|
1518
|
+
base_image,
|
1511
1519
|
config,
|
1512
1520
|
cli_template_vars,
|
1513
1521
|
queue,
|
@@ -1604,6 +1612,7 @@ def launch(
|
|
1604
1612
|
git_hash=git_version,
|
1605
1613
|
name=job_name,
|
1606
1614
|
project=project,
|
1615
|
+
base_image=base_image,
|
1607
1616
|
build_context=build_context,
|
1608
1617
|
dockerfile=dockerfile,
|
1609
1618
|
entity=entity,
|
@@ -2001,6 +2010,12 @@ def describe(job):
|
|
2001
2010
|
help="Path to the build context from the root of the job source code. If "
|
2002
2011
|
"provided, this is used as the base path for the Dockerfile and entrypoint.",
|
2003
2012
|
)
|
2013
|
+
@click.option(
|
2014
|
+
"--base-image",
|
2015
|
+
"-B",
|
2016
|
+
type=str,
|
2017
|
+
help="Base image to use for the job. Incompatible with image jobs.",
|
2018
|
+
)
|
2004
2019
|
@click.option(
|
2005
2020
|
"--dockerfile",
|
2006
2021
|
"-D",
|
@@ -2025,6 +2040,7 @@ def create(
|
|
2025
2040
|
git_hash,
|
2026
2041
|
runtime,
|
2027
2042
|
build_context,
|
2043
|
+
base_image,
|
2028
2044
|
dockerfile,
|
2029
2045
|
):
|
2030
2046
|
"""Create a job from a source, without a wandb run.
|
@@ -2056,6 +2072,10 @@ def create(
|
|
2056
2072
|
)
|
2057
2073
|
entrypoint = "main.py"
|
2058
2074
|
|
2075
|
+
if job_type == "image" and base_image:
|
2076
|
+
wandb.termerror("Cannot provide --base-image/-B for an `image` job")
|
2077
|
+
return
|
2078
|
+
|
2059
2079
|
artifact, action, aliases = _create_job(
|
2060
2080
|
api=api,
|
2061
2081
|
path=path,
|
@@ -2069,6 +2089,7 @@ def create(
|
|
2069
2089
|
git_hash=git_hash,
|
2070
2090
|
runtime=runtime,
|
2071
2091
|
build_context=build_context,
|
2092
|
+
base_image=base_image,
|
2072
2093
|
dockerfile=dockerfile,
|
2073
2094
|
)
|
2074
2095
|
if not artifact:
|
wandb/data_types.py
CHANGED
@@ -104,7 +104,7 @@ class _TableIndex(int, _TableLinkMixin):
|
|
104
104
|
def _json_helper(val, artifact):
|
105
105
|
if isinstance(val, WBValue):
|
106
106
|
return val.to_json(artifact)
|
107
|
-
elif val.__class__
|
107
|
+
elif val.__class__ is dict:
|
108
108
|
res = {}
|
109
109
|
for key in val:
|
110
110
|
res[key] = _json_helper(val[key], artifact)
|
@@ -270,10 +270,10 @@ class Table(Media):
|
|
270
270
|
if dtype is None:
|
271
271
|
dtype = _dtypes.UnknownType()
|
272
272
|
|
273
|
-
if optional.__class__
|
273
|
+
if optional.__class__ is not list:
|
274
274
|
optional = [optional for _ in range(len(self.columns))]
|
275
275
|
|
276
|
-
if dtype.__class__
|
276
|
+
if dtype.__class__ is not list:
|
277
277
|
dtype = [dtype for _ in range(len(self.columns))]
|
278
278
|
|
279
279
|
self._column_types = _dtypes.TypedDictType({})
|
@@ -312,7 +312,7 @@ class WandbLogger(Logger):
|
|
312
312
|
self._prefix = prefix
|
313
313
|
self._experiment = experiment
|
314
314
|
self._logged_model_time: Dict[str, float] = {}
|
315
|
-
self._checkpoint_callback: Optional[
|
315
|
+
self._checkpoint_callback: Optional[ModelCheckpoint] = None
|
316
316
|
|
317
317
|
# paths are processed as strings
|
318
318
|
if save_dir is not None:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import base64
|
1
2
|
import datetime
|
2
3
|
import io
|
3
4
|
import json
|
@@ -16,13 +17,13 @@ from wandb.util import parse_version
|
|
16
17
|
|
17
18
|
openai = util.get_module(
|
18
19
|
name="openai",
|
19
|
-
required="
|
20
|
-
lazy=
|
20
|
+
required="This integration requires `openai`. To install, please run `pip install openai`",
|
21
|
+
lazy=False,
|
21
22
|
)
|
22
23
|
|
23
|
-
if parse_version(openai.__version__) < parse_version("1.0
|
24
|
+
if parse_version(openai.__version__) < parse_version("1.12.0"):
|
24
25
|
raise wandb.Error(
|
25
|
-
f"This integration requires openai version 1.0
|
26
|
+
f"This integration requires openai version 1.12.0 and above. Your current version is {openai.__version__} "
|
26
27
|
"To fix, please `pip install -U openai`"
|
27
28
|
)
|
28
29
|
|
@@ -228,7 +229,14 @@ class WandbLogger:
|
|
228
229
|
# check results are present
|
229
230
|
try:
|
230
231
|
results_id = fine_tune.result_files[0]
|
231
|
-
|
232
|
+
try:
|
233
|
+
encoded_results = cls.openai_client.files.content(
|
234
|
+
file_id=results_id
|
235
|
+
).read()
|
236
|
+
results = base64.b64decode(encoded_results).decode("utf-8")
|
237
|
+
except Exception:
|
238
|
+
# attempt to read as text, works for older jobs
|
239
|
+
results = cls.openai_client.files.content(file_id=results_id).text
|
232
240
|
except openai.NotFoundError:
|
233
241
|
if show_individual_warnings:
|
234
242
|
wandb.termwarn(
|
@@ -23,7 +23,6 @@ def annotate_keypoint_results(result: Results, visualize_skeleton: bool):
|
|
23
23
|
|
24
24
|
|
25
25
|
def annotate_keypoint_batch(image_path: str, keypoints: Any, visualize_skeleton: bool):
|
26
|
-
original_image = None
|
27
26
|
with Image.open(image_path) as original_image:
|
28
27
|
original_image = np.ascontiguousarray(original_image)
|
29
28
|
annotator = Annotator(original_image)
|
wandb/sdk/artifacts/artifact.py
CHANGED
@@ -751,7 +751,7 @@ class Artifact:
|
|
751
751
|
def save(
|
752
752
|
self,
|
753
753
|
project: Optional[str] = None,
|
754
|
-
settings: Optional["wandb.
|
754
|
+
settings: Optional["wandb.sdk.wandb_settings.Settings"] = None,
|
755
755
|
) -> None:
|
756
756
|
"""Persist any changes made to the artifact.
|
757
757
|
|
wandb/sdk/data_types/_dtypes.py
CHANGED
@@ -56,7 +56,7 @@ class TypeRegistry:
|
|
56
56
|
# but will be ultimately treated as a None. Ignoring type since
|
57
57
|
# mypy does not trust that py_obj is a float by the time it is
|
58
58
|
# passed to isnan.
|
59
|
-
if py_obj.__class__
|
59
|
+
if py_obj.__class__ is float and math.isnan(py_obj): # type: ignore
|
60
60
|
return NoneType()
|
61
61
|
|
62
62
|
# TODO: generalize this to handle other config input types
|
@@ -134,7 +134,7 @@ def _params_obj_to_json_obj(
|
|
134
134
|
artifact: t.Optional["Artifact"] = None,
|
135
135
|
) -> t.Any:
|
136
136
|
"""Helper method."""
|
137
|
-
if params_obj.__class__
|
137
|
+
if params_obj.__class__ is dict:
|
138
138
|
return {
|
139
139
|
key: _params_obj_to_json_obj(params_obj[key], artifact)
|
140
140
|
for key in params_obj
|
@@ -151,7 +151,7 @@ def _json_obj_to_params_obj(
|
|
151
151
|
json_obj: t.Any, artifact: t.Optional["Artifact"] = None
|
152
152
|
) -> t.Any:
|
153
153
|
"""Helper method."""
|
154
|
-
if json_obj.__class__
|
154
|
+
if json_obj.__class__ is dict:
|
155
155
|
if "wb_type" in json_obj:
|
156
156
|
return TypeRegistry.type_from_dict(json_obj, artifact)
|
157
157
|
else:
|
@@ -159,7 +159,7 @@ def _json_obj_to_params_obj(
|
|
159
159
|
key: _json_obj_to_params_obj(json_obj[key], artifact)
|
160
160
|
for key in json_obj
|
161
161
|
}
|
162
|
-
elif json_obj.__class__
|
162
|
+
elif json_obj.__class__ is list:
|
163
163
|
return [_json_obj_to_params_obj(item, artifact) for item in json_obj]
|
164
164
|
else:
|
165
165
|
return json_obj
|
@@ -533,7 +533,7 @@ class UnionType(Type):
|
|
533
533
|
self,
|
534
534
|
allowed_types: t.Optional[t.Sequence[ConvertibleToType]] = None,
|
535
535
|
):
|
536
|
-
assert allowed_types is None or (allowed_types.__class__
|
536
|
+
assert allowed_types is None or (allowed_types.__class__ is list)
|
537
537
|
if allowed_types is None:
|
538
538
|
wb_types = []
|
539
539
|
else:
|
@@ -159,9 +159,11 @@ class Media(WBValue):
|
|
159
159
|
# into Media itself we should get rid of them
|
160
160
|
from wandb import Image
|
161
161
|
from wandb.data_types import Audio
|
162
|
+
from wandb.sdk.wandb_run import Run
|
162
163
|
|
163
164
|
json_obj = {}
|
164
|
-
|
165
|
+
|
166
|
+
if isinstance(run, Run):
|
165
167
|
json_obj.update(
|
166
168
|
{
|
167
169
|
"_type": "file", # TODO(adrian): This isn't (yet) a real media type we support on the frontend.
|
@@ -276,7 +276,9 @@ class BoundingBoxes2D(JSONMetadata):
|
|
276
276
|
return True
|
277
277
|
|
278
278
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
279
|
-
|
279
|
+
from wandb.sdk.wandb_run import Run
|
280
|
+
|
281
|
+
if isinstance(run_or_artifact, Run):
|
280
282
|
return super().to_json(run_or_artifact)
|
281
283
|
elif isinstance(run_or_artifact, wandb.Artifact):
|
282
284
|
# TODO (tim): I would like to log out a proper dictionary representing this object, but don't
|
@@ -191,9 +191,11 @@ class ImageMask(Media):
|
|
191
191
|
)
|
192
192
|
|
193
193
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
194
|
+
from wandb.sdk.wandb_run import Run
|
195
|
+
|
194
196
|
json_dict = super().to_json(run_or_artifact)
|
195
197
|
|
196
|
-
if isinstance(run_or_artifact,
|
198
|
+
if isinstance(run_or_artifact, Run):
|
197
199
|
json_dict["_type"] = self.type_name()
|
198
200
|
return json_dict
|
199
201
|
elif isinstance(run_or_artifact, wandb.Artifact):
|
wandb/sdk/data_types/image.py
CHANGED
@@ -418,6 +418,8 @@ class Image(BatchableMedia):
|
|
418
418
|
)
|
419
419
|
|
420
420
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
421
|
+
from wandb.sdk.wandb_run import Run
|
422
|
+
|
421
423
|
json_dict = super().to_json(run_or_artifact)
|
422
424
|
json_dict["_type"] = Image._log_type
|
423
425
|
json_dict["format"] = self.format
|
@@ -456,7 +458,7 @@ class Image(BatchableMedia):
|
|
456
458
|
"digest": classes_entry.digest,
|
457
459
|
}
|
458
460
|
|
459
|
-
elif not isinstance(run_or_artifact,
|
461
|
+
elif not isinstance(run_or_artifact, Run):
|
460
462
|
raise ValueError("to_json accepts wandb_run.Run or wandb_artifact.Artifact")
|
461
463
|
|
462
464
|
if self._boxes:
|
@@ -148,7 +148,9 @@ class _SavedModel(WBValue, Generic[SavedModelObjType]):
|
|
148
148
|
# bit of tech debt in the other data types which requires the input to `to_json`
|
149
149
|
# to accept a Run or Artifact. However, Run additions should be deprecated in the future.
|
150
150
|
# This check helps ensure we do not add to the debt.
|
151
|
-
|
151
|
+
from wandb.sdk.wandb_run import Run
|
152
|
+
|
153
|
+
if isinstance(run_or_artifact, Run):
|
152
154
|
raise ValueError("SavedModel cannot be added to run - must use artifact")
|
153
155
|
artifact = run_or_artifact
|
154
156
|
json_obj = {
|
wandb/sdk/interface/interface.py
CHANGED
@@ -54,18 +54,20 @@ MANIFEST_FILE_SIZE_THRESHOLD = 100_000
|
|
54
54
|
|
55
55
|
GlobStr = NewType("GlobStr", str)
|
56
56
|
|
57
|
-
if
|
58
|
-
from
|
57
|
+
if sys.version_info >= (3, 8):
|
58
|
+
from typing import Literal, TypedDict
|
59
|
+
else:
|
60
|
+
from typing_extensions import Literal, TypedDict
|
61
|
+
|
62
|
+
PolicyName = Literal["now", "live", "end"]
|
59
63
|
|
60
|
-
if sys.version_info >= (3, 8):
|
61
|
-
from typing import Literal, TypedDict
|
62
|
-
else:
|
63
|
-
from typing_extensions import Literal, TypedDict
|
64
64
|
|
65
|
-
|
65
|
+
class FilesDict(TypedDict):
|
66
|
+
files: Iterable[Tuple[GlobStr, PolicyName]]
|
66
67
|
|
67
|
-
|
68
|
-
|
68
|
+
|
69
|
+
if TYPE_CHECKING:
|
70
|
+
from ..wandb_run import Run
|
69
71
|
|
70
72
|
|
71
73
|
logger = logging.getLogger("wandb")
|
@@ -112,15 +114,14 @@ class InterfaceBase:
|
|
112
114
|
def _publish_header(self, header: pb.HeaderRecord) -> None:
|
113
115
|
raise NotImplementedError
|
114
116
|
|
115
|
-
def
|
116
|
-
|
117
|
-
resp = self._communicate_status(status)
|
118
|
-
return resp
|
117
|
+
def deliver_status(self) -> MailboxHandle:
|
118
|
+
return self._deliver_status(pb.StatusRequest())
|
119
119
|
|
120
120
|
@abstractmethod
|
121
|
-
def
|
122
|
-
self,
|
123
|
-
|
121
|
+
def _deliver_status(
|
122
|
+
self,
|
123
|
+
status: pb.StatusRequest,
|
124
|
+
) -> MailboxHandle:
|
124
125
|
raise NotImplementedError
|
125
126
|
|
126
127
|
def _make_config(
|
@@ -299,7 +299,7 @@ class InterfaceShared(InterfaceBase):
|
|
299
299
|
raise NotImplementedError
|
300
300
|
|
301
301
|
def _communicate(
|
302
|
-
self, rec: pb.Record, timeout: Optional[int] =
|
302
|
+
self, rec: pb.Record, timeout: Optional[int] = 30, local: Optional[bool] = None
|
303
303
|
) -> Optional[pb.Result]:
|
304
304
|
return self._communicate_async(rec, local=local).get(timeout=timeout)
|
305
305
|
|
@@ -421,15 +421,12 @@ class InterfaceShared(InterfaceBase):
|
|
421
421
|
rec = self._make_record(alert=proto_alert)
|
422
422
|
self._publish(rec)
|
423
423
|
|
424
|
-
def
|
425
|
-
self,
|
426
|
-
|
424
|
+
def _deliver_status(
|
425
|
+
self,
|
426
|
+
status: pb.StatusRequest,
|
427
|
+
) -> MailboxHandle:
|
427
428
|
req = self._make_request(status=status)
|
428
|
-
|
429
|
-
if resp is None:
|
430
|
-
return None
|
431
|
-
assert resp.response.status_response
|
432
|
-
return resp.response.status_response
|
429
|
+
return self._deliver_record(req)
|
433
430
|
|
434
431
|
def _publish_exit(self, exit_data: pb.RunExitRecord) -> None:
|
435
432
|
rec = self._make_record(exit=exit_data)
|
wandb/sdk/internal/datastore.py
CHANGED
wandb/sdk/internal/handler.py
CHANGED
@@ -745,8 +745,6 @@ class HandleManager:
|
|
745
745
|
self._respond_result(result)
|
746
746
|
|
747
747
|
def handle_request_status(self, record: Record) -> None:
|
748
|
-
# TODO(mempressure): do something better?
|
749
|
-
assert record.control.req_resp
|
750
748
|
result = proto_util._result_from_record(record)
|
751
749
|
self._respond_result(result)
|
752
750
|
|
wandb/sdk/internal/internal.py
CHANGED
@@ -423,15 +423,18 @@ class JobBuilder:
|
|
423
423
|
api: Api,
|
424
424
|
build_context: Optional[str] = None,
|
425
425
|
dockerfile: Optional[str] = None,
|
426
|
+
base_image: Optional[str] = None,
|
426
427
|
) -> Optional[Artifact]:
|
427
428
|
"""Build a job artifact from the current run.
|
428
429
|
|
429
430
|
Arguments:
|
431
|
+
api (Api): The API object to use to create the job artifact.
|
430
432
|
build_context (Optional[str]): Path within the job source code to
|
431
433
|
the image build context. Saved as part of the job for future
|
432
434
|
builds.
|
433
435
|
dockerfile (Optional[str]): Path within the build context the
|
434
436
|
Dockerfile. Saved as part of the job for future builds.
|
437
|
+
base_image (Optional[str]): The base image used to run the job code.
|
435
438
|
|
436
439
|
Returns:
|
437
440
|
Optional[Artifact]: The job artifact if it was successfully built,
|
@@ -467,8 +470,6 @@ class JobBuilder:
|
|
467
470
|
"warn",
|
468
471
|
)
|
469
472
|
return None
|
470
|
-
metadata["dockerfile"] = dockerfile
|
471
|
-
metadata["build_context"] = build_context
|
472
473
|
|
473
474
|
runtime: Optional[str] = metadata.get("python")
|
474
475
|
# can't build a job without a python version
|
@@ -520,6 +521,8 @@ class JobBuilder:
|
|
520
521
|
source["build_context"] = build_context # type: ignore[typeddict-item]
|
521
522
|
if dockerfile:
|
522
523
|
source["dockerfile"] = dockerfile # type: ignore[typeddict-item]
|
524
|
+
if base_image:
|
525
|
+
source["base_image"] = base_image # type: ignore[typeddict-item]
|
523
526
|
|
524
527
|
# Pop any keys that are initialized to None. The current TypedDict
|
525
528
|
# system for source dicts requires all keys to be present, but we
|
wandb/sdk/internal/tb_watcher.py
CHANGED
@@ -123,7 +123,7 @@ class TBWatcher:
|
|
123
123
|
self._force = force
|
124
124
|
# TODO(jhr): do we need locking in this queue?
|
125
125
|
self._watcher_queue = queue.PriorityQueue()
|
126
|
-
wandb.tensorboard.reset_state()
|
126
|
+
wandb.tensorboard.reset_state() # type: ignore
|
127
127
|
|
128
128
|
def _calculate_namespace(self, logdir: str, rootdir: str) -> Optional[str]:
|
129
129
|
namespace: Optional[str]
|
@@ -430,7 +430,7 @@ class TBEventConsumer:
|
|
430
430
|
def _handle_event(
|
431
431
|
self, event: "ProtoEvent", history: Optional["TBHistory"] = None
|
432
432
|
) -> None:
|
433
|
-
wandb.tensorboard._log(
|
433
|
+
wandb.tensorboard._log( # type: ignore
|
434
434
|
event.event,
|
435
435
|
step=event.event.step,
|
436
436
|
namespace=event.namespace,
|
wandb/sdk/internal/update.py
CHANGED
@@ -10,7 +10,7 @@ def _find_available(
|
|
10
10
|
) -> Optional[Tuple[str, bool, bool, bool, Optional[str]]]:
|
11
11
|
from wandb.util import parse_version
|
12
12
|
|
13
|
-
pypi_url =
|
13
|
+
pypi_url = "https://pypi.org/pypi/wandb/json"
|
14
14
|
|
15
15
|
yanked_dict = {}
|
16
16
|
try:
|
@@ -78,7 +78,7 @@ def check_available(current_version: str) -> Optional[Dict[str, Optional[str]]]:
|
|
78
78
|
if not package_info:
|
79
79
|
return None
|
80
80
|
|
81
|
-
wandb_module_name = wandb
|
81
|
+
wandb_module_name = "wandb"
|
82
82
|
|
83
83
|
latest_version, pip_prerelease, deleted, yanked, yanked_reason = package_info
|
84
84
|
upgrade_message = (
|
@@ -63,6 +63,13 @@ else:
|
|
63
63
|
NAMESPACE = "wandb"
|
64
64
|
|
65
65
|
|
66
|
+
def get_pod_name_safe(job: client.V1Job):
|
67
|
+
try:
|
68
|
+
return job.spec.template.metadata.name
|
69
|
+
except AttributeError:
|
70
|
+
return None
|
71
|
+
|
72
|
+
|
66
73
|
async def _wait_for_completion(
|
67
74
|
batch_client: client.BatchV1Api, job_name: str, deadline_secs: Optional[int] = None
|
68
75
|
) -> bool:
|
@@ -319,17 +326,18 @@ class KanikoBuilder(AbstractBuilder):
|
|
319
326
|
await self._create_docker_ecr_config_map(
|
320
327
|
build_job_name, core_v1, repo_uri
|
321
328
|
)
|
322
|
-
await batch_v1.create_namespaced_job(NAMESPACE, build_job)
|
323
|
-
|
329
|
+
k8s_job = await batch_v1.create_namespaced_job(NAMESPACE, build_job)
|
324
330
|
# wait for double the job deadline since it might take time to schedule
|
325
331
|
if not await _wait_for_completion(
|
326
332
|
batch_v1, build_job_name, 3 * _DEFAULT_BUILD_TIMEOUT_SECS
|
327
333
|
):
|
328
334
|
if job_tracker:
|
329
335
|
job_tracker.set_err_stage("build")
|
330
|
-
|
331
|
-
|
332
|
-
|
336
|
+
msg = f"Failed to build image in kaniko for job {run_id}."
|
337
|
+
pod_name = get_pod_name_safe(k8s_job)
|
338
|
+
if pod_name:
|
339
|
+
msg += f" View logs with `kubectl logs -n {NAMESPACE} {pod_name}`."
|
340
|
+
raise Exception(msg)
|
333
341
|
try:
|
334
342
|
pods_from_job = await core_v1.list_namespaced_pod(
|
335
343
|
namespace=NAMESPACE, label_selector=f"job-name={build_job_name}"
|
wandb/sdk/launch/create_job.py
CHANGED
@@ -114,6 +114,7 @@ def _create_job(
|
|
114
114
|
git_hash: Optional[str] = None,
|
115
115
|
build_context: Optional[str] = None,
|
116
116
|
dockerfile: Optional[str] = None,
|
117
|
+
base_image: Optional[str] = None,
|
117
118
|
) -> Tuple[Optional[Artifact], str, List[str]]:
|
118
119
|
wandb.termlog(f"Creating launch job of type: {job_type}...")
|
119
120
|
|
@@ -188,6 +189,7 @@ def _create_job(
|
|
188
189
|
api.api,
|
189
190
|
dockerfile=dockerfile,
|
190
191
|
build_context=build_context,
|
192
|
+
base_image=base_image,
|
191
193
|
)
|
192
194
|
if not artifact:
|
193
195
|
wandb.termerror("JobBuilder failed to build a job")
|
wandb/sdk/lib/apikey.py
CHANGED
@@ -107,7 +107,7 @@ def prompt_api_key( # noqa: C901
|
|
107
107
|
|
108
108
|
if jupyter and "google.colab" in sys.modules:
|
109
109
|
log_string = term.LOG_STRING_NOCOLOR
|
110
|
-
key = wandb.jupyter.attempt_colab_login(app_url)
|
110
|
+
key = wandb.jupyter.attempt_colab_login(app_url) # type: ignore
|
111
111
|
if key is not None:
|
112
112
|
write_key(settings, key, api=api)
|
113
113
|
return key # type: ignore
|
wandb/sdk/service/streams.py
CHANGED
@@ -81,9 +81,7 @@ class StreamRecord:
|
|
81
81
|
self._wait_thread_active()
|
82
82
|
|
83
83
|
def _wait_thread_active(self) -> None:
|
84
|
-
|
85
|
-
# TODO: using the default communicate timeout, is that enough? retries?
|
86
|
-
assert result
|
84
|
+
self._iface.deliver_status().wait(timeout=-1)
|
87
85
|
|
88
86
|
def join(self) -> None:
|
89
87
|
self._iface.join()
|
@@ -212,7 +210,7 @@ class StreamMux:
|
|
212
210
|
# run_id = action.stream_id # will want to fix if a streamid != runid
|
213
211
|
settings = action._data
|
214
212
|
thread = StreamThread(
|
215
|
-
target=wandb.wandb_sdk.internal.internal.wandb_internal,
|
213
|
+
target=wandb.wandb_sdk.internal.internal.wandb_internal, # type: ignore
|
216
214
|
kwargs=dict(
|
217
215
|
settings=settings,
|
218
216
|
record_q=stream._record_q,
|
wandb/sdk/wandb_config.py
CHANGED
@@ -61,7 +61,7 @@ class Config:
|
|
61
61
|
|
62
62
|
Using absl flags
|
63
63
|
```
|
64
|
-
flags.DEFINE_string(
|
64
|
+
flags.DEFINE_string("model", None, "model to run") # name, default, help
|
65
65
|
wandb.config.update(flags.FLAGS) # adds all absl flags to config
|
66
66
|
```
|
67
67
|
|