Skip to content

gh-107394: Document the keys method being part of the datamodel #107395

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

Closed
wants to merge 4 commits into from

Conversation

Gouvernathor
Copy link
Contributor

@Gouvernathor Gouvernathor commented Jul 28, 2023

I arbitrarily chose to list the keys method as part of the Python datamodel, and the instances it's called in as part of the CPython implementation. It could be preferred to remove the implementation detail part, but I think other options are not as great.

Feel free to propose changes, the formulation is probably not optimal.


📚 Documentation preview 📚: https://cpython-previews--107395.org.readthedocs.build/


.. impl-detail::

In CPython, the method is used by the ``**expression`` syntax in
Copy link

Choose a reason for hiding this comment

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

any identifier works certainly, but other places in the file it says **keywords, **kwds and **kwargs. For those used to python, something like **kwargs is even easier to read since it fits a very well known pattern, maybe?

Copy link
Contributor Author

@Gouvernathor Gouvernathor Jul 28, 2023

Choose a reason for hiding this comment

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

**kwargs can mean two things, either something you write in a function signature, also known as a variadic keyword parameter or a keyword catch-all, or you can write it in a function call. In the former case it takes an identifier and you can only have one, and in the latter it takes any expression and you can have several of them in the same call.
I think that's the reason why it was written as **expression in the Calls section of the doc (which I link to), so I think this formulation is less ambiguous.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From the datamo page, since you talked about other examples :

  • The first occurrence is **keywords which in contexts designates a function signature, specifically not the unary ** operator I'm talking about in this PR
  • The second is __init_subclass__ taking a **kwargs in its signature so same issue, even though it calls the super with the visually identical **kwargs after
  • Then there is __prepare__ and the metaclass call, which... are a mix of the two, I guess.

@@ -2590,6 +2591,19 @@ through the object's keys; for sequences, it should iterate through the values.
the container.


.. method:: object.keys(self)

This method can be used by Python in arbitrary circumstances to treat an
Copy link
Member

Choose a reason for hiding this comment

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

«Arbitrary» makes it sound like this is not well defined

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's the goal : to make no promises as to which part of the implementation use keys rather than, for example, __iter__. That formulation could disappear if we consider what I wrote as an implementation detail to be documented, and if we also make the pledge not to rely on keys for anything other than the unary ** and the update method. I think it's better this way.

Copy link
Member

Choose a reason for hiding this comment

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

But it sends a mixed message to have the datamodel doc sound uncertain about this!

Copy link
Member

Choose a reason for hiding this comment

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

Are there any places in Python where the presence of keys is not used to determine a mapping?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethanfurman there aren't many places where it needs to be determined whether something is a mapping or not, so I guess no, not really. Though issubclass/isinstance with collections.abc.MutableMapping doesn't check that and only checks inheritance (and things registered to it using the class's register method), as opposed to other ABCs in the same module - but that's the stdlib, not the CPython implem itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we could say that Python calls that method when it needs to tell a mapping apart from a sequence, and that it happens at least with the unary ** and in dict.update ? Without implementation detail entry at all. And assuming no other instance where it doesn't check keys is found.

Co-authored-by: bluss <bluss@users.noreply.github.com>
@@ -2590,6 +2591,19 @@ through the object's keys; for sequences, it should iterate through the values.
the container.


.. method:: object.keys(self)

This method can be used by Python in arbitrary circumstances to treat an
Copy link
Member

Choose a reason for hiding this comment

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

Are there any places in Python where the presence of keys is not used to determine a mapping?

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

Gouvernathor and others added 2 commits July 28, 2023 20:59
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
co-authored by @merwok
Copy link
Member

@terryjreedy terryjreedy left a comment

Choose a reason for hiding this comment

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

I consider both the change and the addition to be wrong and therefore feel this PR should be rejected and closed.

This issue is based on the OP's idea that 'keys' is 'reserved' because it is the 'override' method for the ** 'operator'. However, ** is a context-dependent syntax token, not an operator in the usual sense. If we do consider it a special 'syntax operator', the actual override method is, as usual, a true reserved method, mapping.keys().__iter__. The latter should be either mapping.iter or the equivalent; the indirection is only for duck typing. By the docs definition, reserved words all begin with _.

OP also claims that 'keys' is somehow unique. As I understand the claim, this is not so.

For more, see my comment today on the discourse thread, which expands a bit on my previous comment.

@Gouvernathor
Copy link
Contributor Author

Gouvernathor commented Jul 29, 2023

I suggest leaving that kind of consideration to the issue or the Discourse thread, and only focus on the phrasing and things like that in here. Although, of course, this PR cannot be merged before the question of relevance is resolved (and I understand why you mark it as disapproved).

@erlend-aasland
Copy link
Contributor

Closing, since the linked issue is closed.

@Gouvernathor Gouvernathor deleted the patch-7 branch August 4, 2023 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants