Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ably/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
70 changes: 3 additions & 67 deletions ably/realtime/realtime_channel.py → ably/realtime/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand Down
2 changes: 1 addition & 1 deletion ably/realtime/realtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
70 changes: 70 additions & 0 deletions ably/types/channeloptions.py
Original file line number Diff line number Diff line change
@@ -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'),
)
3 changes: 2 additions & 1 deletion test/ably/realtime/realtimechannel_publish_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion test/ably/realtime/realtimechannel_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/ably/realtime/realtimechannel_vcdiff_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/ably/realtime/realtimeresume_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading