pythonpython-typingpytype

Break import cycle while type checking


I have split a large class implementation into different packages [1], and have used an import inside a method body to avoid a compilation cycle, as follows:

# model.py

class MyInt:
  def __init__(self, value: int):
    self.value = value
  
  def is_prime(self) -> bool:
    from methods import is_prime
    return is_prime(self)
# methods.py

from model import MyInt

def is_prime(x: MyInt) -> bool:
  # TODO: actually implement this
  return x.value == 2 or x.value % 2 == 1

However, pytype is not happy about this, failing to find the pyi file when reaching the import cycle:

File "/home/bkim/Projects/mwe/model.py", line 6, in is_prime: Couldn't import pyi for 'methods' [pyi-error]

Can't find pyi for 'model', referenced from 'methods'

How can I avoid this and still get type-checking?

[1] I've done this with just one tiny, utility method, actually. No need to yell about splitting a class across multiple packages.


Solution

  • This solution uses typing.TYPE_CHECKING, to have one behavior during type checking and another during runtime:

    import typing
    
    class MyInt:
      def is_prime(self) -> bool:
        if typing.TYPE_CHECKING:
          return False  
        from methods import is_prime
        return is_prime(self)
    

    Curiously, using from typing import TYPE_CHECKING doesn't work, which may be a bug?