Skip to content

Add typing annotations#592

Merged
davisagli merged 1 commit into
mainfrom
ale/typing
Jun 17, 2026
Merged

Add typing annotations#592
davisagli merged 1 commit into
mainfrom
ale/typing

Conversation

@ale-rt

@ale-rt ale-rt commented Nov 30, 2025

Copy link
Copy Markdown
Member

Initial draft courtesy of monkeytype:

.venv/bin/uv pip install -e plone.api[test] monkeytype zope.testrunner
monkeytype run .venv/bin/zope-testrunner --path plone.api/src/
for module in `monkeytype list-modules`; do monkeytype apply $module || true > /dev/null;done
  • I signed and returned the Plone Contributor Agreement, and received and accepted an invitation to join a team in the Plone GitHub organization.
  • I verified there aren't any other open pull requests for the same change.
  • I followed the guidelines in Contributing to Plone.
  • I successfully ran code quality checks on my changes locally.
  • I successfully ran tests on my changes locally.
  • If needed, I added new tests for my changes.
  • If needed, I added documentation for my changes.
  • I included a change log entry in my commits.

If your pull request closes an open issue, include the exact text below, immediately followed by the issue number. When your pull request gets merged, then that issue will close automatically.

Closes #


📚 Documentation preview 📚: https://ploneapi--592.org.readthedocs.build/

@mister-roboto

Copy link
Copy Markdown

@ale-rt thanks for creating this Pull Request and helping to improve Plone!

TL;DR: Finish pushing changes, pass all other checks, then paste a comment:

@jenkins-plone-org please run jobs

To ensure that these changes do not break other parts of Plone, the Plone test suite matrix needs to pass, but it takes 30-60 min. Other CI checks are usually much faster and the Plone Jenkins resources are limited, so when done pushing changes and all other checks pass either start all Jenkins PR jobs yourself, or simply add the comment above in this PR to start all the jobs automatically.

Happy hacking!

Comment thread src/plone/api/portal.py
def get_localized_time(datetime=None, long_format=False, time_only=False):
def get_localized_time(
datetime: Optional[Union[date, DateTime, datetime]] = None,
long_format: bool = False,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This exposes an incorrect behavior of this method as long_format can also be a custom string
https://github.com/plone/plone.base/blob/18f2f4c7ca24da0d6b26bf9c25a061c7cf3ec037/src/plone/base/i18nl10n.py#L221-L224

@ale-rt

ale-rt commented Nov 30, 2025

Copy link
Copy Markdown
Member Author

@jenkins-plone-org please run jobs

@ale-rt

ale-rt commented Dec 1, 2025

Copy link
Copy Markdown
Member Author

@jenkins-plone-org please run jobs

@ericof

ericof commented Dec 1, 2025

Copy link
Copy Markdown
Member

@ale-rt Take a look at https://github.com/plone/plone-stubs. The current state already support plone.api and it should be in a decent state.

@ale-rt

ale-rt commented Dec 1, 2025

Copy link
Copy Markdown
Member Author

@jenkins-plone-org please run jobs

@ale-rt

ale-rt commented Dec 1, 2025

Copy link
Copy Markdown
Member Author

@ale-rt Take a look at https://github.com/plone/plone-stubs. The current state already support plone.api and it should be in a decent state.

Thanks, I checked it, yet I believe this is an improvement worth to be merged.

@ale-rt ale-rt requested a review from davisagli December 1, 2025 20:14

@davisagli davisagli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will take some time to review carefully.

For a start, at first glance, I see lots of annotations with ImplicitAcquisitionWrapper that look wrong. Those are usually meant to be a DexterityContent, and I think monkeytype was confused by the acquisition wrapper.

@ale-rt

ale-rt commented Dec 2, 2025

Copy link
Copy Markdown
Member Author

This will take some time to review carefully.

For a start, at first glance, I see lots of annotations with ImplicitAcquisitionWrapper that look wrong. Those are usually meant to be a DexterityContent, and I think monkeytype was confused by the acquisition wrapper.

It does not look wrong to me:

>>> isinstance(api.portal.get(), ImplicitAcquisitionWrapper)
True

I think it is way worse to use in the annotation DexterityContent because that might be not true at all.

@ericof

ericof commented Dec 2, 2025

Copy link
Copy Markdown
Member

@ale-rt Right now, all content types we have are Dexterity based. I understand your point of using ImplicitAcquisitionWrapper, but this is kind of useless in term of auto-complete for IDEs, isn't it?

@davisagli

Copy link
Copy Markdown
Member

Most of these APIs are designed specifically to work with content objects, not any acquisition-wrapped Python object. So using ImplicitAcquisitionWrapper still seems quite wrong to me.

@ale-rt

ale-rt commented Dec 2, 2025

Copy link
Copy Markdown
Member Author

@ale-rt Right now, all content types we have are Dexterity based. I understand your point of using ImplicitAcquisitionWrapper, but this is kind of useless in term of auto-complete for IDEs, isn't it?

Autocomplete in the IDE is not the point of this PR, IMO.

Most probably you will anyway end up with code like:

obj: Document = api.content.get(UID="...")
view: PloneView = api.content.get_view("plone")

@ale-rt

ale-rt commented Dec 2, 2025

Copy link
Copy Markdown
Member Author

Most of these APIs are designed specifically to work with content objects, not any acquisition-wrapped Python object. So using ImplicitAcquisitionWrapper still seems quite wrong to me.

To me it seems wrong to say it returns a dexterity content :D
I could replace that with Any, because that would be accurate. What do you think?

@davisagli

Copy link
Copy Markdown
Member

Any is not remotely accurate. If the function is meant to do something with a content item and I pass it a str (for example), that will not work.

ale-rt added a commit that referenced this pull request May 27, 2026
@ale-rt ale-rt force-pushed the ale/typing branch 2 times, most recently from 2eb1c7b to 75a7796 Compare May 27, 2026 20:01
ale-rt added a commit that referenced this pull request May 27, 2026
Backport some clean up from #592
@ale-rt ale-rt mentioned this pull request May 27, 2026
8 tasks
ale-rt added a commit that referenced this pull request May 27, 2026
Backport some clean up from #592
ale-rt added a commit that referenced this pull request May 27, 2026
Backport some clean up from #592
@ale-rt

ale-rt commented May 27, 2026

Copy link
Copy Markdown
Member Author

@jenkins-plone-org please run jobs

Comment thread news/+ec620103.internal.md Outdated
Comment thread src/plone/api/_types.py Outdated
Comment thread src/plone/api/_types.py Outdated
Comment thread src/plone/api/_types.py Outdated
Comment thread src/plone/api/addon.py Outdated
Comment thread src/plone/api/content.py
Comment thread src/plone/api/content.py Outdated
Comment thread src/plone/api/content.py Outdated
Comment thread src/plone/api/content.py Outdated
Comment thread src/plone/api/portal.py Outdated
mister-roboto pushed a commit to plone/buildout.coredev that referenced this pull request May 29, 2026
Branch: refs/heads/main
Date: 2026-05-27T22:46:05+02:00
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com>
Commit: plone/plone.api@62f3fc7

Clean up

Backport some clean up from plone/plone.api#592

Files changed:
A news/592.bugfix.md
M docs/portal.md
M src/plone/api/content.py
M src/plone/api/portal.py
M src/plone/api/tests/test_portal.py
M src/plone/api/user.py
Repository: plone.api

Branch: refs/heads/main
Date: 2026-05-28T13:35:59+02:00
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com>
Commit: plone/plone.api@257aee3

fixup! Clean up

Files changed:
M src/plone/api/user.py
Repository: plone.api

Branch: refs/heads/main
Date: 2026-05-28T13:39:07+02:00
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com>
Commit: plone/plone.api@ef8dd61

fixup! Clean up

Files changed:
M src/plone/api/user.py
Repository: plone.api

Branch: refs/heads/main
Date: 2026-05-29T09:41:44+02:00
Author: David Glick (davisagli) <david@glicksoftware.com>
Commit: plone/plone.api@829547a

Merge pull request #605 from plone/ale/typing-backports

 Clean up

Files changed:
A news/592.bugfix.md
M docs/portal.md
M src/plone/api/content.py
M src/plone/api/portal.py
M src/plone/api/tests/test_portal.py
M src/plone/api/user.py
mister-roboto pushed a commit to plone/buildout.coredev that referenced this pull request May 29, 2026
Branch: refs/heads/main
Date: 2026-05-27T22:46:05+02:00
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com>
Commit: plone/plone.api@62f3fc7

Clean up

Backport some clean up from plone/plone.api#592

Files changed:
A news/592.bugfix.md
M docs/portal.md
M src/plone/api/content.py
M src/plone/api/portal.py
M src/plone/api/tests/test_portal.py
M src/plone/api/user.py
Repository: plone.api

Branch: refs/heads/main
Date: 2026-05-28T13:35:59+02:00
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com>
Commit: plone/plone.api@257aee3

fixup! Clean up

Files changed:
M src/plone/api/user.py
Repository: plone.api

Branch: refs/heads/main
Date: 2026-05-28T13:39:07+02:00
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com>
Commit: plone/plone.api@ef8dd61

fixup! Clean up

Files changed:
M src/plone/api/user.py
Repository: plone.api

Branch: refs/heads/main
Date: 2026-05-29T09:41:44+02:00
Author: David Glick (davisagli) <david@glicksoftware.com>
Commit: plone/plone.api@829547a

Merge pull request #605 from plone/ale/typing-backports

 Clean up

Files changed:
A news/592.bugfix.md
M docs/portal.md
M src/plone/api/content.py
M src/plone/api/portal.py
M src/plone/api/tests/test_portal.py
M src/plone/api/user.py
Comment thread .meta.toml Outdated
Comment thread src/plone/api/content.py Outdated
@davisagli

Copy link
Copy Markdown
Member

@jenkins-plone-org please run jobs

@davisagli davisagli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, assuming the jenkins builds pass

@ale-rt

ale-rt commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

@ericof, @mauritsvanrees are you ok having this merged?

@ericof

ericof commented Jun 5, 2026

Copy link
Copy Markdown
Member

Would you mind taking a look at plone-stubs? It solves many issues I see with your current approach.
Either way, I'm not opposed to your merge

@davisagli

Copy link
Copy Markdown
Member

@ericof I worked on this with @ale-rt at the sprint. We resolved the issues I had noticed earlier and I think it's in pretty good shape now. What are the issues you still see? We can't consider fixing them if you don't say what they are.

You and I have talked about plone-stubs before. I see the reasoning for having one package in the short term where stubs can be added for multiple Plone packages. But I also think in the long term we should try to add type hints to the actual packages.

@ericof

ericof commented Jun 6, 2026

Copy link
Copy Markdown
Member

@davisagli, @ale-rt First, sorry for sounding so "negative", that was not my intention.

Instead of doing a nit-pick about which types should be returned, I would like to suggest two immediate points (considering what I've learned so far about typing plone.api and other packages) to be addressed:

  • We probably should be using more @overloads to closely match the signature of the functions here:
@overload
def get(userid: str, username: str | None = None) -> MemberData | None:
@overload
def get(userid: None, username: str) -> MemberData | None:
  • To avoid polluting the code with all overloads, we should ship the .pyi files

If plone.api is completely typed I would remove it from plone-stubs and keep working on the other packages.

And, as I said, I'm not opposing this PR

@davisagli

Copy link
Copy Markdown
Member

@ericof Thanks for the clarification. I agree, using overloads for the functions that accept several different combinations of parameters sounds like it would be a nice improvement.

@davisagli

Copy link
Copy Markdown
Member

Let's go ahead and merge this, and work on other improvements (such as overloads) in a new PR.

@davisagli davisagli merged commit 62237a9 into main Jun 17, 2026
15 checks passed
@davisagli davisagli deleted the ale/typing branch June 17, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants