How do I type subclasses that require private types?

Hello, I’ve subclassed the ConfigParser class whose get() method is typed as follows (pyi):

def get(self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T) -> str | _T: ...

Note the _SectionName which is defined as (pyi):

class _UNNAMED_SECTION: ...
UNNAMED_SECTION: _UNNAMED_SECTION

_SectionName: TypeAlias = str | _UNNAMED_SECTION

Being a “private” module type I tried to create my own type like so:

if TYPE_CHECKING:
    # fails: from configparser import UNNAMED_SECTION  # [valid-type]
    # See also: https://github.com/python/typeshed/tree/main/stdlib/_typeshed
    # fails: from _typeshed import configparser  # [attr-defined]
    # fails: from _typeshed import _SectionName  # [attr-defined]
    # fails: from _typeshed.configparser import _SectionName  # [import-not-found]
    # fails: from _typeshed import UNNAMED_SECTION  # [attr-defined]
    from _typeshed.configparser import UNNAMED_SECTION  # [import-not-found]

    SectionName: TypeAlias = str | UNNAMED_SECTION

However, I can’t seem to be able to import UNNAMED_SECTION or _SectionName, and I’m running out of ideas.

How would I type this method in a subclass? This is for Python 3.13 and mypy v1.16.0.

Thank you!

Looks like a design error in ConfigParser’s type annotations to me. A public interface shouldn’t contain private types for exactly the reason in this question.

1 Like

First of all, I think you want _UNNAMED_SECTION. UNNAMED_SECTION is an object, not a type. The definition of _SectionName reflects that fact.

But I think the main issue is that your mypy config does not set the python version to 3.13. Either way it seems more robust to import _SectionName from typeshed, then you have a type alias that works on every Python version, without having to maintain it yourself.

You should import _UNNAMED_SECTION (the type, not the constant, as mentioned before) from configparser, so not from _typeshed.