Skip to content

Commit bfde1a1

Browse files
committed
fix: CustomCloud export, event handler & error handler
#625
1 parent ec7e085 commit bfde1a1

4 files changed

Lines changed: 24 additions & 15 deletions

File tree

scratchattach/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .cloud.cloud import ScratchCloud, TwCloud, get_cloud, get_scratch_cloud, get_tw_cloud
1+
from .cloud.cloud import CustomCloud, ScratchCloud, TwCloud, get_cloud, get_scratch_cloud, get_tw_cloud
22
from .cloud._base import BaseCloud, AnyCloud
33

44
from .eventhandlers.cloud_server import init_cloud_server

scratchattach/cloud/_base.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import annotations
2+
import traceback
23

34
import json
45
import ssl
@@ -9,6 +10,8 @@
910
from threading import Lock
1011
from collections.abc import Iterator
1112

13+
from scratchattach.cloud import cloud as cloud_module
14+
1215
if TYPE_CHECKING:
1316
from _typeshed import SupportsRead
1417
else:
@@ -173,7 +176,12 @@ class WebSocketEventStream(EventStream):
173176

174177
def __init__(self, cloud: BaseCloud):
175178
super().__init__()
176-
self.source_cloud = type(cloud)(project_id=cloud.project_id)
179+
# NOTE: maybe consider using copy.copy here (copy.deepcopy doesn't work as you cannot deepcopy a Thread)
180+
cloud_type = type(cloud)
181+
if cloud_type is cloud_module.CustomCloud:
182+
self.source_cloud = cloud_type(project_id=cloud.project_id, cloud_host=cloud.cloud_host)
183+
else:
184+
self.source_cloud = cloud_type(project_id=cloud.project_id)
177185
self.source_cloud._session = cloud._session
178186
self.source_cloud.cookie = cloud.cookie
179187
self.source_cloud.header = cloud.header
@@ -217,7 +225,6 @@ def read(self, amount: int = -1) -> Iterator[dict[str, Any]]:
217225
done = False
218226
# print("Getting data...")
219227
with self.reading:
220-
# print("Getting data...", end_time is None, end_time > time.time(), end_time is None or end_time > time.time())
221228
while not done:
222229
# print("Getting data...")
223230
try:
@@ -229,11 +236,18 @@ def read(self, amount: int = -1) -> Iterator[dict[str, Any]]:
229236
self.receive_new(timeout=timeout_end - time.time() if has_timeout else None)
230237
if not self.packets_left:
231238
continue
232-
yield json.loads(self.packets_left.pop(0))
233239
i += 1
240+
yield json.loads(self.packets_left.pop(0))
234241
done = True
242+
except json.JSONDecodeError as e:
243+
# this could happen e.g. when the scratchattach server sends the message
244+
# "This server uses @TimMcCool's scratchattach 2.0.0"
245+
warnings.warn(f"Invalid JSON sent from server: {e}")
235246
except Exception:
236-
# traceback.print_exc()
247+
# NOTE: at the very least for `except Exception`, let's print the traceback
248+
# ideally we would never even use `except Exception`. Maybe this is technical debt.
249+
# TODO: investigate what the exception we actually want to catch here
250+
traceback.print_exc()
237251
self.source_cloud.reconnect()
238252

239253
def __del__(self):

scratchattach/eventhandlers/cloud_events.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,15 @@ def _updater(self):
6363
# continue
6464
cloud_activity_dict = cast(CloudActivityDict, data)
6565
cloud_activity_dict["variable_name"] = cloud_activity_dict["name"]
66-
cloud_activity_dict["name"] = cloud_activity_dict[
67-
"variable_name"
68-
].replace("☁ ", "")
66+
cloud_activity_dict["name"] = cloud_activity_dict["variable_name"].replace("☁ ", "")
6967
_a._update_from_dict(cloud_activity_dict)
7068
# print(f"sending event {_a}")
7169
self.call_event(f"on_{_a.type}", [_a])
7270
except Exception as e:
7371
print(f"Cloud events _updated ignored: {e} {traceback.format_exc()}")
7472
pass
7573
except Exception:
74+
traceback.print_exc() # always print blanketed exceptions!!
7675
self.subsequent_reconnects += 1
7776
time.sleep(0.1) # cooldown
7877

@@ -88,9 +87,7 @@ class ManualCloudLogEvents:
8887

8988
def __init__(self, cloud: _base.LogCloud):
9089
if not isinstance(cloud, _base.LogCloud):
91-
raise ValueError(
92-
"Cloud log events can't be used with a cloud that has no logs available"
93-
)
90+
raise ValueError("Cloud log events can't be used with a cloud that has no logs available")
9491
self.cloud = cloud
9592
self.source_cloud = cloud
9693
self._session = cloud._session
@@ -121,9 +118,7 @@ class CloudLogEvents(BaseEventHandler):
121118
def __init__(self, cloud: _base.LogCloud, *, update_interval=0.1):
122119
super().__init__()
123120
if not isinstance(cloud, _base.LogCloud):
124-
raise ValueError(
125-
"Cloud log events can't be used with a cloud that has no logs available"
126-
)
121+
raise ValueError("Cloud log events can't be used with a cloud that has no logs available")
127122
self.cloud = cloud
128123
self.source_cloud = cloud
129124
self.update_interval = update_interval

tests/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)