Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type annotation for an iterable class

I've got a class that extends ElementTree.Element:

import xml.etree.ElementTree as ET
from typing import cast


class MyElement(ET.Element):
    def my_method(self):
        print('OK')


xml = '''<test> <sub/> <sub/> </test>'''

root: MyElement = cast(
    MyElement,
    ET.fromstring(xml, parser=ET.XMLParser(target=ET.TreeBuilder(element_factory=MyElement))))

root.my_method()  # this is fine

for ch in root:
    ch.my_method()  # PyCharm error message  ???

This does work, however the last line is highlighted by PyCharm because it considers ch to be Element, not MyElement.

How should I annotate MyElement to make it clear that when I iterate it, I get MyElement instances and not ET.Elements?

like image 518
gog Avatar asked Sep 11 '25 19:09

gog


1 Answers

Annotate the __iter__ of MyElement as a method to return Iterator[MyElement]. There is almost no additional runtime overhead. Pycharm and mypy will both pass:

from collections.abc import Callable, Iterator


class MyElement(ET.Element):
    def my_method(self):
        print('OK')

    __iter__: Callable[..., Iterator['MyElement']]
like image 186
Mechanic Pig Avatar answered Sep 14 '25 11:09

Mechanic Pig