OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

All bases of a protocol must be protocols- is typing.MutableMapping not a Protocol?

  • Thread starter Thread starter ThomasNicholas
  • Start date Start date
T

ThomasNicholas

Guest
I want to define a typing protocol for a custom mapping class. This class needs to be very similar to a MutableMapping, except that it has a couple of additional methods beyond those those that collections.abc.MutableMapping defines as abstract methods (specifically .copy()), and I also want to specify in advance which types any implementations of the custom mapping class must use as keys and values.

After reading through PEP 544 I thought I should be able to do this:

Code:
from typing import Hashable, MutableMapping, Protocol, TypeVar


TVarMapProt = TypeVar("TVarMapProt", bound="VariableMappingProtocol")


class VariableMappingProtocol(MutableMapping[Hashable, int], Protocol):
    """
    Protocol for the type behaviour of a class which
    acts basically like a dict of int objects.
    """

    def copy(self: TVarMapProt) -> TVarMapProt:
         # TODO replace return type with Self if PEP 673 goes through
        ...

The idea being that in my code I can state that a type VariableMappingProtocol is expected, and then the user would have to use their own class that was defined like this in order to avoid a typing error:

Code:
TCusVarMap = TypeVar("CusVarMap", bound="CustomVariableMapping")


class CustomVariableMapping:
    """Defines all the methods that a MutableMapping does, but mapping Hashables to ints"""

    def __getitem__(self, key: Hashable) -> int:
        # implementation goes here
        ...

    # etc. for __setitem__, and so on...

    def copy(self) -> TCusVarMap:
        # implementation goes here
        ...

The problem is that when I run mypy on the code defining VariableMappingProtocol I get this error:

Code:
test.py:7: error: All bases of a protocol must be protocols
Found 1 error in 1 file (checked 1 source file)

If I delete MutableMapping so that VariableMappingProtocol only inherits from Protocol then the error goes away. But then I'm not getting the structural typing I want for all the abstract methods from MutableMapping.

So it seems the problem is that typing.MutableMapping is not considered a Protocol? But that's weird, especially as I can treat some of the other types in typing as Protocols, e.g. this example (from PEP 544)

Code:
from typing import Protocol, Sized


class SizedProtocol(Sized, Protocol):
    """
    Protocol for the type behaviour of a class which has a __len__ method.
    """
    ...

which doesn't throw any mypy errors.

How can I inherit from MutableMapping as a Protocol, and thus avoid the need to write out all the methods of MutableMapping in my VariableMappingProtocol definition?
<p>I want to define a typing protocol for a custom mapping class. This class needs to be very similar to a <code>MutableMapping</code>, except that it has a couple of additional methods beyond those those that <code>collections.abc.MutableMapping</code> defines as abstract methods (specifically <code>.copy()</code>), and I also want to specify in advance which types any implementations of the custom mapping class must use as keys and values.</p>
<p>After reading through <a href="https://www.python.org/dev/peps/pep-0544/" rel="nofollow noreferrer">PEP 544</a> I thought I should be able to do this:</p>
<pre class="lang-py prettyprint-override"><code>from typing import Hashable, MutableMapping, Protocol, TypeVar


TVarMapProt = TypeVar("TVarMapProt", bound="VariableMappingProtocol")


class VariableMappingProtocol(MutableMapping[Hashable, int], Protocol):
"""
Protocol for the type behaviour of a class which
acts basically like a dict of int objects.
"""

def copy(self: TVarMapProt) -> TVarMapProt:
# TODO replace return type with Self if PEP 673 goes through
...
</code></pre>
<p>The idea being that in my code I can state that a type <code>VariableMappingProtocol</code> is expected, and then the user would have to use their own class that was defined like this in order to avoid a typing error:</p>
<pre class="lang-py prettyprint-override"><code>TCusVarMap = TypeVar("CusVarMap", bound="CustomVariableMapping")


class CustomVariableMapping:
"""Defines all the methods that a MutableMapping does, but mapping Hashables to ints"""

def __getitem__(self, key: Hashable) -> int:
# implementation goes here
...

# etc. for __setitem__, and so on...

def copy(self) -> TCusVarMap:
# implementation goes here
...
</code></pre>
<p>The problem is that when I run <code>mypy</code> on the code defining <code>VariableMappingProtocol</code> I get this error:</p>
<pre><code>test.py:7: error: All bases of a protocol must be protocols
Found 1 error in 1 file (checked 1 source file)
</code></pre>
<p>If I delete <code>MutableMapping</code> so that <code>VariableMappingProtocol</code> only inherits from <code>Protocol</code> then the error goes away. But then I'm not getting the structural typing I want for all the abstract methods from <code>MutableMapping</code>.</p>
<p>So it seems the problem is that <code>typing.MutableMapping</code> is not considered a <code>Protocol</code>? But that's weird, especially as I can treat some of the other types in <code>typing</code> as <code>Protocols</code>, e.g. <a href="https://www.python.org/dev/peps/pep-0544/#id27" rel="nofollow noreferrer">this example (from PEP 544)</a></p>
<pre class="lang-py prettyprint-override"><code>from typing import Protocol, Sized


class SizedProtocol(Sized, Protocol):
"""
Protocol for the type behaviour of a class which has a __len__ method.
"""
...
</code></pre>
<p>which doesn't throw any <code>mypy</code> errors.</p>
<p>How can I inherit from <code>MutableMapping</code> as a <code>Protocol</code>, and thus avoid the need to write out all the methods of <code>MutableMapping</code> in my <code>VariableMappingProtocol</code> definition?</p>
 

Latest posts

A
Replies
0
Views
1
Ashrik Ahamed
A
A
Replies
0
Views
1
Ashrik Ahamed
A

Online statistics

Members online
0
Guests online
4
Total visitors
4
Top