ElementTree: empty path makes find()/findall()/findtext() raise TypeError

Aberta Para iniciantes
#161,807 1 comentário 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
76/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
python
Domínio
backend

Direção de pesquisa

Comece lendo xml.etree.ElementPath.iterfind() e os chamadores de find(), findall() e findtext() descritos na issue. Reproduza o comportamento de um caminho vazio com e sem namespaces, incluindo o fallback em Python puro. O trabalho estará concluído quando todos os casos retornarem resultados consistentes ou gerarem um SyntaxError claro, com testes de regressão para ambas as implementações.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

extension-modules stdlib topic-XML type-bug
Bug report
Bug description

Passing an empty path to find(), findall() or findtext() (or to xml.etree.ElementPath directly) raises a confusing TypeError instead of returning a result or a clear error. Whether it happens depends on which implementation runs and on whether namespaces is passed.

With the C accelerator:

import xml.etree.ElementTree as ET
from xml.etree import ElementPath

root = ET.Element("root")
root.findall("")                  # []
root.findall("", namespaces={})   # TypeError: 'NoneType' object is not iterable
ElementPath.findall(root, "")     # TypeError: 'NoneType' object is not iterable

With the pure-Python implementation (the fallback used when _elementtree is unavailable), all of them fail:

import sys
sys.modules["_elementtree"] = None
import xml.etree.ElementTree as ET

root = ET.Element("root")
root.findall("")                  # TypeError: 'NoneType' object is not iterable
root.find("")                     # TypeError: 'NoneType' object is not an iterator
root.findtext("", default="D")    # TypeError: 'NoneType' object is not an iterator

Cause. ElementPath.iterfind() is a plain function, not a generator. For an empty path the tokenizer yields nothing, and the function does a bare return:

        try:
            token = next()
        except StopIteration:
            return

So it returns None instead of an iterator, and findall(), find() and findtext() then call list() or next() on None. The C accelerator only avoids this for a plain path without namespaces: its fast path treats "" as a tag name and returns [], None or the default.

Expected. The same result in both implementations, with or without namespaces. That could be either an empty result ([], None, the default), matching the C fast path, or a clear SyntaxError("invalid path"), which iterfind() already raises a few lines later for other incomplete paths. A minimal fix would be return iter(()) instead of the bare return.

I'm happy to open a PR.

CPython versions tested on:

CPython main branch, 3.14, 3.13, 3.12

Operating systems tested on:

Linux

Linked PRs
  • gh-161916
Linguagem predominante
Python
Estrelas
78.2k
Forks
36.6k
Merge médio
19h 57min
PRs com merge (30d)
630

Preparar o ambiente

Abrir no Codespaces

Inicia o contêiner de desenvolvimento do projeto no navegador, com a sua própria conta do GitHub.

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.