Warning: mysqli::__construct(): (HY000/1203): User howardkn already has more than 'max_user_connections' active connections in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\includes\artfuncs.php on line 21
Failed to connect to MySQL: (1203) User howardkn already has more than 'max_user_connections' active connections
Warning: mysqli::query(): Couldn't fetch mysqli in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\index.php on line 66
Article <mailman.87.1737156810.2912.python-list@python.org>
Deutsch   English   Français   Italiano  
<mailman.87.1737156810.2912.python-list@python.org>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!weretis.net!feeder8.news.weretis.net!fu-berlin.de!uni-berlin.de!not-for-mail
From: Ian Pilcher <arequipeno@gmail.com>
Newsgroups: comp.lang.python
Subject: Struggling to understand Callable type hinting
Date: Fri, 17 Jan 2025 17:33:23 -0600
Lines: 68
Message-ID: <mailman.87.1737156810.2912.python-list@python.org>
References: <f01d0808-16fb-4b91-a518-a84d6973fee1@gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: news.uni-berlin.de AdiK60BM1JQG3ULZLVtEig/klA0daqCA9+YRPT34HzSQ==
Cancel-Lock: sha1:rpqDYF6X7kEjJ5n+qFl06MLE5Z8= sha256:CqRf2kMtg61ch3liSv9GghpOzhfVsa5Oz78anGkStVo=
Return-Path: <arequipeno@gmail.com>
X-Original-To: python-list@python.org
Delivered-To: python-list@mail.python.org
Authentication-Results: mail.python.org; dkim=pass
 reason="2048-bit key; unprotected key"
 header.d=gmail.com header.i=@gmail.com header.b=Qv/mgL+H;
 dkim-adsp=pass; dkim-atps=neutral
X-Spam-Status: OK 0.003
X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'project,': 0.03; 'skip:@
 10': 0.03; 'argument': 0.04; 'def': 0.04; 'hitting': 0.07;
 'valueerror:': 0.09; 'import': 0.15; 'that.': 0.15; 'args[0]':
 0.16; 'arguments': 0.16; 'confusion.': 0.16; 'hints': 0.16;
 'instance': 0.16; 'intuitive': 0.16; 'newline': 0.16; 'none:':
 0.16; 'pointers': 0.16; 'specify': 0.16; 'subject:hinting': 0.16;
 'wrapper': 0.16; 'message-id:@gmail.com': 0.18; 'figure': 0.19;
 'to:addr:python-list': 0.20; "i've": 0.22; 'skip:_ 10': 0.22;
 'thanks!': 0.24; 'to:name:python-list@python.org': 0.24; 'past':
 0.25; 'cannot': 0.25; 'seems': 0.26; 'interface': 0.26; "isn't":
 0.27; 'header:User-Agent:1': 0.30; 'attempt': 0.31; 'keyword':
 0.32; 'but': 0.32; "i'm": 0.33; 'received:google.com': 0.34;
 'appreciated.': 0.34; 'from:addr:gmail.com': 0.34; 'really': 0.36;
 '...': 0.37; 'could': 0.37; 'class': 0.37; 'example': 0.37; 'way':
 0.38; 'read': 0.38; 'use': 0.39; 'neither': 0.39; 'beginning':
 0.40; 'should': 0.40; 'method': 0.61; 'true': 0.63; 'here': 0.63;
 'skip:b 20': 0.63; 'skip:b 10': 0.63; 'your': 0.64; 'areas': 0.67;
 'head': 0.73; 'name,': 0.75; 'combination': 0.76; 'quickly': 0.80;
 'indicated': 0.81; 'skip:= 70': 0.84; 'subject:type': 0.93
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=gmail.com; s=20230601; t=1737156807; x=1737761607; darn=python.org;
 h=content-transfer-encoding:subject:from:to:content-language
 :user-agent:mime-version:date:message-id:from:to:cc:subject:date
 :message-id:reply-to;
 bh=6JrzLB8iXaxrhBE8phiLd6xsl7MfsPVVW/Baf1O62BA=;
 b=Qv/mgL+Hjijz5hgdXnOrQZN9Nucc2+7KUfbeKfXRefAFoJZ3RBYA5cObgy0vgbw3xd
 KWFUkzm2HbO0hxpEFKiIVZEenonXDs1xO8MyH6AmBSaAKD+Yt+rbiIM8qWFSCn9B8dIy
 Y5jWI8beCvSF0q5NTE5Hi4jeK4eozaLE6NZaxqwTXesqKCxvmErIRr1GuuZ7wGdEA+YI
 Gbz6Jb7qfhhFdD89065HYpbn7KM9iKRwySubKe4NZHYuDrcTRWKukSZ67BZqOX0tWmls
 Kr7wCzEGT4+EgNJq2i78QPgqg9jUf0rYSYZJVZjsKvBpf3RRhLqVnSF+v7LNicOqXKDH
 HR5Q==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1737156807; x=1737761607;
 h=content-transfer-encoding:subject:from:to:content-language
 :user-agent:mime-version:date:message-id:x-gm-message-state:from:to
 :cc:subject:date:message-id:reply-to;
 bh=6JrzLB8iXaxrhBE8phiLd6xsl7MfsPVVW/Baf1O62BA=;
 b=oVmxH4FrbGOJuWpD5uuKnNl0mgwRIbKt1Iyrx2iW4+ptAi4JCzVNk6EMcLL5bEUrgl
 IAp+Db4RfTZTd8eTO9Q4EaVl/isPeDvwXklQ2hshoNCqpU+GzYMnRuPEeUFeNkV1diPh
 a0SkLeG29drKPNjnjGtZX9428SX9ifLTe8Y0jByKnVhTT1Qs39VIAUEdka/9/4nY07aY
 L7/IyZJMB3bsp0kn9KwPZzy11pUKDjWoKewh1K7so9H+iYDzzJ//4ytXjJjC7SY+E6u+
 0hOVpbI513em+bDk1x7mvb6KsKn1NHMFJtwwlPHt+si7tltGItZBfzWY2HjIJX1wuZba
 sm4g==
X-Gm-Message-State: AOJu0Yy0H8LYGPZVPMol8czmXl4aLGDFXGWtz0ywj6XbPN3d1IQyt1it
 AqqCy6dMowdVlXSV0tUMEsqJBp3IypExY30bW+aTZR9zHXHzNpK9aEpyoQ==
X-Gm-Gg: ASbGncscK1IelMEKYxy5ucSHCsg40Ir9EA3fLfYiOeMnwd6eEotDu6xaBSSIwWwFTdp
 vpYHRn5nKPezgdfEpKaXYnZyDIH3Orbx9VW8LS/w4oBCpjHeLJKOdtSihufPUNU7Kb85zZrGjDz
 33c30D8Ya+hjcbQ4mIMebZkc0WYvLpfXMghEt7uvHCEDc4XiVBwDuJI8VBICu2hnVOds4yVNfiI
 RrlK1KHCqr6gGp0Z70McY9VOZvI1IpJoLiggiv8jp+WYc+zkuVd/aqBEUKW5w4Z1XM+2+Rg9j4y
 9KhTWv9rxhuE4BcqdVqfEQ9hQZVfo7WhxQ+FY7Y=
X-Google-Smtp-Source: AGHT+IEbLcZ5KTeStwqQpbo+BVYoguJuax4KfnPE74r/tvTJwH+bxSpXbca8ZBRp/WrTCytanqmKCg==
X-Received: by 2002:a4a:ee06:0:b0:5f8:d1a1:bea3 with SMTP id
 006d021491bc7-5fa39018497mr2791998eaf.2.1737156806605; 
 Fri, 17 Jan 2025 15:33:26 -0800 (PST)
User-Agent: Mozilla Thunderbird
Content-Language: en-US
X-BeenThere: python-list@python.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: General discussion list for the Python programming language
 <python-list.python.org>
List-Unsubscribe: <https://mail.python.org/mailman/options/python-list>,
 <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive: <https://mail.python.org/pipermail/python-list/>
List-Post: <mailto:python-list@python.org>
List-Help: <mailto:python-list-request@python.org?subject=help>
List-Subscribe: <https://mail.python.org/mailman/listinfo/python-list>,
 <mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID: <f01d0808-16fb-4b91-a518-a84d6973fee1@gmail.com>
Bytes: 7495

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
========================================================================