Struggling to understand Callable type hinting

Ian Pilcher arequipeno at gmail.com
Fri Jan 17 18:33:23 EST 2025


I am making my first attempt to use type hinting in a new project, and
I'm quickly hitting areas that I'm having trouble understanding.  One of
them is how to write type hints for a method decorator.

Here is an example that illustrates my confusion.  (Sorry for the
length.)


import collections.abc

class BufferScanner(object):

     def __init__(self, buf: str) -> None:
         self._buffer = buf
         self._index = 0
         self._eof = False
         self._line = 1
         self._column = 1

     @property
     def eof(self) -> bool:
         return self._eof

     @staticmethod
     def _check_eof(method: collections.abc.Callable -> (
         collections.abc.Callable
     ):
         def wrapper(*args, **kwargs):
             self = args[0]
             if not self._eof:
                 method(*args, **kwargs)
                 if self._index >= len(self._buffer):
                     self._eof = True
             return self._eof
         return wrapper

     @_check_eof
     def next_line(self) -> None:
         """Advance the scanner to the beginning of the next line."""
         try:
             i = self._buffer.index('\n', self._index)
         except ValueError:
             self._index = len(self._buffer)  # decorator will set _eof
             return
         self._index = i + 1  # move past the newline
         self._line += 1
         self._column = 1


I cannot figure out how to correctly specify the Callable argument and
return type for _check_eof().  As indicated by the name, method should
be a method (of the BufferScanner class), so its first positional
argument should always be an instance of BufferScanner, but it could
have any combination of positional and/or keyword arguments after that.

I've read the TypeVar and ParamSpec documentation, and me head is
spinning, but neither one really seems to help with this situation.

Any pointers to good resources or the correct way to do this are
appreciated.

Thanks!

-- 
========================================================================
If your user interface is intuitive in retrospect ... it isn't intuitive
========================================================================



More information about the Python-list mailing list