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

Abierto Apto para principiantes
#161,807 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
python
Área
backend

Línea de trabajo

Empieza leyendo xml.etree.ElementPath.iterfind() y los llamadores de find(), findall() y findtext() descritos en el issue. Reproduce el comportamiento de una ruta vacía con y sin namespaces, incluido el fallback puro de Python. El objetivo se alcanza cuando todos los casos devuelven resultados coherentes o generan un SyntaxError claro, y hay pruebas de regresión para ambas implementaciones.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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
Lenguaje dominante
Python
Estrellas
78.2k
Forks
36.6k
Merge medio
19 h 57 min
PR fusionados (30 d)
630

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de python/cpython

Todos los issues de python/cpython

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.