Skip to content

Support configparser.UNNAMED_SECTION (#13542) #13544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 27, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 52 additions & 40 deletions stdlib/configparser.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ else:
"MAX_INTERPOLATION_DEPTH",
]

if sys.version_info >= (3, 13):
class _UNNAMED_SECTION: ...
UNNAMED_SECTION: _UNNAMED_SECTION

_SectionName: TypeAlias = str | _UNNAMED_SECTION
# A list of sections can only include an unnamed section if the parser was initialized with
# allow_unnamed_section=True. Any prevents users from having to use explicit
# type checks if allow_unnamed_section is False (the default).
_SectionNameList: TypeAlias = list[Any]
else:
_SectionName: TypeAlias = str
_SectionNameList: TypeAlias = list[str]

_Section: TypeAlias = Mapping[str, str]
_Parser: TypeAlias = MutableMapping[str, _Section]
_ConverterCallback: TypeAlias = Callable[[str], Any]
Expand All @@ -87,17 +100,17 @@ DEFAULTSECT: Final = "DEFAULT"
MAX_INTERPOLATION_DEPTH: Final = 10

class Interpolation:
def before_get(self, parser: _Parser, section: str, option: str, value: str, defaults: _Section) -> str: ...
def before_set(self, parser: _Parser, section: str, option: str, value: str) -> str: ...
def before_read(self, parser: _Parser, section: str, option: str, value: str) -> str: ...
def before_write(self, parser: _Parser, section: str, option: str, value: str) -> str: ...
def before_get(self, parser: _Parser, section: _SectionName, option: str, value: str, defaults: _Section) -> str: ...
def before_set(self, parser: _Parser, section: _SectionName, option: str, value: str) -> str: ...
def before_read(self, parser: _Parser, section: _SectionName, option: str, value: str) -> str: ...
def before_write(self, parser: _Parser, section: _SectionName, option: str, value: str) -> str: ...

class BasicInterpolation(Interpolation): ...
class ExtendedInterpolation(Interpolation): ...

if sys.version_info < (3, 13):
class LegacyInterpolation(Interpolation):
def before_get(self, parser: _Parser, section: str, option: str, value: str, vars: _Section) -> str: ...
def before_get(self, parser: _Parser, section: _SectionName, option: str, value: str, vars: _Section) -> str: ...

class RawConfigParser(_Parser):
_SECT_TMPL: ClassVar[str] # undocumented
Expand Down Expand Up @@ -220,11 +233,11 @@ class RawConfigParser(_Parser):
def __iter__(self) -> Iterator[str]: ...
def __contains__(self, key: object) -> bool: ...
def defaults(self) -> _Section: ...
def sections(self) -> list[str]: ...
def add_section(self, section: str) -> None: ...
def has_section(self, section: str) -> bool: ...
def options(self, section: str) -> list[str]: ...
def has_option(self, section: str, option: str) -> bool: ...
def sections(self) -> _SectionNameList: ...
def add_section(self, section: _SectionName) -> None: ...
def has_section(self, section: _SectionName) -> bool: ...
def options(self, section: _SectionName) -> list[str]: ...
def has_option(self, section: _SectionName, option: str) -> bool: ...
def read(self, filenames: StrOrBytesPath | Iterable[StrOrBytesPath], encoding: str | None = None) -> list[str]: ...
def read_file(self, f: Iterable[str], source: str | None = None) -> None: ...
def read_string(self, string: str, source: str = "<string>") -> None: ...
Expand All @@ -234,26 +247,26 @@ class RawConfigParser(_Parser):
# These get* methods are partially applied (with the same names) in
# SectionProxy; the stubs should be kept updated together
@overload
def getint(self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None) -> int: ...
def getint(self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None) -> int: ...
@overload
def getint(
self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T = ...
self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T = ...
) -> int | _T: ...
@overload
def getfloat(self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None) -> float: ...
def getfloat(self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None) -> float: ...
@overload
def getfloat(
self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T = ...
self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T = ...
) -> float | _T: ...
@overload
def getboolean(self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None) -> bool: ...
def getboolean(self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None) -> bool: ...
@overload
def getboolean(
self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T = ...
self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T = ...
) -> bool | _T: ...
def _get_conv(
self,
section: str,
section: _SectionName,
option: str,
conv: Callable[[str], _T],
*,
Expand All @@ -263,29 +276,31 @@ class RawConfigParser(_Parser):
) -> _T: ...
# This is incompatible with MutableMapping so we ignore the type
@overload # type: ignore[override]
def get(self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None) -> str | MaybeNone: ...
def get(self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None) -> str | MaybeNone: ...
@overload
def get(
self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T
self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T
) -> str | _T | MaybeNone: ...
@overload
def items(self, *, raw: bool = False, vars: _Section | None = None) -> ItemsView[str, SectionProxy]: ...
@overload
def items(self, section: str, raw: bool = False, vars: _Section | None = None) -> list[tuple[str, str]]: ...
def set(self, section: str, option: str, value: str | None = None) -> None: ...
def items(self, section: _SectionName, raw: bool = False, vars: _Section | None = None) -> list[tuple[str, str]]: ...
def set(self, section: _SectionName, option: str, value: str | None = None) -> None: ...
def write(self, fp: SupportsWrite[str], space_around_delimiters: bool = True) -> None: ...
def remove_option(self, section: str, option: str) -> bool: ...
def remove_section(self, section: str) -> bool: ...
def remove_option(self, section: _SectionName, option: str) -> bool: ...
def remove_section(self, section: _SectionName) -> bool: ...
def optionxform(self, optionstr: str) -> str: ...
@property
def converters(self) -> ConverterMapping: ...

class ConfigParser(RawConfigParser):
# This is incompatible with MutableMapping so we ignore the type
@overload # type: ignore[override]
def get(self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None) -> str: ...
def get(self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None) -> str: ...
@overload
def get(self, section: str, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T) -> str | _T: ...
def get(
self, section: _SectionName, option: str, *, raw: bool = False, vars: _Section | None = None, fallback: _T
) -> str | _T: ...

if sys.version_info < (3, 12):
class SafeConfigParser(ConfigParser): ... # deprecated alias
Expand Down Expand Up @@ -349,38 +364,38 @@ class Error(Exception):
def __init__(self, msg: str = "") -> None: ...

class NoSectionError(Error):
section: str
def __init__(self, section: str) -> None: ...
section: _SectionName
def __init__(self, section: _SectionName) -> None: ...

class DuplicateSectionError(Error):
section: str
section: _SectionName
source: str | None
lineno: int | None
def __init__(self, section: str, source: str | None = None, lineno: int | None = None) -> None: ...
def __init__(self, section: _SectionName, source: str | None = None, lineno: int | None = None) -> None: ...

class DuplicateOptionError(Error):
section: str
section: _SectionName
option: str
source: str | None
lineno: int | None
def __init__(self, section: str, option: str, source: str | None = None, lineno: int | None = None) -> None: ...
def __init__(self, section: _SectionName, option: str, source: str | None = None, lineno: int | None = None) -> None: ...

class NoOptionError(Error):
section: str
section: _SectionName
option: str
def __init__(self, option: str, section: str) -> None: ...
def __init__(self, option: str, section: _SectionName) -> None: ...

class InterpolationError(Error):
section: str
section: _SectionName
option: str
def __init__(self, option: str, section: str, msg: str) -> None: ...
def __init__(self, option: str, section: _SectionName, msg: str) -> None: ...

class InterpolationDepthError(InterpolationError):
def __init__(self, option: str, section: str, rawval: object) -> None: ...
def __init__(self, option: str, section: _SectionName, rawval: object) -> None: ...

class InterpolationMissingOptionError(InterpolationError):
reference: str
def __init__(self, option: str, section: str, rawval: object, reference: str) -> None: ...
def __init__(self, option: str, section: _SectionName, rawval: object, reference: str) -> None: ...

class InterpolationSyntaxError(InterpolationError): ...

Expand All @@ -403,9 +418,6 @@ class MissingSectionHeaderError(ParsingError):
def __init__(self, filename: str, lineno: int, line: str) -> None: ...

if sys.version_info >= (3, 13):
class _UNNAMED_SECTION: ...
UNNAMED_SECTION: _UNNAMED_SECTION

class MultilineContinuationError(ParsingError):
lineno: int
line: str
Expand Down