Skip to content
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

Support configparser.UNNAMED_SECTION (#13542) #13544

Merged
merged 3 commits into from
Feb 27, 2025

Conversation

mtnpke
Copy link
Contributor

@mtnpke mtnpke commented Feb 26, 2025

UNNAMED_SECTION was added in Python 3.13 and can be used in place of any section name. It is not actually a string though, so it needs a separate type.

UNNAMED_SECTION was added in Python 3.13 and can be used in place of any
section name. It is not actually a string though, so it needs a
separate type.

This comment has been minimized.

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I don't think, the DEFAULT section can be used everywhere. See below.

@mtnpke
Copy link
Contributor Author

mtnpke commented Feb 26, 2025

@srittau Not sure what you're talking about; this PR is about unnamed section, which is unrelated to the default section and can absolutely be used for sections() and options().

@mtnpke
Copy link
Contributor Author

mtnpke commented Feb 26, 2025

Python 3.13.1 (tags/v3.13.1:0671451, Dec  3 2024, 19:06:28) [MSC v.1942 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import configparser
>>> cp = configparser.ConfigParser(allow_unnamed_section=True)
>>> cp.read_string("a=1\n[sec]b=2")
>>> cp.sections()
[<UNNAMED_SECTION>, 'sec']
>>> type(cp.sections()[0])
<class 'configparser._UnnamedSection'>
>>> type(cp.sections()[1])
<class 'str'>
>>> cp.has_section(configparser.UNNAMED_SECTION)
True
>>> cp.options(configparser.UNNAMED_SECTION)
['a']
>>>

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mixing up unnamed and default sections it seems. That said, can you try one thing, please. See below. This will hopefully fix the new mypy primer hits.

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) -> list[_SectionName]: ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def sections(self) -> list[_SectionName]: ...
# This list 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).
def sections(self) -> list[str | _UNNAMED_SECTION | Any]: ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will not work because _UNNAMED_SECTION does not exist for python < 3.13

Copy link
Contributor Author

@mtnpke mtnpke Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of this in general because it limits the usefulness of type checking, but if it's a requirement that mypy_primer does not fail we can try it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably better to have separate branches for Python >= 3.13 and Python < 3.12 here anyway, so that < 3.12 can get tighter types here.

In typeshed, usability is a major concern. As the primer output shows, code that is currently working correctly would need additional churn with this change. This is something we want to avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you mean "< 3.13". It already has tighter types because of the type aliases. <3.13 will get list[str], as before.

As the types were objectively wrong before (as far as >= 3.13 is concerned!), it will be difficult to get it working without changes to existing code. What do you suggest?

@srittau srittau dismissed their stale review February 26, 2025 14:43

I was mixing up unnamed and default sections.

This comment has been minimized.

@mtnpke
Copy link
Contributor Author

mtnpke commented Feb 27, 2025

@srittau It does not help, unfortunately.

@srittau
Copy link
Collaborator

srittau commented Feb 27, 2025

Hmm, yes I wasn't sure if the "Any trick" worked in this situation. Unfortunately, the best we can do here is use list[Any] as return type (for >= 3.13). This is another one of the situation where AnyOf (python/typing#566) would help.

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@srittau srittau merged commit 0647903 into python:main Feb 27, 2025
55 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

configparser.UNNAMED_SECTION cannot be used with ConfigParser section API
2 participants