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 login.
 36    url: Annotated[str, IOAttrs('u')]
 37
 38    # Proxy-Login id for querying results.
 39    proxyid: Annotated[str, IOAttrs('p')]
 40
 41    # Proxy-Login key for querying results.
 42    proxykey: Annotated[str, IOAttrs('k')]
 43
 44
 45@ioprepped
 46@dataclass
 47class LoginProxyStateQueryMessage(Message):
 48    """Soo.. how is that login proxy going?"""
 49
 50    proxyid: Annotated[str, IOAttrs('p')]
 51    proxykey: Annotated[str, IOAttrs('k')]
 52
 53    @override
 54    @classmethod
 55    def get_response_types(cls) -> list[type[Response] | None]:
 56        return [LoginProxyStateQueryResponse]
 57
 58
 59@ioprepped
 60@dataclass
 61class LoginProxyStateQueryResponse(Response):
 62    """Here's the info on that login-proxy you asked about, boss."""
 63
 64    class State(Enum):
 65        """States a login-proxy can be in."""
 66
 67        WAITING = 'waiting'
 68        SUCCESS = 'success'
 69        FAIL = 'fail'
 70
 71    state: Annotated[State, IOAttrs('s')]
 72
 73    # On success, these will be filled out.
 74    credentials: Annotated[str | None, IOAttrs('tk')]
 75
 76
 77@ioprepped
 78@dataclass
 79class LoginProxyCompleteMessage(Message):
 80    """Just so you know, we're done with this proxy."""
 81
 82    proxyid: Annotated[str, IOAttrs('p')]
 83
 84
 85@ioprepped
 86@dataclass
 87class PingMessage(Message):
 88    """Standard ping."""
 89
 90    @override
 91    @classmethod
 92    def get_response_types(cls) -> list[type[Response] | None]:
 93        return [PingResponse]
 94
 95
 96@ioprepped
 97@dataclass
 98class PingResponse(Response):
 99    """pong."""
100
101
102@ioprepped
103@dataclass
104class TestMessage(Message):
105    """Can I get some of that workspace action?"""
106
107    testfoo: Annotated[int, IOAttrs('f')]
108
109    @override
110    @classmethod
111    def get_response_types(cls) -> list[type[Response] | None]:
112        return [TestResponse]
113
114
115@ioprepped
116@dataclass
117class TestResponse(Response):
118    """Here's that workspace you asked for, boss."""
119
120    testfoo: Annotated[int, IOAttrs('f')]
121
122
123@ioprepped
124@dataclass
125class PromoCodeMessage(Message):
126    """User is entering a promo code"""
127
128    code: Annotated[str, IOAttrs('c')]
129
130    @override
131    @classmethod
132    def get_response_types(cls) -> list[type[Response] | None]:
133        return [PromoCodeResponse]
134
135
136@ioprepped
137@dataclass
138class PromoCodeResponse(Response):
139    """Applied that promo code for ya, boss."""
140
141    valid: Annotated[bool, IOAttrs('v')]
142    message: Annotated[str | None, IOAttrs('m', store_default=False)] = None
143
144
145@ioprepped
146@dataclass
147class WorkspaceFetchState:
148    """Common state data for a workspace fetch."""
149
150    manifest: Annotated[DirectoryManifest, IOAttrs('m')]
151    iteration: Annotated[int, IOAttrs('i')] = 0
152    total_deletes: Annotated[int, IOAttrs('tdels')] = 0
153    total_downloads: Annotated[int, IOAttrs('tdlds')] = 0
154    total_up_to_date: Annotated[int | None, IOAttrs('tunmd')] = None
155
156
157@ioprepped
158@dataclass
159class WorkspaceFetchMessage(Message):
160    """Can I get some of that workspace action?"""
161
162    workspaceid: Annotated[str, IOAttrs('w')]
163    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
164
165    @override
166    @classmethod
167    def get_response_types(cls) -> list[type[Response] | None]:
168        return [WorkspaceFetchResponse]
169
170
171@ioprepped
172@dataclass
173class WorkspaceFetchResponse(Response):
174    """Here's that workspace you asked for, boss."""
175
176    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
177    deletes: Annotated[list[str], IOAttrs('dlt', store_default=False)] = field(
178        default_factory=list
179    )
180    downloads_inline: Annotated[
181        dict[str, bytes], IOAttrs('dinl', store_default=False)
182    ] = field(default_factory=dict)
183
184    done: Annotated[bool, IOAttrs('d')] = False
185
186
187@ioprepped
188@dataclass
189class MerchAvailabilityMessage(Message):
190    """Can we show merch link?"""
191
192    @override
193    @classmethod
194    def get_response_types(cls) -> list[type[Response] | None]:
195        return [MerchAvailabilityResponse]
196
197
198@ioprepped
199@dataclass
200class MerchAvailabilityResponse(Response):
201    """About that merch..."""
202
203    url: Annotated[str | None, IOAttrs('u')]
204
205
206@ioprepped
207@dataclass
208class SignInMessage(Message):
209    """Can I sign in please?"""
210
211    login_type: Annotated[LoginType, IOAttrs('l')]
212    sign_in_token: Annotated[str, IOAttrs('t')]
213
214    # For debugging. Can remove soft_default once build 20988+ is ubiquitous.
215    description: Annotated[str, IOAttrs('d', soft_default='-')]
216    apptime: Annotated[float, IOAttrs('at', soft_default=-1.0)]
217
218    @override
219    @classmethod
220    def get_response_types(cls) -> list[type[Response] | None]:
221        return [SignInResponse]
222
223
224@ioprepped
225@dataclass
226class SignInResponse(Response):
227    """Here's that sign-in result you asked for, boss."""
228
229    credentials: Annotated[str | None, IOAttrs('c')]
230
231
232@ioprepped
233@dataclass
234class ManageAccountMessage(Message):
235    """Message asking for a manage-account url."""
236
237    @override
238    @classmethod
239    def get_response_types(cls) -> list[type[Response] | None]:
240        return [ManageAccountResponse]
241
242
243@ioprepped
244@dataclass
245class ManageAccountResponse(Response):
246    """Here's that sign-in result you asked for, boss."""
247
248    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 login.
37    url: Annotated[str, IOAttrs('u')]
38
39    # Proxy-Login id for querying results.
40    proxyid: Annotated[str, IOAttrs('p')]
41
42    # Proxy-Login key for querying results.
43    proxykey: Annotated[str, IOAttrs('k')]

Response to a request for a login proxy.

LoginProxyRequestResponse( url: 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 0x10399e6c0>]
proxyid: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x10399ebd0>]
proxykey: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x10399e180>]
@ioprepped
@dataclass
class LoginProxyStateQueryMessage(efro.message._message.Message):
46@ioprepped
47@dataclass
48class LoginProxyStateQueryMessage(Message):
49    """Soo.. how is that login proxy going?"""
50
51    proxyid: Annotated[str, IOAttrs('p')]
52    proxykey: Annotated[str, IOAttrs('k')]
53
54    @override
55    @classmethod
56    def get_response_types(cls) -> list[type[Response] | None]:
57        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 0x10379c650>]
proxykey: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x10379c410>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
54    @override
55    @classmethod
56    def get_response_types(cls) -> list[type[Response] | None]:
57        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):
60@ioprepped
61@dataclass
62class LoginProxyStateQueryResponse(Response):
63    """Here's the info on that login-proxy you asked about, boss."""
64
65    class State(Enum):
66        """States a login-proxy can be in."""
67
68        WAITING = 'waiting'
69        SUCCESS = 'success'
70        FAIL = 'fail'
71
72    state: Annotated[State, IOAttrs('s')]
73
74    # On success, these will be filled out.
75    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 0x103b66780>]
credentials: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x103b66a20>]
class LoginProxyStateQueryResponse.State(enum.Enum):
65    class State(Enum):
66        """States a login-proxy can be in."""
67
68        WAITING = 'waiting'
69        SUCCESS = 'success'
70        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):
78@ioprepped
79@dataclass
80class LoginProxyCompleteMessage(Message):
81    """Just so you know, we're done with this proxy."""
82
83    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 0x103af9700>]
Inherited Members
efro.message._message.Message
get_response_types
@ioprepped
@dataclass
class PingMessage(efro.message._message.Message):
86@ioprepped
87@dataclass
88class PingMessage(Message):
89    """Standard ping."""
90
91    @override
92    @classmethod
93    def get_response_types(cls) -> list[type[Response] | None]:
94        return [PingResponse]

Standard ping.

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
91    @override
92    @classmethod
93    def get_response_types(cls) -> list[type[Response] | None]:
94        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):
 97@ioprepped
 98@dataclass
 99class PingResponse(Response):
100    """pong."""

pong.

@ioprepped
@dataclass
class TestMessage(efro.message._message.Message):
103@ioprepped
104@dataclass
105class TestMessage(Message):
106    """Can I get some of that workspace action?"""
107
108    testfoo: Annotated[int, IOAttrs('f')]
109
110    @override
111    @classmethod
112    def get_response_types(cls) -> list[type[Response] | None]:
113        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 0x103afb260>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
110    @override
111    @classmethod
112    def get_response_types(cls) -> list[type[Response] | None]:
113        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):
116@ioprepped
117@dataclass
118class TestResponse(Response):
119    """Here's that workspace you asked for, boss."""
120
121    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 0x1040edc40>]
@ioprepped
@dataclass
class PromoCodeMessage(efro.message._message.Message):
124@ioprepped
125@dataclass
126class PromoCodeMessage(Message):
127    """User is entering a promo code"""
128
129    code: Annotated[str, IOAttrs('c')]
130
131    @override
132    @classmethod
133    def get_response_types(cls) -> list[type[Response] | None]:
134        return [PromoCodeResponse]

User is entering a promo code

PromoCodeMessage(code: Annotated[str, <efro.dataclassio._base.IOAttrs object>])
code: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1040ee8d0>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
131    @override
132    @classmethod
133    def get_response_types(cls) -> list[type[Response] | None]:
134        return [PromoCodeResponse]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

@ioprepped
@dataclass
class PromoCodeResponse(efro.message._message.Response):
137@ioprepped
138@dataclass
139class PromoCodeResponse(Response):
140    """Applied that promo code for ya, boss."""
141
142    valid: Annotated[bool, IOAttrs('v')]
143    message: Annotated[str | None, IOAttrs('m', store_default=False)] = None

Applied that promo code for ya, boss.

PromoCodeResponse( valid: Annotated[bool, <efro.dataclassio._base.IOAttrs object>], message: Annotated[str | None, <efro.dataclassio._base.IOAttrs object>] = None)
valid: Annotated[bool, <efro.dataclassio._base.IOAttrs object at 0x1040ed010>]
message: Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x1040ed310>] = None
@ioprepped
@dataclass
class WorkspaceFetchState:
146@ioprepped
147@dataclass
148class WorkspaceFetchState:
149    """Common state data for a workspace fetch."""
150
151    manifest: Annotated[DirectoryManifest, IOAttrs('m')]
152    iteration: Annotated[int, IOAttrs('i')] = 0
153    total_deletes: Annotated[int, IOAttrs('tdels')] = 0
154    total_downloads: Annotated[int, IOAttrs('tdlds')] = 0
155    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 0x1040efc20>]
iteration: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1040ee5a0>] = 0
total_deletes: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1040ee6c0>] = 0
total_downloads: Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1040ee7e0>] = 0
total_up_to_date: Annotated[int | None, <efro.dataclassio._base.IOAttrs object at 0x1040ee900>] = None
@ioprepped
@dataclass
class WorkspaceFetchMessage(efro.message._message.Message):
158@ioprepped
159@dataclass
160class WorkspaceFetchMessage(Message):
161    """Can I get some of that workspace action?"""
162
163    workspaceid: Annotated[str, IOAttrs('w')]
164    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
165
166    @override
167    @classmethod
168    def get_response_types(cls) -> list[type[Response] | None]:
169        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 0x1040ef5c0>]
state: Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object at 0x1040eff50>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
166    @override
167    @classmethod
168    def get_response_types(cls) -> list[type[Response] | None]:
169        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):
172@ioprepped
173@dataclass
174class WorkspaceFetchResponse(Response):
175    """Here's that workspace you asked for, boss."""
176
177    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
178    deletes: Annotated[list[str], IOAttrs('dlt', store_default=False)] = field(
179        default_factory=list
180    )
181    downloads_inline: Annotated[
182        dict[str, bytes], IOAttrs('dinl', store_default=False)
183    ] = field(default_factory=dict)
184
185    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 0x1042a8bf0>]
deletes: Annotated[list[str], <efro.dataclassio._base.IOAttrs object at 0x1042a8d10>]
downloads_inline: Annotated[dict[str, bytes], <efro.dataclassio._base.IOAttrs object at 0x1042a8e30>]
done: Annotated[bool, <efro.dataclassio._base.IOAttrs object at 0x1042a8fe0>] = False
@ioprepped
@dataclass
class MerchAvailabilityMessage(efro.message._message.Message):
188@ioprepped
189@dataclass
190class MerchAvailabilityMessage(Message):
191    """Can we show merch link?"""
192
193    @override
194    @classmethod
195    def get_response_types(cls) -> list[type[Response] | None]:
196        return [MerchAvailabilityResponse]

Can we show merch link?

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
193    @override
194    @classmethod
195    def get_response_types(cls) -> list[type[Response] | None]:
196        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):
199@ioprepped
200@dataclass
201class MerchAvailabilityResponse(Response):
202    """About that merch..."""
203
204    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 0x1042aa780>]
@ioprepped
@dataclass
class SignInMessage(efro.message._message.Message):
207@ioprepped
208@dataclass
209class SignInMessage(Message):
210    """Can I sign in please?"""
211
212    login_type: Annotated[LoginType, IOAttrs('l')]
213    sign_in_token: Annotated[str, IOAttrs('t')]
214
215    # For debugging. Can remove soft_default once build 20988+ is ubiquitous.
216    description: Annotated[str, IOAttrs('d', soft_default='-')]
217    apptime: Annotated[float, IOAttrs('at', soft_default=-1.0)]
218
219    @override
220    @classmethod
221    def get_response_types(cls) -> list[type[Response] | None]:
222        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 0x1042ab500>]
sign_in_token: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1042ab590>]
description: Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x1042ab5f0>]
apptime: Annotated[float, <efro.dataclassio._base.IOAttrs object at 0x1042ab680>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
219    @override
220    @classmethod
221    def get_response_types(cls) -> list[type[Response] | None]:
222        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):
225@ioprepped
226@dataclass
227class SignInResponse(Response):
228    """Here's that sign-in result you asked for, boss."""
229
230    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 0x1042c9f70>]
@ioprepped
@dataclass
class ManageAccountMessage(efro.message._message.Message):
233@ioprepped
234@dataclass
235class ManageAccountMessage(Message):
236    """Message asking for a manage-account url."""
237
238    @override
239    @classmethod
240    def get_response_types(cls) -> list[type[Response] | None]:
241        return [ManageAccountResponse]

Message asking for a manage-account url.

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
238    @override
239    @classmethod
240    def get_response_types(cls) -> list[type[Response] | None]:
241        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):
244@ioprepped
245@dataclass
246class ManageAccountResponse(Response):
247    """Here's that sign-in result you asked for, boss."""
248
249    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 0x1042cbaa0>]