Clean state types

This commit is contained in:
Teknique 2023-06-17 00:27:51 -07:00
parent cf2c26e99b
commit 00521a1283
No known key found for this signature in database
GPG Key ID: 54D9906A294B7FF3

View File

@ -1,36 +1,47 @@
from typing import Self, Optional
from enum import StrEnum from enum import StrEnum
from typing import Optional, Self
from .config import VeilidConfig
from .types import (ByteCount, RouteId, Timestamp, TimestampDuration, TypedKey,
ValueData, ValueSubkey, VeilidLogLevel,
urlsafe_b64decode_no_pad)
from .types import *
from .config import *
class AttachmentState(StrEnum): class AttachmentState(StrEnum):
DETACHED = 'Detached' DETACHED = "Detached"
ATTACHING = 'Attaching' ATTACHING = "Attaching"
ATTACHED_WEAK = 'AttachedWeak' ATTACHED_WEAK = "AttachedWeak"
ATTACHED_GOOD = 'AttachedGood' ATTACHED_GOOD = "AttachedGood"
ATTACHED_STRONG = 'AttachedStrong' ATTACHED_STRONG = "AttachedStrong"
FULLY_ATTACHED = 'FullyAttached' FULLY_ATTACHED = "FullyAttached"
OVER_ATTACHED = 'OverAttached' OVER_ATTACHED = "OverAttached"
DETACHING = 'Detaching' DETACHING = "Detaching"
class VeilidStateAttachment: class VeilidStateAttachment:
state: AttachmentState state: AttachmentState
public_internet_ready: bool public_internet_ready: bool
local_network_ready: bool local_network_ready: bool
def __init__(self, state: AttachmentState, public_internet_ready: bool, local_network_ready: bool): def __init__(
self,
state: AttachmentState,
public_internet_ready: bool,
local_network_ready: bool,
):
self.state = state self.state = state
self.public_internet_ready = public_internet_ready self.public_internet_ready = public_internet_ready
self.local_network_ready = local_network_ready self.local_network_ready = local_network_ready
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidStateAttachment( return cls(
AttachmentState(j['state']), AttachmentState(j["state"]),
j['public_internet_ready'], j["public_internet_ready"],
j['local_network_ready']) j["local_network_ready"],
)
class RPCStats: class RPCStats:
messages_sent: int messages_sent: int
@ -42,9 +53,17 @@ class RPCStats:
recent_lost_answers: int recent_lost_answers: int
failed_to_send: int failed_to_send: int
def __init__(self, messages_sent: int, messages_rcvd: int, questions_in_flight: int, def __init__(
last_question_ts: Optional[Timestamp], last_seen_ts: Optional[Timestamp], self,
first_consecutive_seen_ts: Optional[Timestamp], recent_lost_answers: int, failed_to_send: int): messages_sent: int,
messages_rcvd: int,
questions_in_flight: int,
last_question_ts: Optional[Timestamp],
last_seen_ts: Optional[Timestamp],
first_consecutive_seen_ts: Optional[Timestamp],
recent_lost_answers: int,
failed_to_send: int,
):
self.messages_sent = messages_sent self.messages_sent = messages_sent
self.messages_rcvd = messages_rcvd self.messages_rcvd = messages_rcvd
self.questions_in_flight = questions_in_flight self.questions_in_flight = questions_in_flight
@ -54,36 +73,46 @@ class RPCStats:
self.recent_lost_answers = recent_lost_answers self.recent_lost_answers = recent_lost_answers
self.failed_to_send = failed_to_send self.failed_to_send = failed_to_send
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return RPCStats( return cls(
j['messages_sent'], j["messages_sent"],
j['messages_rcvd'], j["messages_rcvd"],
j['questions_in_flight'], j["questions_in_flight"],
None if j['last_question_ts'] is None else Timestamp(j['last_question_ts']), None if j["last_question_ts"] is None else Timestamp(j["last_question_ts"]),
None if j['last_seen_ts'] is None else Timestamp(j['last_seen_ts']), None if j["last_seen_ts"] is None else Timestamp(j["last_seen_ts"]),
None if j['first_consecutive_seen_ts'] is None else Timestamp(j['first_consecutive_seen_ts']), None
j['recent_lost_answers'], if j["first_consecutive_seen_ts"] is None
j['failed_to_send']) else Timestamp(j["first_consecutive_seen_ts"]),
j["recent_lost_answers"],
j["failed_to_send"],
)
class LatencyStats: class LatencyStats:
fastest: TimestampDuration fastest: TimestampDuration
average: TimestampDuration average: TimestampDuration
slowest: TimestampDuration slowest: TimestampDuration
def __init__(self, fastest: TimestampDuration, average: TimestampDuration, slowest: TimestampDuration): def __init__(
self,
fastest: TimestampDuration,
average: TimestampDuration,
slowest: TimestampDuration,
):
self.fastest = fastest self.fastest = fastest
self.average = average self.average = average
self.slowest = slowest self.slowest = slowest
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return LatencyStats( return cls(
TimestampDuration(j['fastest']), TimestampDuration(j["fastest"]),
TimestampDuration(j['average']), TimestampDuration(j["average"]),
TimestampDuration(j['slowest'])) TimestampDuration(j["slowest"]),
)
class TransferStats: class TransferStats:
@ -92,20 +121,27 @@ class TransferStats:
average: ByteCount average: ByteCount
minimum: ByteCount minimum: ByteCount
def __init__(self, total: ByteCount, maximum: ByteCount, average: ByteCount, minimum: ByteCount): def __init__(
self,
total: ByteCount,
maximum: ByteCount,
average: ByteCount,
minimum: ByteCount,
):
self.total = total self.total = total
self.maximum = maximum self.maximum = maximum
self.average = average self.average = average
self.minimum = minimum self.minimum = minimum
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return TransferStats( return cls(
ByteCount(j['total']), ByteCount(j["total"]),
ByteCount(j['maximum']), ByteCount(j["maximum"]),
ByteCount(j['average']), ByteCount(j["average"]),
ByteCount(j['minimum'])) ByteCount(j["minimum"]),
)
class TransferStatsDownUp: class TransferStatsDownUp:
@ -116,12 +152,11 @@ class TransferStatsDownUp:
self.down = down self.down = down
self.up = up self.up = up
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return TransferStatsDownUp( return cls(TransferStats.from_json(j["down"]), TransferStats.from_json(j["up"]))
TransferStats.from_json(j['down']),
TransferStats.from_json(j['up']))
class PeerStats: class PeerStats:
time_added: Timestamp time_added: Timestamp
@ -129,20 +164,28 @@ class PeerStats:
latency: Optional[LatencyStats] latency: Optional[LatencyStats]
transfer: TransferStatsDownUp transfer: TransferStatsDownUp
def __init__(self, time_added: Timestamp, rpc_stats: RPCStats, latency: Optional[LatencyStats], transfer: TransferStatsDownUp): def __init__(
self,
time_added: Timestamp,
rpc_stats: RPCStats,
latency: Optional[LatencyStats],
transfer: TransferStatsDownUp,
):
self.time_added = time_added self.time_added = time_added
self.rpc_stats = rpc_stats self.rpc_stats = rpc_stats
self.latency = latency self.latency = latency
self.transfer = transfer self.transfer = transfer
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return PeerStats( return cls(
j['time_added'], j["time_added"],
RPCStats.from_json(j['rpc_stats']), RPCStats.from_json(j["rpc_stats"]),
None if j['latency'] is None else LatencyStats.from_json(j['latency']), None if j["latency"] is None else LatencyStats.from_json(j["latency"]),
TransferStatsDownUp.from_json(j['transfer'])) TransferStatsDownUp.from_json(j["transfer"]),
)
class PeerTableData: class PeerTableData:
node_ids: list[str] node_ids: list[str]
@ -154,13 +197,13 @@ class PeerTableData:
self.peer_address = peer_address self.peer_address = peer_address
self.peer_stats = peer_stats self.peer_stats = peer_stats
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return PeerTableData( return cls(
j['node_ids'], j["node_ids"], j["peer_address"], PeerStats.from_json(j["peer_stats"])
j['peer_address'], )
PeerStats.from_json(j['peer_stats']))
class VeilidStateNetwork: class VeilidStateNetwork:
started: bool started: bool
@ -168,20 +211,28 @@ class VeilidStateNetwork:
bps_up: ByteCount bps_up: ByteCount
peers: list[PeerTableData] peers: list[PeerTableData]
def __init__(self, started: bool, bps_down: ByteCount, bps_up: ByteCount, peers: list[PeerTableData]): def __init__(
self,
started: bool,
bps_down: ByteCount,
bps_up: ByteCount,
peers: list[PeerTableData],
):
self.started = started self.started = started
self.bps_down = bps_down self.bps_down = bps_down
self.bps_up = bps_up self.bps_up = bps_up
self.peers = peers self.peers = peers
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidStateNetwork( return cls(
j['started'], j["started"],
ByteCount(j['bps_down']), ByteCount(j["bps_down"]),
ByteCount(j['bps_up']), ByteCount(j["bps_up"]),
list(map(lambda x: PeerTableData.from_json(x), j['peers']))) [PeerTableData.from_json(peer) for peer in j["peers"]],
)
class VeilidStateConfig: class VeilidStateConfig:
config: VeilidConfig config: VeilidConfig
@ -189,48 +240,54 @@ class VeilidStateConfig:
def __init__(self, config: VeilidConfig): def __init__(self, config: VeilidConfig):
self.config = config self.config = config
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidStateConfig( return cls(VeilidConfig.from_json(j["config"]))
VeilidConfig.from_json(j['config'])
)
class VeilidState: class VeilidState:
attachment: VeilidStateAttachment attachment: VeilidStateAttachment
network: VeilidStateNetwork network: VeilidStateNetwork
config: VeilidStateConfig config: VeilidStateConfig
def __init__(self, attachment: VeilidStateAttachment, network: VeilidStateNetwork, config: VeilidStateConfig): def __init__(
self,
attachment: VeilidStateAttachment,
network: VeilidStateNetwork,
config: VeilidStateConfig,
):
self.attachment = attachment self.attachment = attachment
self.network = network self.network = network
self.config = config self.config = config
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidState( return cls(
VeilidStateAttachment.from_json(j['attachment']), VeilidStateAttachment.from_json(j["attachment"]),
VeilidStateNetwork.from_json(j['network']), VeilidStateNetwork.from_json(j["network"]),
VeilidStateConfig.from_json(j['config'])) VeilidStateConfig.from_json(j["config"]),
)
class VeilidLog: class VeilidLog:
log_level: VeilidLogLevel log_level: VeilidLogLevel
message: str message: str
backtrace: Optional[str] backtrace: Optional[str]
def __init__(self, log_level: VeilidLogLevel, message: str, backtrace: Optional[str]): def __init__(
self, log_level: VeilidLogLevel, message: str, backtrace: Optional[str]
):
self.log_level = log_level self.log_level = log_level
self.message = message self.message = message
self.backtrace = backtrace self.backtrace = backtrace
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidLog( return cls(VeilidLogLevel(j["log_level"]), j["message"], j["backtrace"])
VeilidLogLevel(j['log_level']),
j['message'],
j['backtrace'])
class VeilidAppMessage: class VeilidAppMessage:
sender: Optional[TypedKey] sender: Optional[TypedKey]
@ -240,12 +297,14 @@ class VeilidAppMessage:
self.sender = sender self.sender = sender
self.message = message self.message = message
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidAppMessage( return cls(
None if j['sender'] is None else TypedKey(j['sender']), None if j["sender"] is None else TypedKey(j["sender"]),
urlsafe_b64decode_no_pad(j['message'])) urlsafe_b64decode_no_pad(j["message"]),
)
class VeilidAppCall: class VeilidAppCall:
sender: Optional[TypedKey] sender: Optional[TypedKey]
@ -257,13 +316,15 @@ class VeilidAppCall:
self.message = message self.message = message
self.call_id = call_id self.call_id = call_id
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidAppCall( return cls(
None if j['sender'] is None else TypedKey(j['sender']), None if j["sender"] is None else TypedKey(j["sender"]),
urlsafe_b64decode_no_pad(j['message']), urlsafe_b64decode_no_pad(j["message"]),
j['call_id']) j["call_id"],
)
class VeilidRouteChange: class VeilidRouteChange:
dead_routes: list[RouteId] dead_routes: list[RouteId]
@ -273,12 +334,14 @@ class VeilidRouteChange:
self.dead_routes = dead_routes self.dead_routes = dead_routes
self.dead_remote_routes = dead_remote_routes self.dead_remote_routes = dead_remote_routes
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidRouteChange( return cls(
list(map(lambda x: RouteId(x), j['dead_routes'])), [RouteId(route) for route in j["dead_routes"]],
list(map(lambda x: RouteId(x), j['dead_remote_routes']))) [RouteId(route) for route in j["dead_remote_routes"]],
)
class VeilidValueChange: class VeilidValueChange:
key: TypedKey key: TypedKey
@ -286,20 +349,23 @@ class VeilidValueChange:
count: int count: int
value: ValueData value: ValueData
def __init__(self, key: TypedKey, subkeys: list[ValueSubkey], count: int, value: ValueData): def __init__(
self, key: TypedKey, subkeys: list[ValueSubkey], count: int, value: ValueData
):
self.key = key self.key = key
self.subkeys = subkeys self.subkeys = subkeys
self.count = count self.count = count
self.value = value self.value = value
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
return VeilidValueChange( return cls(
TypedKey(j['key']), TypedKey(j["key"]),
list(map(lambda x: ValueSubkey(x), j['subkeys'])), [ValueSubkey(key) for key in j["subkeys"]],
j['count'], j["count"],
ValueData.from_json(j['value'])) ValueData.from_json(j["value"]),
)
class VeilidUpdateKind(StrEnum): class VeilidUpdateKind(StrEnum):
@ -313,19 +379,36 @@ class VeilidUpdateKind(StrEnum):
VALUE_CHANGE = "ValueChange" VALUE_CHANGE = "ValueChange"
SHUTDOWN = "Shutdown" SHUTDOWN = "Shutdown"
VeilidUpdateDetailType = Optional[
VeilidLog
| VeilidAppMessage
| VeilidAppCall
| VeilidStateAttachment
| VeilidStateNetwork
| VeilidStateConfig
| VeilidRouteChange
| VeilidValueChange
]
class VeilidUpdate: class VeilidUpdate:
kind: VeilidUpdateKind kind: VeilidUpdateKind
detail: Optional[VeilidLog | VeilidAppMessage | VeilidAppCall | VeilidStateAttachment | VeilidStateNetwork | VeilidStateConfig | VeilidRouteChange | VeilidValueChange] detail: VeilidUpdateDetailType
def __init__(self, kind: VeilidUpdateKind, detail: Optional[VeilidLog | VeilidAppMessage | VeilidAppCall | VeilidStateAttachment | VeilidStateNetwork | VeilidStateConfig | VeilidRouteChange | VeilidValueChange]): def __init__(
self,
kind: VeilidUpdateKind,
detail: VeilidUpdateDetailType,
):
self.kind = kind self.kind = kind
self.detail = detail self.detail = detail
@staticmethod @classmethod
def from_json(j: dict) -> Self: def from_json(cls, j: dict) -> Self:
'''JSON object hook''' """JSON object hook"""
kind = VeilidUpdateKind(j['kind']) kind = VeilidUpdateKind(j["kind"])
detail = None detail: VeilidUpdateDetailType = None
match kind: match kind:
case VeilidUpdateKind.LOG: case VeilidUpdateKind.LOG:
detail = VeilidLog.from_json(j) detail = VeilidLog.from_json(j)
@ -347,4 +430,4 @@ class VeilidUpdate:
detail = None detail = None
case _: case _:
raise ValueError("Unknown VeilidUpdateKind") raise ValueError("Unknown VeilidUpdateKind")
return VeilidUpdate(kind, detail) return cls(kind, detail)