title: How to check that concrete method is respecting type-hinting for an abstract method
body: <p>This is a two-part question, but the second part is dependent on the first part.</p>
  
  <p>For educational purposes, I am trying to implement an abstract base class and test suite for <a href="https://en.wikipedia.org/wiki/Group_(mathematics)" rel="nofollow noreferrer">groups</a> (the concept from abstract algebra). Part of the definition of an algebraic group is equivalent to a type constraint, and I want to implement that type constraint on an ABC, and have something complain if the methods on the concrete classes don't conform to that constraint.</p>
  
  <p>I've got a first-pass implementation for this for the group of Boolean values under logical <code>and</code>, but there are at least two things wrong with it, and I'm hoping you can help me fix it.</p>
  
  <pre class="lang-py prettyprint-override"><code>from __future__ import annotations
  from abc import ABC, abstractmethod
  
  
  class AbsGroup(ABC):
      @abstractmethod
      def op(self, other: AbsGroup) -&gt; AbsGroup:   # &lt;-- Line-of-interest #1
          pass
  
  
  class Bool(AbsGroup):
  
      def __init__(self, val="False"):
  
          if val not in ["True", "False"]:
              raise ValueError("Invalid Bool value %s" % val)
  
          self.val = val
  
      def op(self, other):
          """Logical AND"""
          if self.val == "True" and other.val == "True":  # &lt;-- Line-of-interest #2
              return Bool("True")
          return Bool("False")
  
      def __eq__(self, other):
          return self.val == other.val
  
      def __repr__(self):
          return self.val
  </code></pre>
  
  <p>Firstly: Line-of-interest #1 is what's doing the type-constraint work, but the current implementation is wrong. It only checks that the method receives and returns an <code>AbsGroup</code> instance. This could be any <code>AbsGroup</code> instance. I want it to check that for the concrete class it gets inherited by, it receives and returns an instance of that concrete class (so in the case of <code>Bool</code> it receives and returns an instance of <code>Bool</code>). The point of the exercise is to do this in one location, rather than having to set it specifically on each concrete class. I presume this is done with some type-hinting generics that are a little bit deeper than I've yet to delve with regard to type-hinting. How do I do this?</p>
  
  <p>Secondly: how do I <em>check</em> the concrete method is complying with the abstract type hint? The type inspector in my IDE (PyCharm) complains at Line-of-interest #2, because it's expecting <code>other</code> to be of type <code>AbsGroup</code>, which doesn't have a <code>val</code> attribute. This is expected, and would go away if I could figure out the solution to the first problem, but my IDE is the <em>only</em> thing I can find that notices this discrepancy. <code>mypy</code> is silent on the matter by default, as are flake8 and pylint. It's great that PyCharm is on the ball, but if I wanted to incorporate this into a workflow, what command would I have to run that would fail in the event of my concrete method not complying with the abstract signature?</p>