diff --git a/ably/__init__.py b/ably/__init__.py index ce1a6d0f..2280daa0 100644 --- a/ably/__init__.py +++ b/ably/__init__.py @@ -12,7 +12,7 @@ from ably.types.options import Options, VCDiffDecoder from ably.util.crypto import CipherParams from ably.util.exceptions import AblyAuthException, AblyException, IncompatibleClientIdException -from ably.vcdiff.default_vcdiff_decoder import AblyVCDiffDecoder +from ably.vcdiff.defaultvcdiffdecoder import AblyVCDiffDecoder logger = logging.getLogger(__name__) logger.addHandler(logging.NullHandler()) diff --git a/ably/realtime/realtime_channel.py b/ably/realtime/channel.py similarity index 94% rename from ably/realtime/realtime_channel.py rename to ably/realtime/channel.py index 792c6717..e0fd6251 100644 --- a/ably/realtime/realtime_channel.py +++ b/ably/realtime/channel.py @@ -2,12 +2,13 @@ import asyncio import logging -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING from ably.realtime.connection import ConnectionState from ably.rest.channel import Channel from ably.rest.channel import Channels as RestChannels from ably.transport.websockettransport import ProtocolMessageAction +from ably.types.channeloptions import ChannelOptions from ably.types.channelstate import ChannelState, ChannelStateChange from ably.types.flags import Flag, has_flag from ably.types.message import Message, MessageAction, MessageVersion @@ -20,75 +21,10 @@ if TYPE_CHECKING: from ably.realtime.realtime import AblyRealtime - from ably.util.crypto import CipherParams log = logging.getLogger(__name__) -class ChannelOptions: - """Channel options for Ably Realtime channels - - Attributes - ---------- - cipher : CipherParams, optional - Requests encryption for this channel when not null, and specifies encryption-related parameters. - params : Dict[str, str], optional - Channel parameters that configure the behavior of the channel. - """ - - def __init__(self, cipher: CipherParams | None = None, params: dict | None = None): - self.__cipher = cipher - self.__params = params - # Validate params - if self.__params and not isinstance(self.__params, dict): - raise AblyException("params must be a dictionary", 40000, 400) - - @property - def cipher(self): - """Get cipher configuration""" - return self.__cipher - - @property - def params(self) -> dict[str, str]: - """Get channel parameters""" - return self.__params - - def __eq__(self, other): - """Check equality with another ChannelOptions instance""" - if not isinstance(other, ChannelOptions): - return False - - return (self.__cipher == other.__cipher and - self.__params == other.__params) - - def __hash__(self): - """Make ChannelOptions hashable""" - return hash(( - self.__cipher, - tuple(sorted(self.__params.items())) if self.__params else None, - )) - - def to_dict(self) -> dict[str, Any]: - """Convert to dictionary representation""" - result = {} - if self.__cipher is not None: - result['cipher'] = self.__cipher - if self.__params: - result['params'] = self.__params - return result - - @classmethod - def from_dict(cls, options_dict: dict[str, Any]) -> ChannelOptions: - """Create ChannelOptions from dictionary""" - if not isinstance(options_dict, dict): - raise AblyException("options must be a dictionary", 40000, 400) - - return cls( - cipher=options_dict.get('cipher'), - params=options_dict.get('params'), - ) - - class RealtimeChannel(EventEmitter, Channel): """ Ably Realtime Channel @@ -139,7 +75,7 @@ def __init__(self, realtime: AblyRealtime, name: str, channel_options: ChannelOp self.__internal_state_emitter = EventEmitter() # Initialize presence for this channel - from ably.realtime.realtimepresence import RealtimePresence + from ably.realtime.presence import RealtimePresence self.__presence = RealtimePresence(self) # Pass channel options as dictionary to parent Channel class diff --git a/ably/realtime/realtimepresence.py b/ably/realtime/presence.py similarity index 99% rename from ably/realtime/realtimepresence.py rename to ably/realtime/presence.py index f3351114..79d73070 100644 --- a/ably/realtime/realtimepresence.py +++ b/ably/realtime/presence.py @@ -20,7 +20,7 @@ from ably.util.exceptions import AblyException if TYPE_CHECKING: - from ably.realtime.realtime_channel import RealtimeChannel + from ably.realtime.channel import RealtimeChannel log = logging.getLogger(__name__) diff --git a/ably/realtime/realtime.py b/ably/realtime/realtime.py index 9b9c4016..69e1e8e0 100644 --- a/ably/realtime/realtime.py +++ b/ably/realtime/realtime.py @@ -2,8 +2,8 @@ import logging from typing import Optional +from ably.realtime.channel import Channels from ably.realtime.connection import Connection, ConnectionState -from ably.realtime.realtime_channel import Channels from ably.rest.rest import AblyRest log = logging.getLogger(__name__) diff --git a/ably/types/channeloptions.py b/ably/types/channeloptions.py new file mode 100644 index 00000000..48e34dfe --- /dev/null +++ b/ably/types/channeloptions.py @@ -0,0 +1,70 @@ +from __future__ import annotations + +from typing import Any + +from ably.util.crypto import CipherParams +from ably.util.exceptions import AblyException + + +class ChannelOptions: + """Channel options for Ably Realtime channels + + Attributes + ---------- + cipher : CipherParams, optional + Requests encryption for this channel when not null, and specifies encryption-related parameters. + params : Dict[str, str], optional + Channel parameters that configure the behavior of the channel. + """ + + def __init__(self, cipher: CipherParams | None = None, params: dict | None = None): + self.__cipher = cipher + self.__params = params + # Validate params + if self.__params and not isinstance(self.__params, dict): + raise AblyException("params must be a dictionary", 40000, 400) + + @property + def cipher(self): + """Get cipher configuration""" + return self.__cipher + + @property + def params(self) -> dict[str, str]: + """Get channel parameters""" + return self.__params + + def __eq__(self, other): + """Check equality with another ChannelOptions instance""" + if not isinstance(other, ChannelOptions): + return False + + return (self.__cipher == other.__cipher and + self.__params == other.__params) + + def __hash__(self): + """Make ChannelOptions hashable""" + return hash(( + self.__cipher, + tuple(sorted(self.__params.items())) if self.__params else None, + )) + + def to_dict(self) -> dict[str, Any]: + """Convert to dictionary representation""" + result = {} + if self.__cipher is not None: + result['cipher'] = self.__cipher + if self.__params: + result['params'] = self.__params + return result + + @classmethod + def from_dict(cls, options_dict: dict[str, Any]) -> ChannelOptions: + """Create ChannelOptions from dictionary""" + if not isinstance(options_dict, dict): + raise AblyException("options must be a dictionary", 40000, 400) + + return cls( + cipher=options_dict.get('cipher'), + params=options_dict.get('params'), + ) diff --git a/ably/vcdiff/default_vcdiff_decoder.py b/ably/vcdiff/defaultvcdiffdecoder.py similarity index 100% rename from ably/vcdiff/default_vcdiff_decoder.py rename to ably/vcdiff/defaultvcdiffdecoder.py diff --git a/test/ably/realtime/realtimechannel_publish_test.py b/test/ably/realtime/realtimechannel_publish_test.py index 1f4a6981..9ecf10f9 100644 --- a/test/ably/realtime/realtimechannel_publish_test.py +++ b/test/ably/realtime/realtimechannel_publish_test.py @@ -2,9 +2,10 @@ import pytest +from ably.realtime.channel import ChannelState from ably.realtime.connection import ConnectionState -from ably.realtime.realtime_channel import ChannelOptions, ChannelState from ably.transport.websockettransport import ProtocolMessageAction +from ably.types.channeloptions import ChannelOptions from ably.types.message import Message from ably.util.crypto import CipherParams from ably.util.exceptions import AblyException, IncompatibleClientIdException diff --git a/test/ably/realtime/realtimechannel_test.py b/test/ably/realtime/realtimechannel_test.py index f12fbea1..6d2865f2 100644 --- a/test/ably/realtime/realtimechannel_test.py +++ b/test/ably/realtime/realtimechannel_test.py @@ -2,9 +2,10 @@ import pytest +from ably.realtime.channel import ChannelState, RealtimeChannel from ably.realtime.connection import ConnectionState -from ably.realtime.realtime_channel import ChannelOptions, ChannelState, RealtimeChannel from ably.transport.websockettransport import ProtocolMessageAction +from ably.types.channeloptions import ChannelOptions from ably.types.message import Message from ably.util.exceptions import AblyException from test.ably.testapp import TestApp diff --git a/test/ably/realtime/realtimechannel_vcdiff_test.py b/test/ably/realtime/realtimechannel_vcdiff_test.py index af778089..48a484a9 100644 --- a/test/ably/realtime/realtimechannel_vcdiff_test.py +++ b/test/ably/realtime/realtimechannel_vcdiff_test.py @@ -5,7 +5,7 @@ from ably import AblyVCDiffDecoder from ably.realtime.connection import ConnectionState -from ably.realtime.realtime_channel import ChannelOptions +from ably.types.channeloptions import ChannelOptions from ably.types.options import VCDiffDecoder from test.ably.testapp import TestApp from test.ably.utils import BaseAsyncTestCase, WaitableEvent diff --git a/test/ably/realtime/realtimeresume_test.py b/test/ably/realtime/realtimeresume_test.py index 8aae598f..bfe77efa 100644 --- a/test/ably/realtime/realtimeresume_test.py +++ b/test/ably/realtime/realtimeresume_test.py @@ -2,8 +2,8 @@ import pytest +from ably.realtime.channel import ChannelState from ably.realtime.connection import ConnectionState -from ably.realtime.realtime_channel import ChannelState from ably.transport.websockettransport import ProtocolMessageAction from test.ably.testapp import TestApp from test.ably.utils import BaseAsyncTestCase, random_string