11import asyncio
2+ import warnings
23from abc import ABC
34from types import TracebackType
45from typing import Any , AsyncContextManager , Generator , Optional , Type , Union
910from pamqp .common import Arguments
1011
1112from .abc import (
12- AbstractChannel , AbstractExchange , AbstractQueue , TimeoutType ,
13- UnderlayChannel ,
13+ AbstractChannel , AbstractConnection , AbstractExchange , AbstractQueue ,
14+ TimeoutType , UnderlayChannel ,
1415)
16+ from .exceptions import ChannelInvalidStateError
1517from .exchange import Exchange , ExchangeType
1618from .log import get_logger
1719from .message import IncomingMessage
@@ -52,7 +54,7 @@ class Channel(ChannelContext):
5254
5355 def __init__ (
5456 self ,
55- connection : aiormq . abc . AbstractConnection ,
57+ connection : AbstractConnection ,
5658 channel_number : Optional [int ] = None ,
5759 publisher_confirms : bool = True ,
5860 on_return_raises : bool = False ,
@@ -73,12 +75,12 @@ def __init__(
7375 'without "publisher_confirms"' ,
7476 )
7577
76- self ._connection : aiormq . abc . AbstractConnection = connection
78+ self ._connection : AbstractConnection = connection
7779
7880 # That's means user closed channel instance explicitly
7981 self ._closed : bool = False
8082
81- self ._channel = None
83+ self ._channel : Optional [ UnderlayChannel ] = None
8284 self ._channel_number = channel_number
8385
8486 self .close_callbacks = CallbackCollection (self )
@@ -99,9 +101,10 @@ def is_closed(self) -> bool:
99101 side or after the close() method has been called."""
100102 if not self .is_initialized or self ._closed :
101103 return True
102- if not self ._channel :
104+ channel = self ._channel
105+ if channel is None :
103106 return True
104- return self . _channel .channel .is_closed
107+ return channel .channel .is_closed
105108
106109 async def close (
107110 self ,
@@ -119,45 +122,58 @@ async def close(
119122 self ._closed = True
120123 await self ._channel .close ()
121124
122- @property
123- def channel (self ) -> aiormq .abc .AbstractChannel :
125+ async def get_underlay_channel (self ) -> aiormq .abc .AbstractChannel :
124126
125127 if not self .is_initialized or not self ._channel :
126128 raise aiormq .exceptions .ChannelInvalidStateError (
127129 "Channel was not opened" ,
128130 )
129131
130- if self .is_closed :
131- raise aiormq .exceptions .ChannelInvalidStateError (
132- "Channel has been closed" ,
133- )
132+ return self ._channel .channel
134133
134+ @property
135+ def channel (self ) -> aiormq .abc .AbstractChannel :
136+ warnings .warn (
137+ "This property is deprecated, do not use this anymore." ,
138+ DeprecationWarning ,
139+ )
140+ if self ._channel is None :
141+ raise aiormq .exceptions .ChannelInvalidStateError
135142 return self ._channel .channel
136143
137144 @property
138145 def number (self ) -> Optional [int ]:
139- return (
140- self .channel . number
141- if self . is_initialized
142- else self ._channel_number
143- )
146+ if self . _channel is None :
147+ return self ._channel_number
148+
149+ underlay_channel : UnderlayChannel = self ._channel
150+ return underlay_channel . channel . number
144151
145152 def __str__ (self ) -> str :
146153 return "{}" .format (self .number or "Not initialized channel" )
147154
148155 async def _open (self ) -> None :
149156 await self ._connection .ready ()
150157
158+ transport = self ._connection .transport
159+ if transport is None :
160+ raise ChannelInvalidStateError ("No active transport in channel" )
161+
151162 channel = await UnderlayChannel .create (
152- self . _connection ,
163+ transport . connection ,
153164 self ._on_close ,
154165 publisher_confirms = self .publisher_confirms ,
155166 on_return_raises = self .on_return_raises ,
156167 channel_number = self ._channel_number ,
157168 )
158169
159- await self ._on_open (channel .channel )
160170 self ._channel = channel
171+ try :
172+ await self ._on_open ()
173+ except BaseException as e :
174+ await channel .close (e )
175+ self ._channel = None
176+ raise
161177 self ._closed = False
162178
163179 async def initialize (self , timeout : TimeoutType = None ) -> None :
@@ -169,9 +185,9 @@ async def initialize(self, timeout: TimeoutType = None) -> None:
169185 await self ._open ()
170186 await self ._on_initialized ()
171187
172- async def _on_open (self , channel : aiormq . abc . AbstractChannel ) -> None :
188+ async def _on_open (self ) -> None :
173189 self .default_exchange : Exchange = self .EXCHANGE_CLASS (
174- channel = channel ,
190+ channel = self ,
175191 arguments = None ,
176192 auto_delete = False ,
177193 durable = False ,
@@ -192,7 +208,8 @@ async def _on_close(self, closing: asyncio.Future) -> None:
192208 self ._channel .channel .on_return_callbacks .discard (self ._on_return )
193209
194210 async def _on_initialized (self ) -> None :
195- self .channel .on_return_callbacks .add (self ._on_return )
211+ channel = await self .get_underlay_channel ()
212+ channel .on_return_callbacks .add (self ._on_return )
196213
197214 def _on_return (self , message : aiormq .abc .DeliveredMessage ) -> None :
198215 self .return_callbacks (IncomingMessage (message , no_ack = True ))
@@ -241,7 +258,7 @@ async def declare_exchange(
241258 durable = False
242259
243260 exchange = self .EXCHANGE_CLASS (
244- channel = self . channel ,
261+ channel = self ,
245262 name = name ,
246263 type = type ,
247264 durable = durable ,
@@ -281,7 +298,7 @@ async def get_exchange(
281298 return await self .declare_exchange (name = name , passive = True )
282299 else :
283300 return self .EXCHANGE_CLASS (
284- channel = self . channel ,
301+ channel = self ,
285302 name = name ,
286303 durable = False ,
287304 auto_delete = False ,
@@ -321,7 +338,7 @@ async def declare_queue(
321338 """
322339
323340 queue : AbstractQueue = self .QUEUE_CLASS (
324- channel = self . channel ,
341+ channel = self ,
325342 name = name ,
326343 durable = durable ,
327344 exclusive = exclusive ,
@@ -358,7 +375,7 @@ async def get_queue(
358375 return await self .declare_queue (name = name , passive = True )
359376 else :
360377 return self .QUEUE_CLASS (
361- channel = self . channel ,
378+ channel = self ,
362379 name = name ,
363380 durable = False ,
364381 exclusive = False ,
@@ -379,7 +396,9 @@ async def set_qos(
379396 warn ('Use "global_" instead of "all_channels"' , DeprecationWarning )
380397 global_ = all_channels
381398
382- return await self .channel .basic_qos (
399+ channel = await self .get_underlay_channel ()
400+
401+ return await channel .basic_qos (
383402 prefetch_count = prefetch_count ,
384403 prefetch_size = prefetch_size ,
385404 global_ = global_ ,
@@ -394,7 +413,8 @@ async def queue_delete(
394413 if_empty : bool = False ,
395414 nowait : bool = False ,
396415 ) -> aiormq .spec .Queue .DeleteOk :
397- return await self .channel .queue_delete (
416+ channel = await self .get_underlay_channel ()
417+ return await channel .queue_delete (
398418 queue = queue_name ,
399419 if_unused = if_unused ,
400420 if_empty = if_empty ,
@@ -409,7 +429,8 @@ async def exchange_delete(
409429 if_unused : bool = False ,
410430 nowait : bool = False ,
411431 ) -> aiormq .spec .Exchange .DeleteOk :
412- return await self .channel .exchange_delete (
432+ channel = await self .get_underlay_channel ()
433+ return await channel .exchange_delete (
413434 exchange = exchange_name ,
414435 if_unused = if_unused ,
415436 nowait = nowait ,
@@ -426,7 +447,8 @@ def transaction(self) -> Transaction:
426447 return Transaction (self )
427448
428449 async def flow (self , active : bool = True ) -> aiormq .spec .Channel .FlowOk :
429- return await self .channel .flow (active = active )
450+ channel = await self .get_underlay_channel ()
451+ return await channel .flow (active = active )
430452
431453
432454__all__ = ("Channel" ,)
0 commit comments