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
  8from enum import Enum
  9
 10from typing_extensions import override
 11from efro.message import Message, Response
 12from efro.dataclassio import ioprepped, IOAttrs
 13from bacommon.transfer import DirectoryManifest
 14from bacommon.login import LoginType
 15
 16if TYPE_CHECKING:
 17    pass
 18
 19
 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]
 29
 30
 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')]
 44
 45
 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]
 58
 59
 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')]
 76
 77
 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')]
 84
 85
 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]
 95
 96
 97@ioprepped
 98@dataclass
 99class PingResponse(Response):
100    """pong."""
101
102
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]
114
115
116@ioprepped
117@dataclass
118class TestResponse(Response):
119    """Here's that workspace you asked for, boss."""
120
121    testfoo: Annotated[int, IOAttrs('f')]
122
123
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]
135
136
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
144
145
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
156
157
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]
170
171
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
186
187
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]
197
198
199@ioprepped
200@dataclass
201class MerchAvailabilityResponse(Response):
202    """About that merch..."""
203
204    url: Annotated[str | None, IOAttrs('u')]
205
206
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]
223
224
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')]
231
232
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]
242
243
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')]
@ioprepped
@dataclass
class LoginProxyRequestMessage(efro.message._message.Message):
21@ioprepped
22@dataclass
23class LoginProxyRequestMessage(Message):
24    """Request send to the cloud to ask for a login-proxy."""
25
26    @override
27    @classmethod
28    def get_response_types(cls) -> list[type[Response] | None]:
29        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]:
26    @override
27    @classmethod
28    def get_response_types(cls) -> list[type[Response] | None]:
29        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):
32@ioprepped
33@dataclass
34class LoginProxyRequestResponse(Response):
35    """Response to a request for a login proxy."""
36
37    # URL to direct the user to for login.
38    url: Annotated[str, IOAttrs('u')]
39
40    # Proxy-Login id for querying results.
41    proxyid: Annotated[str, IOAttrs('p')]
42
43    # Proxy-Login key for querying results.
44    proxykey: Annotated[str, IOAttrs('k')]

Response to a request for a login proxy.

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

Soo.. how is that login proxy going?

LoginProxyStateQueryMessage( proxyid: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object>], proxykey: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object>])
proxyid: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x103f7d890>]
proxykey: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x103e52fd0>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
55    @override
56    @classmethod
57    def get_response_types(cls) -> list[type[Response] | None]:
58        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):
61@ioprepped
62@dataclass
63class LoginProxyStateQueryResponse(Response):
64    """Here's the info on that login-proxy you asked about, boss."""
65
66    class State(Enum):
67        """States a login-proxy can be in."""
68
69        WAITING = 'waiting'
70        SUCCESS = 'success'
71        FAIL = 'fail'
72
73    state: Annotated[State, IOAttrs('s')]
74
75    # On success, these will be filled out.
76    credentials: Annotated[str | None, IOAttrs('tk')]

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

LoginProxyStateQueryResponse( state: typing.Annotated[LoginProxyStateQueryResponse.State, <efro.dataclassio._base.IOAttrs object>], credentials: typing.Annotated[str | None, <efro.dataclassio._base.IOAttrs object>])
state: typing.Annotated[LoginProxyStateQueryResponse.State, <efro.dataclassio._base.IOAttrs object at 0x1025eac90>]
credentials: typing.Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x103eb8750>]
class LoginProxyStateQueryResponse.State(enum.Enum):
66    class State(Enum):
67        """States a login-proxy can be in."""
68
69        WAITING = 'waiting'
70        SUCCESS = 'success'
71        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):
79@ioprepped
80@dataclass
81class LoginProxyCompleteMessage(Message):
82    """Just so you know, we're done with this proxy."""
83
84    proxyid: Annotated[str, IOAttrs('p')]

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

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

Standard ping.

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

pong.

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

Can I get some of that workspace action?

TestMessage( testfoo: typing.Annotated[int, <efro.dataclassio._base.IOAttrs object>])
testfoo: typing.Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x1029a3dd0>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
111    @override
112    @classmethod
113    def get_response_types(cls) -> list[type[Response] | None]:
114        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):
117@ioprepped
118@dataclass
119class TestResponse(Response):
120    """Here's that workspace you asked for, boss."""
121
122    testfoo: Annotated[int, IOAttrs('f')]

Here's that workspace you asked for, boss.

TestResponse( testfoo: typing.Annotated[int, <efro.dataclassio._base.IOAttrs object>])
testfoo: typing.Annotated[int, <efro.dataclassio._base.IOAttrs object at 0x103debd10>]
@ioprepped
@dataclass
class PromoCodeMessage(efro.message._message.Message):
125@ioprepped
126@dataclass
127class PromoCodeMessage(Message):
128    """User is entering a promo code"""
129
130    code: Annotated[str, IOAttrs('c')]
131
132    @override
133    @classmethod
134    def get_response_types(cls) -> list[type[Response] | None]:
135        return [PromoCodeResponse]

User is entering a promo code

PromoCodeMessage(code: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object>])
code: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x103f62bd0>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
132    @override
133    @classmethod
134    def get_response_types(cls) -> list[type[Response] | None]:
135        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):
138@ioprepped
139@dataclass
140class PromoCodeResponse(Response):
141    """Applied that promo code for ya, boss."""
142
143    valid: Annotated[bool, IOAttrs('v')]
144    message: Annotated[str | None, IOAttrs('m', store_default=False)] = None

Applied that promo code for ya, boss.

PromoCodeResponse( valid: typing.Annotated[bool, <efro.dataclassio._base.IOAttrs object>], message: typing.Annotated[str | None, <efro.dataclassio._base.IOAttrs object>] = None)
valid: typing.Annotated[bool, <efro.dataclassio._base.IOAttrs object at 0x1025ae950>]
message: typing.Annotated[str | None, <efro.dataclassio._base.IOAttrs object at 0x1033a0e10>] = None
@ioprepped
@dataclass
class WorkspaceFetchState:
147@ioprepped
148@dataclass
149class WorkspaceFetchState:
150    """Common state data for a workspace fetch."""
151
152    manifest: Annotated[DirectoryManifest, IOAttrs('m')]
153    iteration: Annotated[int, IOAttrs('i')] = 0
154    total_deletes: Annotated[int, IOAttrs('tdels')] = 0
155    total_downloads: Annotated[int, IOAttrs('tdlds')] = 0
156    total_up_to_date: Annotated[int | None, IOAttrs('tunmd')] = None

Common state data for a workspace fetch.

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

Can I get some of that workspace action?

WorkspaceFetchMessage( workspaceid: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object>], state: typing.Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object>])
workspaceid: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x103eb8c50>]
state: typing.Annotated[WorkspaceFetchState, <efro.dataclassio._base.IOAttrs object at 0x102a2e190>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
167    @override
168    @classmethod
169    def get_response_types(cls) -> list[type[Response] | None]:
170        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):
173@ioprepped
174@dataclass
175class WorkspaceFetchResponse(Response):
176    """Here's that workspace you asked for, boss."""
177
178    state: Annotated[WorkspaceFetchState, IOAttrs('s')]
179    deletes: Annotated[list[str], IOAttrs('dlt', store_default=False)] = field(
180        default_factory=list
181    )
182    downloads_inline: Annotated[
183        dict[str, bytes], IOAttrs('dinl', store_default=False)
184    ] = field(default_factory=dict)
185
186    done: Annotated[bool, IOAttrs('d')] = False

Here's that workspace you asked for, boss.

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

Can we show merch link?

@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
194    @override
195    @classmethod
196    def get_response_types(cls) -> list[type[Response] | None]:
197        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):
200@ioprepped
201@dataclass
202class MerchAvailabilityResponse(Response):
203    """About that merch..."""
204
205    url: Annotated[str | None, IOAttrs('u')]

About that merch...

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

Can I sign in please?

SignInMessage( login_type: typing.Annotated[bacommon.login.LoginType, <efro.dataclassio._base.IOAttrs object>], sign_in_token: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object>], description: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object>], apptime: typing.Annotated[float, <efro.dataclassio._base.IOAttrs object>])
login_type: typing.Annotated[bacommon.login.LoginType, <efro.dataclassio._base.IOAttrs object at 0x103f63e90>]
sign_in_token: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x103f10bd0>]
description: typing.Annotated[str, <efro.dataclassio._base.IOAttrs object at 0x103fa5d50>]
apptime: typing.Annotated[float, <efro.dataclassio._base.IOAttrs object at 0x1025f7890>]
@override
@classmethod
def get_response_types(cls) -> list[type[efro.message._message.Response] | None]:
220    @override
221    @classmethod
222    def get_response_types(cls) -> list[type[Response] | None]:
223        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):
226@ioprepped
227@dataclass
228class SignInResponse(Response):
229    """Here's that sign-in result you asked for, boss."""
230
231    credentials: Annotated[str | None, IOAttrs('c')]

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

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

Message asking for a manage-account url.

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

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

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