wandb 0.21.0__py3-none-win32.whl → 0.21.2__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 +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 +525 -360
- wandb/apis/public/artifacts.py +207 -13
- 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/_utils.py +14 -16
- wandb/apis/public/registries/registries_search.py +183 -304
- wandb/apis/public/reports.py +96 -15
- 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/automations/_generated/delete_automation.py +1 -3
- wandb/automations/_generated/enums.py +13 -11
- wandb/beta/workflows.py +66 -30
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +127 -3
- 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/data_pytorch.py +75 -0
- wandb/integration/metaflow/data_sklearn.py +76 -0
- wandb/integration/metaflow/errors.py +13 -0
- wandb/integration/metaflow/metaflow.py +167 -223
- wandb/integration/openai/fine_tuning.py +1 -2
- wandb/integration/weave/__init__.py +6 -0
- wandb/integration/weave/interface.py +49 -0
- wandb/integration/weave/weave.py +63 -0
- wandb/jupyter.py +5 -5
- wandb/plot/custom_chart.py +30 -7
- wandb/proto/v3/wandb_internal_pb2.py +281 -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/_factories.py +17 -0
- wandb/sdk/artifacts/_generated/__init__.py +221 -13
- wandb/sdk/artifacts/_generated/artifact_by_id.py +17 -0
- wandb/sdk/artifacts/_generated/artifact_by_name.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_created_by.py +47 -0
- wandb/sdk/artifacts/_generated/artifact_file_urls.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_type.py +31 -0
- wandb/sdk/artifacts/_generated/artifact_used_by.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +26 -0
- wandb/sdk/artifacts/_generated/delete_artifact.py +28 -0
- wandb/sdk/artifacts/_generated/enums.py +5 -0
- wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +38 -0
- wandb/sdk/artifacts/_generated/fetch_registries.py +32 -0
- wandb/sdk/artifacts/_generated/fragments.py +279 -41
- wandb/sdk/artifacts/_generated/link_artifact.py +6 -0
- wandb/sdk/artifacts/_generated/operations.py +654 -51
- wandb/sdk/artifacts/_generated/registry_collections.py +34 -0
- wandb/sdk/artifacts/_generated/registry_versions.py +34 -0
- wandb/sdk/artifacts/_generated/unlink_artifact.py +25 -0
- wandb/sdk/artifacts/_graphql_fragments.py +3 -86
- wandb/sdk/artifacts/_internal_artifact.py +19 -8
- wandb/sdk/artifacts/_validators.py +14 -4
- wandb/sdk/artifacts/artifact.py +512 -618
- wandb/sdk/artifacts/artifact_file_cache.py +10 -6
- wandb/sdk/artifacts/artifact_manifest.py +10 -9
- wandb/sdk/artifacts/artifact_manifest_entry.py +9 -10
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +5 -3
- wandb/sdk/artifacts/storage_handlers/http_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +1 -1
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +1 -1
- 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/interface/interface_queue.py +1 -4
- wandb/sdk/interface/interface_shared.py +26 -37
- wandb/sdk/interface/interface_sock.py +24 -14
- wandb/sdk/internal/internal_api.py +6 -0
- wandb/sdk/internal/job_builder.py +6 -0
- wandb/sdk/internal/settings_static.py +2 -3
- 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 +15 -2
- 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 +323 -1
- wandb/sdk/launch/sweeps/scheduler.py +2 -3
- wandb/sdk/lib/asyncio_compat.py +19 -16
- wandb/sdk/lib/asyncio_manager.py +252 -0
- wandb/sdk/lib/deprecate.py +1 -7
- wandb/sdk/lib/disabled.py +1 -1
- wandb/sdk/lib/hashutil.py +27 -5
- wandb/sdk/lib/module.py +7 -13
- wandb/sdk/lib/printer.py +2 -2
- wandb/sdk/lib/printer_asyncio.py +3 -1
- wandb/sdk/lib/progress.py +0 -19
- wandb/sdk/lib/retry.py +185 -78
- wandb/sdk/lib/service/service_client.py +106 -0
- wandb/sdk/lib/service/service_connection.py +20 -26
- wandb/sdk/lib/service/service_token.py +30 -13
- wandb/sdk/mailbox/mailbox.py +13 -5
- wandb/sdk/mailbox/mailbox_handle.py +22 -13
- wandb/sdk/mailbox/response_handle.py +42 -106
- wandb/sdk/mailbox/wait_with_progress.py +7 -42
- wandb/sdk/wandb_init.py +77 -116
- wandb/sdk/wandb_login.py +19 -15
- wandb/sdk/wandb_metric.py +2 -0
- wandb/sdk/wandb_run.py +497 -469
- wandb/sdk/wandb_settings.py +145 -4
- wandb/sdk/wandb_setup.py +204 -124
- wandb/sdk/wandb_sweep.py +14 -13
- wandb/sdk/wandb_watch.py +4 -6
- wandb/sync/sync.py +10 -0
- wandb/util.py +58 -1
- wandb/wandb_run.py +1 -2
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/METADATA +1 -1
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/RECORD +145 -129
- wandb/sdk/interface/interface_relay.py +0 -38
- wandb/sdk/interface/router.py +0 -89
- wandb/sdk/interface/router_queue.py +0 -43
- wandb/sdk/interface/router_relay.py +0 -50
- wandb/sdk/interface/router_sock.py +0 -32
- wandb/sdk/lib/sock_client.py +0 -236
- wandb/vendor/pynvml/__init__.py +0 -0
- wandb/vendor/pynvml/pynvml.py +0 -4779
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/WHEEL +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/entry_points.txt +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,38 +0,0 @@
|
|
1
|
-
"""InterfaceRelay - Derived from InterfaceQueue using RelayRouter to preserve uuid req/resp.
|
2
|
-
|
3
|
-
See interface.py for how interface classes relate to each other.
|
4
|
-
"""
|
5
|
-
|
6
|
-
from __future__ import annotations
|
7
|
-
|
8
|
-
import logging
|
9
|
-
from typing import TYPE_CHECKING
|
10
|
-
|
11
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
12
|
-
from wandb.sdk.mailbox import Mailbox
|
13
|
-
|
14
|
-
from .interface_queue import InterfaceQueue
|
15
|
-
|
16
|
-
if TYPE_CHECKING:
|
17
|
-
from queue import Queue
|
18
|
-
|
19
|
-
|
20
|
-
logger = logging.getLogger("wandb")
|
21
|
-
|
22
|
-
|
23
|
-
class InterfaceRelay(InterfaceQueue):
|
24
|
-
_mailbox: Mailbox
|
25
|
-
|
26
|
-
def __init__(
|
27
|
-
self,
|
28
|
-
mailbox: Mailbox,
|
29
|
-
record_q: Queue[pb.Record],
|
30
|
-
result_q: Queue[pb.Result],
|
31
|
-
relay_q: Queue[pb.Result],
|
32
|
-
) -> None:
|
33
|
-
self.relay_q = relay_q
|
34
|
-
super().__init__(
|
35
|
-
record_q=record_q,
|
36
|
-
result_q=result_q,
|
37
|
-
mailbox=mailbox,
|
38
|
-
)
|
wandb/sdk/interface/router.py
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
"""Router - handle message router (base class).
|
2
|
-
|
3
|
-
Router to manage responses.
|
4
|
-
|
5
|
-
"""
|
6
|
-
|
7
|
-
from __future__ import annotations
|
8
|
-
|
9
|
-
import logging
|
10
|
-
import threading
|
11
|
-
from abc import abstractmethod
|
12
|
-
from typing import TYPE_CHECKING
|
13
|
-
|
14
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
15
|
-
from wandb.proto import wandb_server_pb2 as spb
|
16
|
-
from wandb.sdk import mailbox
|
17
|
-
|
18
|
-
if TYPE_CHECKING:
|
19
|
-
from queue import Queue
|
20
|
-
|
21
|
-
|
22
|
-
logger = logging.getLogger("wandb")
|
23
|
-
|
24
|
-
|
25
|
-
class MessageRouterClosedError(Exception):
|
26
|
-
"""Router has been closed."""
|
27
|
-
|
28
|
-
|
29
|
-
class MessageRouter:
|
30
|
-
_request_queue: Queue[pb.Record]
|
31
|
-
_response_queue: Queue[pb.Result]
|
32
|
-
_mailbox: mailbox.Mailbox | None
|
33
|
-
|
34
|
-
def __init__(self, mailbox: mailbox.Mailbox | None = None) -> None:
|
35
|
-
self._mailbox = mailbox
|
36
|
-
self._lock = threading.Lock()
|
37
|
-
|
38
|
-
self._join_event = threading.Event()
|
39
|
-
self._thread = threading.Thread(target=self.message_loop)
|
40
|
-
self._thread.name = "MsgRouterThr"
|
41
|
-
self._thread.daemon = True
|
42
|
-
self._thread.start()
|
43
|
-
|
44
|
-
@abstractmethod
|
45
|
-
def _read_message(self) -> pb.Result | spb.ServerResponse | None:
|
46
|
-
raise NotImplementedError
|
47
|
-
|
48
|
-
@abstractmethod
|
49
|
-
def _send_message(self, record: pb.Record) -> None:
|
50
|
-
raise NotImplementedError
|
51
|
-
|
52
|
-
def message_loop(self) -> None:
|
53
|
-
try:
|
54
|
-
while not self._join_event.is_set():
|
55
|
-
try:
|
56
|
-
msg = self._read_message()
|
57
|
-
except EOFError:
|
58
|
-
# On abnormal shutdown the queue will be destroyed underneath
|
59
|
-
# resulting in EOFError. message_loop needs to exit..
|
60
|
-
logger.warning("EOFError seen in message_loop")
|
61
|
-
break
|
62
|
-
except MessageRouterClosedError as e:
|
63
|
-
logger.warning("message_loop has been closed", exc_info=e)
|
64
|
-
break
|
65
|
-
if not msg:
|
66
|
-
continue
|
67
|
-
self._handle_msg_rcv(msg)
|
68
|
-
|
69
|
-
finally:
|
70
|
-
if self._mailbox:
|
71
|
-
self._mailbox.close()
|
72
|
-
|
73
|
-
def join(self) -> None:
|
74
|
-
self._join_event.set()
|
75
|
-
self._thread.join()
|
76
|
-
|
77
|
-
def _handle_msg_rcv(self, msg: pb.Result | spb.ServerResponse) -> None:
|
78
|
-
if not self._mailbox:
|
79
|
-
return
|
80
|
-
|
81
|
-
if isinstance(msg, pb.Result) and msg.control.mailbox_slot:
|
82
|
-
self._mailbox.deliver(
|
83
|
-
spb.ServerResponse(
|
84
|
-
request_id=msg.control.mailbox_slot,
|
85
|
-
result_communicate=msg,
|
86
|
-
)
|
87
|
-
)
|
88
|
-
elif isinstance(msg, spb.ServerResponse) and msg.request_id:
|
89
|
-
self._mailbox.deliver(msg)
|
@@ -1,43 +0,0 @@
|
|
1
|
-
"""Router - handle message router (queue).
|
2
|
-
|
3
|
-
Router to manage responses from a queue.
|
4
|
-
|
5
|
-
"""
|
6
|
-
|
7
|
-
from __future__ import annotations
|
8
|
-
|
9
|
-
import queue
|
10
|
-
from typing import TYPE_CHECKING
|
11
|
-
|
12
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
13
|
-
from wandb.sdk.mailbox import Mailbox
|
14
|
-
|
15
|
-
from .router import MessageRouter
|
16
|
-
|
17
|
-
if TYPE_CHECKING:
|
18
|
-
from queue import Queue
|
19
|
-
|
20
|
-
|
21
|
-
class MessageQueueRouter(MessageRouter):
|
22
|
-
_request_queue: Queue[pb.Record]
|
23
|
-
_response_queue: Queue[pb.Result]
|
24
|
-
|
25
|
-
def __init__(
|
26
|
-
self,
|
27
|
-
request_queue: Queue[pb.Record],
|
28
|
-
response_queue: Queue[pb.Result],
|
29
|
-
mailbox: Mailbox | None = None,
|
30
|
-
) -> None:
|
31
|
-
self._request_queue = request_queue
|
32
|
-
self._response_queue = response_queue
|
33
|
-
super().__init__(mailbox=mailbox)
|
34
|
-
|
35
|
-
def _read_message(self) -> pb.Result | None:
|
36
|
-
try:
|
37
|
-
msg = self._response_queue.get(timeout=1)
|
38
|
-
except queue.Empty:
|
39
|
-
return None
|
40
|
-
return msg
|
41
|
-
|
42
|
-
def _send_message(self, record: pb.Record) -> None:
|
43
|
-
self._request_queue.put(record)
|
@@ -1,50 +0,0 @@
|
|
1
|
-
"""Router - handle message router (relay).
|
2
|
-
|
3
|
-
Router to manage responses from a queue with relay.
|
4
|
-
|
5
|
-
"""
|
6
|
-
|
7
|
-
from __future__ import annotations
|
8
|
-
|
9
|
-
from typing import TYPE_CHECKING
|
10
|
-
|
11
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
12
|
-
from wandb.proto import wandb_server_pb2 as spb
|
13
|
-
from wandb.sdk.mailbox import Mailbox
|
14
|
-
|
15
|
-
from .router_queue import MessageQueueRouter
|
16
|
-
|
17
|
-
if TYPE_CHECKING:
|
18
|
-
from queue import Queue
|
19
|
-
|
20
|
-
|
21
|
-
class MessageRelayRouter(MessageQueueRouter):
|
22
|
-
_relay_queue: Queue[pb.Result]
|
23
|
-
|
24
|
-
def __init__(
|
25
|
-
self,
|
26
|
-
request_queue: Queue[pb.Record],
|
27
|
-
response_queue: Queue[pb.Result],
|
28
|
-
relay_queue: Queue[pb.Result],
|
29
|
-
mailbox: Mailbox,
|
30
|
-
) -> None:
|
31
|
-
self._relay_queue = relay_queue
|
32
|
-
super().__init__(
|
33
|
-
request_queue=request_queue,
|
34
|
-
response_queue=response_queue,
|
35
|
-
mailbox=mailbox,
|
36
|
-
)
|
37
|
-
|
38
|
-
def _handle_msg_rcv(self, msg: pb.Result | spb.ServerResponse) -> None:
|
39
|
-
if isinstance(msg, pb.Result):
|
40
|
-
relay_msg = msg
|
41
|
-
else:
|
42
|
-
relay_msg = msg.result_communicate
|
43
|
-
|
44
|
-
# This is legacy-service logic for returning responses to the client.
|
45
|
-
# A different thread reads the "relay queue" and writes responses on
|
46
|
-
# the socket.
|
47
|
-
if relay_msg.control.relay_id:
|
48
|
-
self._relay_queue.put(relay_msg)
|
49
|
-
else:
|
50
|
-
super()._handle_msg_rcv(msg)
|
@@ -1,32 +0,0 @@
|
|
1
|
-
"""Router - handle message router (sock).
|
2
|
-
|
3
|
-
Router to manage responses from a socket client.
|
4
|
-
|
5
|
-
"""
|
6
|
-
|
7
|
-
from __future__ import annotations
|
8
|
-
|
9
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
10
|
-
from wandb.proto import wandb_server_pb2 as spb
|
11
|
-
from wandb.sdk.lib.sock_client import SockClient, SockClientClosedError
|
12
|
-
from wandb.sdk.mailbox import Mailbox
|
13
|
-
|
14
|
-
from .router import MessageRouter, MessageRouterClosedError
|
15
|
-
|
16
|
-
|
17
|
-
class MessageSockRouter(MessageRouter):
|
18
|
-
_sock_client: SockClient
|
19
|
-
_mailbox: Mailbox
|
20
|
-
|
21
|
-
def __init__(self, sock_client: SockClient, mailbox: Mailbox) -> None:
|
22
|
-
self._sock_client = sock_client
|
23
|
-
super().__init__(mailbox=mailbox)
|
24
|
-
|
25
|
-
def _read_message(self) -> spb.ServerResponse | None:
|
26
|
-
try:
|
27
|
-
return self._sock_client.read_server_response(timeout=1)
|
28
|
-
except SockClientClosedError as e:
|
29
|
-
raise MessageRouterClosedError from e
|
30
|
-
|
31
|
-
def _send_message(self, record: pb.Record) -> None:
|
32
|
-
self._sock_client.send_record_communicate(record)
|
wandb/sdk/lib/sock_client.py
DELETED
@@ -1,236 +0,0 @@
|
|
1
|
-
import socket
|
2
|
-
import struct
|
3
|
-
import threading
|
4
|
-
import time
|
5
|
-
import uuid
|
6
|
-
from typing import TYPE_CHECKING, Any, List, Optional
|
7
|
-
|
8
|
-
from wandb.proto import wandb_server_pb2 as spb
|
9
|
-
|
10
|
-
if TYPE_CHECKING:
|
11
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
12
|
-
|
13
|
-
|
14
|
-
class SockClientClosedError(Exception):
|
15
|
-
"""Raised on operations on a closed socket."""
|
16
|
-
|
17
|
-
|
18
|
-
class SockClientTimeoutError(Exception):
|
19
|
-
"""Raised if the server didn't respond before the timeout."""
|
20
|
-
|
21
|
-
|
22
|
-
class SockBuffer:
|
23
|
-
_buf_list: List[bytes]
|
24
|
-
_buf_lengths: List[int]
|
25
|
-
_buf_total: int
|
26
|
-
|
27
|
-
def __init__(self) -> None:
|
28
|
-
self._buf_list = []
|
29
|
-
self._buf_lengths = []
|
30
|
-
self._buf_total = 0
|
31
|
-
|
32
|
-
@property
|
33
|
-
def length(self) -> int:
|
34
|
-
return self._buf_total
|
35
|
-
|
36
|
-
def _get(self, start: int, end: int, peek: bool = False) -> bytes:
|
37
|
-
index: Optional[int] = None
|
38
|
-
buffers = []
|
39
|
-
need = end
|
40
|
-
|
41
|
-
# compute buffers needed
|
42
|
-
for i, (buf_len, buf_data) in enumerate(zip(self._buf_lengths, self._buf_list)):
|
43
|
-
buffers.append(buf_data[:need] if need < buf_len else buf_data)
|
44
|
-
if need <= buf_len:
|
45
|
-
index = i
|
46
|
-
break
|
47
|
-
need -= buf_len
|
48
|
-
|
49
|
-
# buffer not large enough, caller should have made sure there was enough data
|
50
|
-
if index is None:
|
51
|
-
raise IndexError("SockBuffer index out of range")
|
52
|
-
|
53
|
-
# advance buffer internals if we are not peeking into the data
|
54
|
-
if not peek:
|
55
|
-
self._buf_total -= end
|
56
|
-
if need < buf_len:
|
57
|
-
# update partially used buffer list
|
58
|
-
self._buf_list = self._buf_list[index:]
|
59
|
-
self._buf_lengths = self._buf_lengths[index:]
|
60
|
-
self._buf_list[0] = self._buf_list[0][need:]
|
61
|
-
self._buf_lengths[0] -= need
|
62
|
-
else:
|
63
|
-
# update fully used buffer list
|
64
|
-
self._buf_list = self._buf_list[index + 1 :]
|
65
|
-
self._buf_lengths = self._buf_lengths[index + 1 :]
|
66
|
-
|
67
|
-
return b"".join(buffers)[start:end]
|
68
|
-
|
69
|
-
def get(self, start: int, end: int) -> bytes:
|
70
|
-
return self._get(start, end)
|
71
|
-
|
72
|
-
def peek(self, start: int, end: int) -> bytes:
|
73
|
-
return self._get(start, end, peek=True)
|
74
|
-
|
75
|
-
def put(self, data: bytes, data_len: int) -> None:
|
76
|
-
self._buf_list.append(data)
|
77
|
-
self._buf_lengths.append(data_len)
|
78
|
-
self._buf_total += data_len
|
79
|
-
|
80
|
-
|
81
|
-
class SockClient:
|
82
|
-
# current header is magic byte "W" followed by 4 byte length of the message
|
83
|
-
HEADLEN = 1 + 4
|
84
|
-
|
85
|
-
def __init__(self, sock: socket.socket) -> None:
|
86
|
-
"""Create a SockClient.
|
87
|
-
|
88
|
-
Args:
|
89
|
-
sock: A connected socket.
|
90
|
-
"""
|
91
|
-
self._sock = sock
|
92
|
-
|
93
|
-
# TODO: use safe uuid's (python3.7+) or emulate this
|
94
|
-
self._sockid = uuid.uuid4().hex
|
95
|
-
self._retry_delay = 0.1
|
96
|
-
self._lock = threading.Lock()
|
97
|
-
self._bufsize = 4096
|
98
|
-
self._buffer = SockBuffer()
|
99
|
-
|
100
|
-
self._detect_bufsize()
|
101
|
-
|
102
|
-
def _detect_bufsize(self) -> None:
|
103
|
-
sndbuf_size = self._sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
|
104
|
-
rcvbuf_size = self._sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
|
105
|
-
self._bufsize = min(sndbuf_size, rcvbuf_size, 65536)
|
106
|
-
|
107
|
-
def close(self) -> None:
|
108
|
-
self._sock.close()
|
109
|
-
|
110
|
-
def shutdown(self, val: int) -> None:
|
111
|
-
self._sock.shutdown(val)
|
112
|
-
|
113
|
-
def set_socket(self, sock: socket.socket) -> None:
|
114
|
-
self._sock = sock
|
115
|
-
self._detect_bufsize()
|
116
|
-
|
117
|
-
def _sendall_with_error_handle(self, data: bytes) -> None:
|
118
|
-
# This is a helper function for sending data in a retry fashion.
|
119
|
-
# Similar to the sendall() function in the socket module, but with
|
120
|
-
# an error handling in case of timeout.
|
121
|
-
total_sent = 0
|
122
|
-
total_data = len(data)
|
123
|
-
while total_sent < total_data:
|
124
|
-
start_time = time.monotonic()
|
125
|
-
try:
|
126
|
-
sent = self._sock.send(data)
|
127
|
-
# sent equal to 0 indicates a closed socket
|
128
|
-
if sent == 0:
|
129
|
-
raise SockClientClosedError("socket connection broken")
|
130
|
-
total_sent += sent
|
131
|
-
# truncate our data to save memory
|
132
|
-
data = data[sent:]
|
133
|
-
# we handle the timeout case for the cases when timeout is set
|
134
|
-
# on a system level by another application
|
135
|
-
except socket.timeout:
|
136
|
-
# adding sleep to avoid tight loop
|
137
|
-
delta_time = time.monotonic() - start_time
|
138
|
-
if delta_time < self._retry_delay:
|
139
|
-
time.sleep(self._retry_delay - delta_time)
|
140
|
-
|
141
|
-
def _send_message(self, msg: Any) -> None:
|
142
|
-
raw_size = msg.ByteSize()
|
143
|
-
data = msg.SerializeToString()
|
144
|
-
assert len(data) == raw_size, "invalid serialization"
|
145
|
-
header = struct.pack("<BI", ord("W"), raw_size)
|
146
|
-
with self._lock:
|
147
|
-
self._sendall_with_error_handle(header + data)
|
148
|
-
|
149
|
-
def send_server_request(self, msg: spb.ServerRequest) -> None:
|
150
|
-
self._send_message(msg)
|
151
|
-
|
152
|
-
def send_server_response(self, msg: spb.ServerResponse) -> None:
|
153
|
-
try:
|
154
|
-
self._send_message(msg)
|
155
|
-
except BrokenPipeError:
|
156
|
-
# TODO(jhr): user thread might no longer be around to receive responses to
|
157
|
-
# things like network status poll loop, there might be a better way to quiesce
|
158
|
-
pass
|
159
|
-
|
160
|
-
def send_record_communicate(self, record: "pb.Record") -> None:
|
161
|
-
server_req = spb.ServerRequest()
|
162
|
-
server_req.request_id = record.control.mailbox_slot
|
163
|
-
server_req.record_communicate.CopyFrom(record)
|
164
|
-
self.send_server_request(server_req)
|
165
|
-
|
166
|
-
def send_record_publish(self, record: "pb.Record") -> None:
|
167
|
-
server_req = spb.ServerRequest()
|
168
|
-
server_req.request_id = record.control.mailbox_slot
|
169
|
-
server_req.record_publish.CopyFrom(record)
|
170
|
-
self.send_server_request(server_req)
|
171
|
-
|
172
|
-
def _extract_packet_bytes(self) -> Optional[bytes]:
|
173
|
-
# Do we have enough data to read the header?
|
174
|
-
start_offset = self.HEADLEN
|
175
|
-
if self._buffer.length >= start_offset:
|
176
|
-
header = self._buffer.peek(0, start_offset)
|
177
|
-
fields = struct.unpack("<BI", header)
|
178
|
-
magic, dlength = fields
|
179
|
-
assert magic == ord("W")
|
180
|
-
# Do we have enough data to read the full record?
|
181
|
-
end_offset = self.HEADLEN + dlength
|
182
|
-
if self._buffer.length >= end_offset:
|
183
|
-
rec_data = self._buffer.get(start_offset, end_offset)
|
184
|
-
return rec_data
|
185
|
-
return None
|
186
|
-
|
187
|
-
def _read_packet_bytes(self, timeout: Optional[int] = None) -> Optional[bytes]:
|
188
|
-
"""Read full message from socket.
|
189
|
-
|
190
|
-
Args:
|
191
|
-
timeout: number of seconds to wait on socket data.
|
192
|
-
|
193
|
-
Raises:
|
194
|
-
SockClientClosedError: socket has been closed.
|
195
|
-
"""
|
196
|
-
while True:
|
197
|
-
rec = self._extract_packet_bytes()
|
198
|
-
if rec:
|
199
|
-
return rec
|
200
|
-
|
201
|
-
if timeout:
|
202
|
-
self._sock.settimeout(timeout)
|
203
|
-
try:
|
204
|
-
data = self._sock.recv(self._bufsize)
|
205
|
-
except socket.timeout:
|
206
|
-
break
|
207
|
-
except OSError as e:
|
208
|
-
raise SockClientClosedError from e
|
209
|
-
finally:
|
210
|
-
if timeout:
|
211
|
-
self._sock.settimeout(None)
|
212
|
-
data_len = len(data)
|
213
|
-
if data_len == 0:
|
214
|
-
# socket.recv() will return 0 bytes if socket was shutdown
|
215
|
-
# caller will handle this condition like other connection problems
|
216
|
-
raise SockClientClosedError
|
217
|
-
self._buffer.put(data, data_len)
|
218
|
-
return None
|
219
|
-
|
220
|
-
def read_server_request(self) -> Optional[spb.ServerRequest]:
|
221
|
-
data = self._read_packet_bytes()
|
222
|
-
if not data:
|
223
|
-
return None
|
224
|
-
rec = spb.ServerRequest()
|
225
|
-
rec.ParseFromString(data)
|
226
|
-
return rec
|
227
|
-
|
228
|
-
def read_server_response(
|
229
|
-
self, timeout: Optional[int] = None
|
230
|
-
) -> Optional[spb.ServerResponse]:
|
231
|
-
data = self._read_packet_bytes(timeout=timeout)
|
232
|
-
if not data:
|
233
|
-
return None
|
234
|
-
rec = spb.ServerResponse()
|
235
|
-
rec.ParseFromString(data)
|
236
|
-
return rec
|
wandb/vendor/pynvml/__init__.py
DELETED
File without changes
|