Repository: ably/ably-python (python)

Issue:
`RSN4b`: Error raised
Spec point `RSN4b`:

```
Calling release() with a channel name that does not correspond to an extant channel entity must return without error
```

At the moment, calling release on a non-existent channel results in an error being raised due to it not appearing in the channel map.

Pull request:
RSN4b Compliance
This change does the following:

- Removes the `__delitem__` magic method from the REST `Channels` implementation (as not part of spec)
- Fixes a non-compliance with `RSN4b` - whereby previously calling release on a non-existent channel would result in a KeyError being raised.

Fixes #472 

Patch:
diff --git a/ably/rest/channel.py b/ably/rest/channel.py
index 5ea8efd..45f6cef 100644
--- a/ably/rest/channel.py
+++ b/ably/rest/channel.py
@@ -219,8 +219,19 @@ class Channels:
     def __iter__(self) -> Iterator[str]:
         return iter(self.__all.values())
 
-    def release(self, key):
-        del self.__all[key]
+    # RSN4
+    def release(self, name):
+        """Releases a Channel object, deleting it, and enabling it to be garbage collected.
+        If the channel does not exist, nothing happens.
 
-    def __delitem__(self, key):
-        return self.release(key)
+        It also removes any listeners associated with the channel.
+
+        Parameters
+        ----------
+        name: str
+            Channel name
+        """
+
+        if name not in self.__all:
+            return
+        del self.__all[name]


Test patch:
diff --git a/test/ably/rest/restchannels_test.py b/test/ably/rest/restchannels_test.py
index c6a791f..b567781 100644
--- a/test/ably/rest/restchannels_test.py
+++ b/test/ably/rest/restchannels_test.py
@@ -70,19 +70,11 @@ class TestChannels(BaseAsyncTestCase):
             assert isinstance(channel, Channel)
             assert name == channel.name
 
+    # RSN4a, RSN4b
     def test_channels_release(self):
         self.ably.channels.get('new_channel')
         self.ably.channels.release('new_channel')
-
-        with pytest.raises(KeyError):
-            self.ably.channels.release('new_channel')
-
-    def test_channels_del(self):
-        self.ably.channels.get('new_channel')
-        del self.ably.channels['new_channel']
-
-        with pytest.raises(KeyError):
-            del self.ably.channels['new_channel']
+        self.ably.channels.release('new_channel')
 
     def test_channel_has_presence(self):
         channel = self.ably.channels.get('new_channnel')