bacommon.cloud

Functionality related to cloud functionality.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Functionality related to cloud functionality."""
  4
  5from __future__ import annotations
  6from dataclasses import dataclass, field
  7from typing import TYPE_CHECKING, Annotated, override
  8from enum import Enum
  9
 10from efro.message import Message, Response
 11from efro.dataclassio import ioprepped, IOAttrs
 12from bacommon.transfer import DirectoryManifest
 13from bacommon.login import LoginType
 14
 15if TYPE_CHECKING:
 16    pass
 17
 18
 19@ioprepped
 20@dataclass
 21class LoginProxyRequestMessage(Message):
 22    """Request send to the cloud to ask for a login-proxy."""
 23
 24    @override
 25    @classmethod
 26    def get_response_types(cls) -> list[type[Response] | None]:
 27        return [LoginProxyRequestResponse]
 28
 29
 30@ioprepped
 31@dataclass
 32class LoginProxyRequestResponse(Response):
 33    """Response to a request for a login proxy."""
 34
 35    # URL to direct the user to for sign in.
 36    url: Annotated[str, IOAttrs('u')]
 37
 38    # URL to use for overlay-web-browser sign ins.
 39    url_overlay: Annotated[str, IOAttrs('uo')]
 40
 41    # Proxy-Login id for querying results.
 42    proxyid: Annotated[str, IOAttrs('p')]
 43
 44    # Proxy-Login key for querying results.
 45    proxykey: Annotated[str, IOAttrs('k')]
 46
 47
 48@ioprepped
 49@dataclass
 50class LoginProxyStateQueryMessage(Message):
 51    """Soo.. how is that login proxy going?"""
 52
 53    proxyid: Annotated[str, IOAttrs('p')]
 54    proxykey: Annotated[str, IOAttrs('k')]
 55
 56    @override
 57    @classmethod
 58    def get_response_types(cls) -> list[type[Response] | None]:
 59        return [LoginProxyStateQueryResponse]
 60
 61
 62@ioprepped
 63@dataclass
 64class LoginProxyStateQueryResponse(Response):
 65    """Here's the info on that login-proxy you asked about, boss."""
 66
 67    class State(Enum):
 68        """States a login-proxy can be in."""
 69
 70        WAITING = 'waiting'
 71        SUCCESS = 'success'
 72        FAIL = 'fail'
 73
 74    state: Annotated[State, IOAttrs('s')]
 75
 76    # On success, these will be filled out.
 77    credentials: Annotated[str | None, IOAttrs('tk')]
 78
 79
 80@ioprepped
 81@dataclass
 82class LoginProxyCompleteMessage(Message):
 83    """Just so you know, we're done with this proxy."""
 84
 85    proxyid: Annotated[str, IOAttrs('p')]
 86
 87
 88@ioprepped
 89@dataclass
 90class PingMessage(Message):
 91    """Standard ping."""
 92
 93    @override
 94    @classmethod
 95    def get_response_types(cls) -> list[type[Response] | None]:
 96        return [PingResponse]
 97
 98
 99@ioprepped
100@dataclass
101class PingResponse(Response):
102    """pong."""
103
104
105@ioprepped
106@dataclass
107class TestMessage(Message):
108    """Can I get some of that workspace action?"""
109
110    testfoo: Annotated[int, IOAttrs('f')]
111
112    @override
113    @classmethod
114    def get_response_types(cls) -> list[type[Response] | None]:
115        return [TestResponse]
116
117
118@ioprepped
119@dataclass
120class TestResponse(Response):
121    """Here's that workspace you asked for, boss."""
122
123    testfoo: Annotated[int, IOAttrs('f')]
124
125
126@ioprepped
127@dataclass
128class SendInfoMessage(Message):
129    """User is using the send-info function"""
130
131    description: Annotated[str, IOAttrs('c')]
132
133    @override
134    @classmethod
135    def get_response_types(cls) -> list[type[Response] | None]:
136        return [SendInfoResponse]
137
138
139@ioprepped
140@dataclass
141class SendInfoResponse(Response):
142    """Response to sending into the server."""
143
144    handled: Annotated[bool, IOAttrs('v')]
145    message: Annotated[str | None, IOAttrs('m', store_default=False)] = None
146    legacy_code: Annotated[str | None, IOAttrs('l', store_default=False)] = None
147
148
149@ioprepped
150@dataclass
151class WorkspaceFetchState:
152    """Common state data for a workspace fetch."""
153
154    manifest: Annotated[DirectoryManifest, IOAttrs('m')]
155    iteration: Annotated[int, IOAttrs('i')] = 0
156    total_deletes: Annotated[int, IOAttrs('tdels')] = 0
157    total_downloads: Annotated[int, IOAttrs('tdlds')] = 0
158    total_up_to_date: Annotated[int | None, IOAttrs('tunmd')] = None
159
160
161@ioprepped
162@dataclass
163class WorkspaceFetchMessage(Message):
164    """Can I get some of that workspace action?"""
165
166    workspaceid: Annotated[str, IOAttrs('w')]
167    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
168
169    @override
170    @classmethod
171    def get_response_types(cls) -> list[type[Response] | None]:
172        return [WorkspaceFetchResponse]
173
174
175@ioprepped
176@dataclass
177class WorkspaceFetchResponse(Response):
178    """Here's that workspace you asked for, boss."""
179
180    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
181    deletes: Annotated[list[str], IOAttrs('dlt', store_default=False)] = field(
182        default_factory=list
183    )
184    downloads_inline: Annotated[
185        dict[str, bytes], IOAttrs('dinl', store_default=False)
186    ] = field(default_factory=dict)
187
188    done: Annotated[bool, IOAttrs('d')] = False
189
190
191@ioprepped
192@dataclass
193class MerchAvailabilityMessage(Message):
194    """Can we show merch link?"""
195
196    @override
197    @classmethod
198    def get_response_types(cls) -> list[type[Response] | None]:
199        return [MerchAvailabilityResponse]
200
201
202@ioprepped
203@dataclass
204class MerchAvailabilityResponse(Response):
205    """About that merch..."""
206
207    url: Annotated[str | None, IOAttrs('u')]
208
209
210@ioprepped
211@dataclass
212class SignInMessage(Message):
213    """Can I sign in please?"""
214
215    login_type: Annotated[LoginType, IOAttrs('l')]
216    sign_in_token: Annotated[str, IOAttrs('t')]
217
218    # For debugging. Can remove soft_default once build 20988+ is ubiquitous.
219    description: Annotated[str, IOAttrs('d', soft_default='-')]
220    apptime: Annotated[float, IOAttrs('at', soft_default=-1.0)]
221
222    @override
223    @classmethod
224    def get_response_types(cls) -> list[type[Response] | None]:
225        return [SignInResponse]
226
227
228@ioprepped
229@dataclass
230class SignInResponse(Response):
231    """Here's that sign-in result you asked for, boss."""
232
233    credentials: Annotated[str | None, IOAttrs('c')]
234
235
236@ioprepped
237@dataclass
238class ManageAccountMessage(Message):
239    """Message asking for a manage-account url."""
240
241    @override
242    @classmethod
243    def get_response_types(cls) -> list[type[Response] | None]:
244        return [ManageAccountResponse]
245
246
247@ioprepped
248@dataclass
249class ManageAccountResponse(Response):
250    """Here's that sign-in result you asked for, boss."""
251
252    url: Annotated[str | None, IOAttrs('u')]
@ioprepped
@dataclass
class LoginProxyRequestMessage(efro.message._message.Message):
20@ioprepped
21@dataclass
22class LoginProxyRequestMessage(Message):
23    """Request send to the cloud to ask for a login-proxy."""
24
25    @override
26    @classmethod
27    def get_response_types(cls) -> list[type[Response] | None]:
28        return [LoginProxyRequestResponse]

Request send to the cloud to ask for a login-proxy.

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
25    @override
26    @classmethod
27    def get_response_types(cls) -> list[type[Response] | None]:
28        return [LoginProxyRequestResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class LoginProxyRequestResponse(efro.message._message.Response):
31@ioprepped
32@dataclass
33class LoginProxyRequestResponse(Response):
34    """Response to a request for a login proxy."""
35
36    # URL to direct the user to for sign in.
37    url: Annotated[str, IOAttrs('u')]
38
39    # URL to use for overlay-web-browser sign ins.
40    url_overlay: Annotated[str, IOAttrs('uo')]
41
42    # Proxy-Login id for querying results.
43    proxyid: Annotated[str, IOAttrs('p')]
44
45    # Proxy-Login key for querying results.
46    proxykey: Annotated[str, IOAttrs('k')]

Response to a request for a login proxy.

LoginProxyRequestResponse( url: Annotated[str, <efro.dataclassio._base.IOAttrs object>], url_overlay: Annotated[str, <efro.dataclassio._base.IOAttrs object>], proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object>], proxykey: Annotated[str, <efro.dataclassio._base.IOAttrs object>])
url: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x107be69f0>]
url_overlay: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x107be6ba0>]
proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x107daeea0>]
proxykey: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x107daedb0>]
@ioprepped
@dataclass
class LoginProxyStateQueryMessage(efro.message._message.Message):
49@ioprepped
50@dataclass
51class LoginProxyStateQueryMessage(Message):
52    """Soo.. how is that login proxy going?"""
53
54    proxyid: Annotated[str, IOAttrs('p')]
55    proxykey: Annotated[str, IOAttrs('k')]
56
57    @override
58    @classmethod
59    def get_response_types(cls) -> list[type[Response] | None]:
60        return [LoginProxyStateQueryResponse]

Soo.. how is that login proxy going?

LoginProxyStateQueryMessage( proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object>], proxykey: Annotated[str, <efro.dataclassio._base.IOAttrs object>])
proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x10803b4a0>]
proxykey: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x108038ec0>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
57    @override
58    @classmethod
59    def get_response_types(cls) -> list[type[Response] | None]:
60        return [LoginProxyStateQueryResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class LoginProxyStateQueryResponse(efro.message._message.Response):
63@ioprepped
64@dataclass
65class LoginProxyStateQueryResponse(Response):
66    """Here's the info on that login-proxy you asked about, boss."""
67
68    class State(Enum):
69        """States a login-proxy can be in."""
70
71        WAITING = 'waiting'
72        SUCCESS = 'success'
73        FAIL = 'fail'
74
75    state: Annotated[State, IOAttrs('s')]
76
77    # On success, these will be filled out.
78    credentials: Annotated[str | None, IOAttrs('tk')]

Here's the info on that login-proxy you asked about, boss.

LoginProxyStateQueryResponse( state: Annotated[LoginProxyStateQueryResponse.State, <efro.dataclassio._base.IOAttrs object>], credentials: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>])
state: Annotated[LoginProxyStateQueryResponse.State, <efro.dataclassio._base.IOAttrs object at 0x10803aa20>]
credentials: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x10803ad50>]
class LoginProxyStateQueryResponse.State(enum.Enum):
68    class State(Enum):
69        """States a login-proxy can be in."""
70
71        WAITING = 'waiting'
72        SUCCESS = 'success'
73        FAIL = 'fail'

States a login-proxy can be in.

WAITING = <State.WAITING: 'waiting'>
SUCCESS = <State.SUCCESS: 'success'>
FAIL = <State.FAIL: 'fail'>
Inherited Members
enum.Enum
name
value
@ioprepped
@dataclass
class LoginProxyCompleteMessage(efro.message._message.Message):
81@ioprepped
82@dataclass
83class LoginProxyCompleteMessage(Message):
84    """Just so you know, we're done with this proxy."""
85
86    proxyid: Annotated[str, IOAttrs('p')]

Just so you know, we're done with this proxy.

LoginProxyCompleteMessage(proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object>])
proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x108615ee0>]
Inherited Members
efro.message._message.Message
get_response_types
@ioprepped
@dataclass
class PingMessage(efro.message._message.Message):
89@ioprepped
90@dataclass
91class PingMessage(Message):
92    """Standard ping."""
93
94    @override
95    @classmethod
96    def get_response_types(cls) -> list[type[Response] | None]:
97        return [PingResponse]

Standard ping.

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
94    @override
95    @classmethod
96    def get_response_types(cls) -> list[type[Response] | None]:
97        return [PingResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class PingResponse(efro.message._message.Response):
100@ioprepped
101@dataclass
102class PingResponse(Response):
103    """pong."""

pong.

@ioprepped
@dataclass
class TestMessage(efro.message._message.Message):
106@ioprepped
107@dataclass
108class TestMessage(Message):
109    """Can I get some of that workspace action?"""
110
111    testfoo: Annotated[int, IOAttrs('f')]
112
113    @override
114    @classmethod
115    def get_response_types(cls) -> list[type[Response] | None]:
116        return [TestResponse]

Can I get some of that workspace action?

TestMessage(testfoo: Annotated[int, <efro.dataclassio._base.IOAttrs object>])
testfoo: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x108616810>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
113    @override
114    @classmethod
115    def get_response_types(cls) -> list[type[Response] | None]:
116        return [TestResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class TestResponse(efro.message._message.Response):
119@ioprepped
120@dataclass
121class TestResponse(Response):
122    """Here's that workspace you asked for, boss."""
123
124    testfoo: Annotated[int, IOAttrs('f')]

Here's that workspace you asked for, boss.

TestResponse(testfoo: Annotated[int, <efro.dataclassio._base.IOAttrs object>])
testfoo: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1086177a0>]
@ioprepped
@dataclass
class SendInfoMessage(efro.message._message.Message):
127@ioprepped
128@dataclass
129class SendInfoMessage(Message):
130    """User is using the send-info function"""
131
132    description: Annotated[str, IOAttrs('c')]
133
134    @override
135    @classmethod
136    def get_response_types(cls) -> list[type[Response] | None]:
137        return [SendInfoResponse]

User is using the send-info function

SendInfoMessage(description: Annotated[str, <efro.dataclassio._base.IOAttrs object>])
description: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1086b5e20>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
134    @override
135    @classmethod
136    def get_response_types(cls) -> list[type[Response] | None]:
137        return [SendInfoResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class SendInfoResponse(efro.message._message.Response):
140@ioprepped
141@dataclass
142class SendInfoResponse(Response):
143    """Response to sending into the server."""
144
145    handled: Annotated[bool, IOAttrs('v')]
146    message: Annotated[str | None, IOAttrs('m', store_default=False)] = None
147    legacy_code: Annotated[str | None, IOAttrs('l', store_default=False)] = None

Response to sending into the server.

SendInfoResponse( handled: Annotated[bool, <efro.dataclassio._base.IOAttrs object>], message: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>] = None, legacy_code: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>] = None)
handled: Annotated[bool, <efro.dataclassio._base.IOAttrs object at 0x1086b6720>]
message: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x1086b4fb0>] = None
legacy_code: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x1086b5160>] = None
@ioprepped
@dataclass
class WorkspaceFetchState:
150@ioprepped
151@dataclass
152class WorkspaceFetchState:
153    """Common state data for a workspace fetch."""
154
155    manifest: Annotated[DirectoryManifest, IOAttrs('m')]
156    iteration: Annotated[int, IOAttrs('i')] = 0
157    total_deletes: Annotated[int, IOAttrs('tdels')] = 0
158    total_downloads: Annotated[int, IOAttrs('tdlds')] = 0
159    total_up_to_date: Annotated[int | None, IOAttrs('tunmd')] = None

Common state data for a workspace fetch.

WorkspaceFetchState( manifest: Annotated[bacommon.transfer.DirectoryManifest, <efro.dataclassio._base.IOAttrs object>], iteration: Annotated[int, <efro.dataclassio._base.IOAttrs object>] = 0, total_deletes: Annotated[int, <efro.dataclassio._base.IOAttrs object>] = 0, total_downloads: Annotated[int, <efro.dataclassio._base.IOAttrs object>] = 0, total_up_to_date: Annotated[int | None, <efro.dataclassio._base.IOAttrs object>] = None)
manifest: Annotated[bacommon.transfer.DirectoryManifest, <efro.dataclassio._base.IOAttrs object at 0x1086b5a90>]
iteration: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1086b6240>] = 0
total_deletes: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1086b6360>] = 0
total_downloads: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1086b64b0>] = 0
total_up_to_date: Annotated[int | None, <efro.dataclassio._base.IOAttrs object at 0x1086b6540>] = None
@ioprepped
@dataclass
class WorkspaceFetchMessage(efro.message._message.Message):
162@ioprepped
163@dataclass
164class WorkspaceFetchMessage(Message):
165    """Can I get some of that workspace action?"""
166
167    workspaceid: Annotated[str, IOAttrs('w')]
168    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
169
170    @override
171    @classmethod
172    def get_response_types(cls) -> list[type[Response] | None]:
173        return [WorkspaceFetchResponse]

Can I get some of that workspace action?

WorkspaceFetchMessage( workspaceid: Annotated[str, <efro.dataclassio._base.IOAttrs object>], state: Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object>])
workspaceid: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1086b7050>]
state: Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object at 0x1086b7920>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
170    @override
171    @classmethod
172    def get_response_types(cls) -> list[type[Response] | None]:
173        return [WorkspaceFetchResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class WorkspaceFetchResponse(efro.message._message.Response):
176@ioprepped
177@dataclass
178class WorkspaceFetchResponse(Response):
179    """Here's that workspace you asked for, boss."""
180
181    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
182    deletes: Annotated[list[str], IOAttrs('dlt', store_default=False)] = field(
183        default_factory=list
184    )
185    downloads_inline: Annotated[
186        dict[str, bytes], IOAttrs('dinl', store_default=False)
187    ] = field(default_factory=dict)
188
189    done: Annotated[bool, IOAttrs('d')] = False

Here's that workspace you asked for, boss.

WorkspaceFetchResponse( state: Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object>], deletes: Annotated[list[str], <efro.dataclassio._base.IOAttrs object>] = <factory>, downloads_inline: Annotated[dict[str, bytes], <efro.dataclassio._base.IOAttrs object>] = <factory>, done: Annotated[bool, <efro.dataclassio._base.IOAttrs object>] = False)
state: Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object at 0x1086d5a00>]
deletes: Annotated[list[str], <efro.dataclassio._base.IOAttrs object at 0x1086d4320>]
downloads_inline: Annotated[dict[str, bytes], <efro.dataclassio._base.IOAttrs object at 0x1086d4440>]
done: Annotated[bool, <efro.dataclassio._base.IOAttrs object at 0x1086d45f0>] = False
@ioprepped
@dataclass
class MerchAvailabilityMessage(efro.message._message.Message):
192@ioprepped
193@dataclass
194class MerchAvailabilityMessage(Message):
195    """Can we show merch link?"""
196
197    @override
198    @classmethod
199    def get_response_types(cls) -> list[type[Response] | None]:
200        return [MerchAvailabilityResponse]

Can we show merch link?

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
197    @override
198    @classmethod
199    def get_response_types(cls) -> list[type[Response] | None]:
200        return [MerchAvailabilityResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class MerchAvailabilityResponse(efro.message._message.Response):
203@ioprepped
204@dataclass
205class MerchAvailabilityResponse(Response):
206    """About that merch..."""
207
208    url: Annotated[str | None, IOAttrs('u')]

About that merch...

MerchAvailabilityResponse(url: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>])
url: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x1086d7980>]
@ioprepped
@dataclass
class SignInMessage(efro.message._message.Message):
211@ioprepped
212@dataclass
213class SignInMessage(Message):
214    """Can I sign in please?"""
215
216    login_type: Annotated[LoginType, IOAttrs('l')]
217    sign_in_token: Annotated[str, IOAttrs('t')]
218
219    # For debugging. Can remove soft_default once build 20988+ is ubiquitous.
220    description: Annotated[str, IOAttrs('d', soft_default='-')]
221    apptime: Annotated[float, IOAttrs('at', soft_default=-1.0)]
222
223    @override
224    @classmethod
225    def get_response_types(cls) -> list[type[Response] | None]:
226        return [SignInResponse]

Can I sign in please?

SignInMessage( login_type: Annotated[bacommon.login.LoginType, <efro.dataclassio._base.IOAttrs object>], sign_in_token: Annotated[str, <efro.dataclassio._base.IOAttrs object>], description: Annotated[str, <efro.dataclassio._base.IOAttrs object>], apptime: Annotated[float, <efro.dataclassio._base.IOAttrs object>])
login_type: Annotated[bacommon.login.LoginType, <efro.dataclassio._base.IOAttrs object at 0x1086d6c60>]
sign_in_token: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1086d6ea0>]
description: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1086d6f00>]
apptime: Annotated[float, <efro.dataclassio._base.IOAttrs object at 0x1086d6f90>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
223    @override
224    @classmethod
225    def get_response_types(cls) -> list[type[Response] | None]:
226        return [SignInResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class SignInResponse(efro.message._message.Response):
229@ioprepped
230@dataclass
231class SignInResponse(Response):
232    """Here's that sign-in result you asked for, boss."""
233
234    credentials: Annotated[str | None, IOAttrs('c')]

Here's that sign-in result you asked for, boss.

SignInResponse( credentials: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>])
credentials: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x108719850>]
@ioprepped
@dataclass
class ManageAccountMessage(efro.message._message.Message):
237@ioprepped
238@dataclass
239class ManageAccountMessage(Message):
240    """Message asking for a manage-account url."""
241
242    @override
243    @classmethod
244    def get_response_types(cls) -> list[type[Response] | None]:
245        return [ManageAccountResponse]

Message asking for a manage-account url.

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
242    @override
243    @classmethod
244    def get_response_types(cls) -> list[type[Response] | None]:
245        return [ManageAccountResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class ManageAccountResponse(efro.message._message.Response):
248@ioprepped
249@dataclass
250class ManageAccountResponse(Response):
251    """Here's that sign-in result you asked for, boss."""
252
253    url: Annotated[str | None, IOAttrs('u')]

Here's that sign-in result you asked for, boss.

ManageAccountResponse(url: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>])
url: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x1087194c0>]