Narrow source positions for exceptions during pattern matching

Aberta
#96,999 4 comentários 0 reações 2 responsáveis Ver no GitHub

@iritkatriel já está trabalhando nisso.

Desde 30/9/2022.

Avaliação

Esta issue ainda não foi avaliada.

Descrição

interpreter-core type-feature

The source range in the traceback is to wide in some cases, if an exception is thrown during matching of a pattern.

The Ranges

example for attribute lookup:

class A:
    def __getattr__(self, name):
        assert name[0] == "a"
        return 5


match A():
    case A(apple=5, banana=7):
        print("hi")

output (Python 3.11.0rc2+):

Traceback (most recent call last):
  File "/home/frank/projects/cpython/match_test.py", line 8, in <module>
    case A(apple=5, banana=7):
         ^^^^^^^^^^^^^^^^^^^^
  File "/home/frank/projects/cpython/match_test.py", line 3, in __getattr__
    assert name[0] == "a"
AssertionError

Annotating only the source positions where the attribute check failed (banana=7) would make the traceback easier to read.

The same problem exists for positional matching:

class A:
    __match_args__ = ("apple", "banana")

    def __getattr__(self, name):
        assert name == "apple"


match A():
    case A(5, 7):
        print("hi")

output (Python 3.11.0rc2+):

Traceback (most recent call last):
  File "/home/frank/projects/cpython/match_test2.py", line 9, in <module>
    case A(5, 7):
         ^^^^^^^
  File "/home/frank/projects/cpython/match_test2.py", line 5, in __getattr__
    assert name == "apple"
AssertionError

Equality checks are handled better:

class NeverEqual:
    def __eq__(self, other):
        assert other==5


class A:
    def __init__(self):
        self.a = NeverEqual()
        self.b = 3


match A():
    case A(a=5|3, b=3):
        print("hi")

output (Python 3.11.0rc2+):

Traceback (most recent call last):
  File "/home/frank/projects/cpython/match_test3.py", line 13, in <module>
    case A(a=5|3, b=3):
               ^
  File "/home/frank/projects/cpython/match_test3.py", line 3, in __eq__
    assert other==5
AssertionError

Instance checks are represented in the same way:

class MetaB(type):
    def __instancecheck__(self, instance):
        assert False, "do not use me"


class B(metaclass=MetaB):
    pass


class A:
    def __init__(self):
        self.a = 5
        self.b = 3


match A():
    case A(a=5, b=2|B()):
        print("hi")

output (Python 3.11.0rc2+):

Traceback (most recent call last):
  File "/home/frank/projects/cpython/match_test4.py", line 17, in <module>
    case A(a=5, b=2|B()):
                    ^^^
  File "/home/frank/projects/cpython/match_test4.py", line 3, in __instancecheck__
    assert False, "do not use me"
AssertionError: do not use me

Problem for the User

Consistent source ranges would improve the readability of the tracebacks.

Is it possible to highlight always only the failing Pattern (with attribute name if given) for failing attribute access?

example:

case A(a=5):
       ^^^
case A(a=B()):
       ^^^^^
case A(5):
       ^
case A(5|B()):
       ^^^^^

Instance checks and equality tests are already handled well:

case A(a=5):
         ^
case A(a=B()):
         ^^^
case A(5):
       ^
case A(B()):
       ^^^
case A(5|B())
         ^^^

Problem for libraries

Libraries are using the source ranges for all sorts of functionality.
Executing for example is using this ranges (for the new 3.11 support) to map from instructions back to ast-nodes. Useful ranges are here required to map to useful ast-nodes.

Linguagem predominante
Python
Estrelas
77.2k
Forks
36k
Merge médio
1d 9h
PRs com merge (30d)
558

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de python/cpython

Todas as issues de python/cpython

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.