Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Expose base class variables via properties #1984

Open
christophertubbs opened this issue Mar 9, 2023 · 0 comments
Open

Comments

@christophertubbs
Copy link

I was chasing down two issues yesterday due to member name clashes. Turns out I was overriding AsyncConsumer.channel_name and RedisChannelLayer.connection (something I will add in another ticket in channels_redis if this ticket is deemed appropriate). AsyncConsumer.channel_name's purpose isn't particularly clear since it acts like more of a unique ID used for registration than a singular name, but I would have avoided the issue if I followed the tutorial more closely. The RedisChannelLayer.connection override, though, exposes the problem more directly. There are a number of member variables that need to be left alone for any of the functionality to work such as InMemoryChannelLayer.groups and InMemoryChannelLayer.channels, both of which might be really easy to overwrite without diving into the source and understanding how everything works under the covers.

I suggest using the following pattern across most of the classes meant to be used as base classes:

class InMemoryChannelLayer(BaseChannelLayer):
    """
    In-memory channel layer implementation
    """

    def __init__(
        self,
        expiry=60,
        group_expiry=86400,
        capacity=100,
        channel_capacity=None,
        **kwargs
    ):
        super().__init__(
            expiry=expiry,
            capacity=capacity,
            channel_capacity=channel_capacity,
            **kwargs
        )
        self.__channels = {}
        self.__groups = {}
        self.__group_expiry = group_expiry

    @property
    def channels(self):
        return self.__channels

    @property
    def groups(self):
        return self.__groups

    @property
    def group_expiry(self):
        return self.__group_expiry

I used InMemoryChannelLayer since it was the most direct example of the use of these variables since the others ended up defining member variables within functions, such as AsyncConsumer.channel_name (which is a more appropriate example) being defined within AsyncConsumer.__call__ (also not ideal).

This pattern should help others avoid the problems I ran into in the future and help maintain the functionality of this library. The following, for example, should fail:

class TVChannelsLayer(AsyncConsumer):
     def __init__(self, tv_channels, **kwargs):
         super().__init__(**kwargs)
         self.channels = tv_channels

That redefinition should result in the following error:

AttributeError: can't set attribute 'channels'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant