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

Issue #533: Implement API get_vocabulary & get_vocabularies_name #557

Merged
merged 15 commits into from
Feb 18, 2025

Conversation

ujsquared
Copy link
Contributor

@ujsquared ujsquared commented Feb 11, 2025

Fixes Issue #533

  • Uses implementation from kitconcept.api, as mentioned in the issue description. Includes both the APIs present in source.
  • Tests written and documentation done.

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

@mister-roboto
Copy link

@ujsquared 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!

@ujsquared
Copy link
Contributor Author

@jenkins-plone-org please run jobs

@stevepiercy
Copy link
Contributor

@ujsquared please edit the pull request description as described in Item 2, second bullet point, in https://6.docs.plone.org/contributing/first-time.html#create-a-pull-request-from-your-fork.

Copy link
Contributor

@stevepiercy stevepiercy left a comment

Choose a reason for hiding this comment

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

Docs look good to me. Minor changes requested to the change log. Thank you!

Needs technical review. Also where and when do we run and verify the doctests, that is, the lines of code with a leading % in the docs?

Direct links to pull request preview:

news/533.feature Outdated Show resolved Hide resolved
news/533.feature Outdated Show resolved Hide resolved
news/533.feature Outdated Show resolved Hide resolved
news/533.feature Outdated Show resolved Hide resolved
@stevepiercy
Copy link
Contributor

Strange, we say to include doctests in https://6.docs.plone.org/plone.api/contribute.html#add-a-function-to-an-existing-module, but don't say how to actually run them or verify them in CI. What did I miss?

As a quick hack, I added this to tox.ini on line 302 as a quick hack:

    sphinx-build -b doctest -d _build/docs/doctrees docs _build/docs/doctest

And running tox -e docs results in no doctests found.

Doctest summary
===============
    0 tests
    0 failures in tests
    0 failures in setup code
    0 failures in cleanup code

@ksuess do you have any idea? I recall you worked on this 2 or 3 years ago.

@ujsquared
Copy link
Contributor Author

Needs technical review. Also where and when do we run and verify the doctests, that is, the lines of code with a leading % in the docs?

I have no idea too, /src/plone/api/tests/doctests/ only contains symlinks to docs/.

try:
vocab = getUtility(IVocabularyFactory, name)
except ComponentLookupError:
raise InvalidParameterError(f"No vocabulary with name '{name}' available.")
Copy link
Member

Choose a reason for hiding this comment

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

Thanks a lot for your contribution!
It might be interesting to have an error message consistent with the one raised by the get_view function:

except ComponentLookupError:
# Getting all available views
sm = getSiteManager()
available_views = sm.adapters.lookupAll(
required=(providedBy(context), providedBy(request)),
provided=Interface,
)
# Check if the requested view is available
# by getting the names of all available views
available_view_names = [view[0] for view in available_views]
if name not in available_view_names:
# Raise an error if the requested view is not available.
raise InvalidParameterError(
"Cannot find a view with name '{name}'.\n"
"Available views are:\n"
"{views}".format(
name=name,
views="\n".join(sorted(available_view_names)),
),
)

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Making the changes.

:return: A list of vocabularies names.
"""
all_vocabs = getUtilitiesFor(IVocabularyFactory)
return [v[0] for v in all_vocabs]
Copy link
Member

Choose a reason for hiding this comment

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

What do you think about:

Suggested change
return [v[0] for v in all_vocabs]
return sorted([name for name, vocabulary in getUtilitiesFor(IVocabularyFactory)])

?

Comment on lines 1462 to 1463
self.assertTrue(vocab)
self.assertTrue(hasattr(vocab, "__iter__")) # Verify it's iterable
Copy link
Member

Choose a reason for hiding this comment

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

I would replace these lines with a self.assertIsInstance

Copy link
Contributor Author

@ujsquared ujsquared Feb 12, 2025

Choose a reason for hiding this comment

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

would you suggest importing collections.abc just to replace current approach?
i can try going with this
image
but i'm not sure if vocabularies with length 0 are to be supported or not.

Copy link
Member

@ale-rt ale-rt Feb 12, 2025

Choose a reason for hiding this comment

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

Nope, sorry. I was referring to something like:

Suggested change
self.assertTrue(vocab)
self.assertTrue(hasattr(vocab, "__iter__")) # Verify it's iterable
self.assertIsInstance(vocabulary, SimpleVocabulary)

Copy link
Member

@ale-rt ale-rt left a comment

Choose a reason for hiding this comment

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

Great work!
Thanks for your contribution.
I added some suggestion.

I would not be cheap with variable names.
I would replace vocab with vocabulary and vocabs with vocabularies.

@ksuess
Copy link
Member

ksuess commented Feb 12, 2025

Strange, we say to include doctests in https://6.docs.plone.org/plone.api/contribute.html#add-a-function-to-an-existing-module, but don't say how to actually run them or verify them in CI. What did I miss?

As a quick hack, I added this to tox.ini on line 302 as a quick hack:

    sphinx-build -b doctest -d _build/docs/doctrees docs _build/docs/doctest

And running tox -e docs results in no doctests found.

Doctest summary
===============
    0 tests
    0 failures in tests
    0 failures in setup code
    0 failures in cleanup code

@ksuess do you have any idea? I recall you worked on this 2 or 3 years ago.

Well, yes, the "contributing" chapter lacks the mentioning of tox -e test.
tox -e test runs all tests, including the doctests.
Will raise a PR.

Copy link
Member

@ksuess ksuess left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your contribution! Awesome.

I think, as most of the vocabularies are not context sensitive, these two new methods would fit better in api.portal than in api.content

self.assertIn("private", states)
self.assertIn("published", states)

def test_vocabulary_context_sensitivity(self):
Copy link
Member

@ksuess ksuess Feb 12, 2025

Choose a reason for hiding this comment

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

This test on context sensitivity would need a vocabulary that is context sensitive to be meaningful.
I would say this test is not really needed, as the new plone.api method api.content.get_vocabulary is simply calling getUtility(IVocabularyFactory, name) and applying this vocabulary to the context. So the underlying code is testing the context sensitivity already.
Further opinions are welcome.

src/plone/api/content.py Outdated Show resolved Hide resolved
vocabulary = portal.get_vocabulary(name="plone.app.vocabularies.PortalTypes")
self.assertIsInstance(
vocabulary, SimpleVocabulary
) # Check for correct interface
Copy link
Member

Choose a reason for hiding this comment

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

this tests on being vocabulary an instance of a class. The comment is not correct. Better no comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Earlier, I was testing for IVocabularyTokenized interface. Missed updating the comment

src/plone/api/tests/test_portal.py Show resolved Hide resolved
docs/portal.md Outdated Show resolved Hide resolved
docs/portal.md Outdated Show resolved Hide resolved
docs/portal.md Show resolved Hide resolved
@ksuess ksuess linked an issue Feb 12, 2025 that may be closed by this pull request
@ujsquared
Copy link
Contributor Author

@jenkins-plone-org please run jobs

src/plone/api/portal.py Outdated Show resolved Hide resolved
Copy link
Member

@ksuess ksuess left a comment

Choose a reason for hiding this comment

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

Looks good to me. Well done, @ujsquared.

The failing test is unrelated.
I approve.

@ksuess ksuess requested review from stevepiercy and ale-rt February 13, 2025 09:04
@ale-rt
Copy link
Member

ale-rt commented Feb 13, 2025

I think, as most of the vocabularies are not context sensitive, these two new methods would fit better in api.portal than in api.content

@ksuess I am not really sure about that.
To me, it seems that api.content is a better fit, but I do not have a strong opinion.

Maybe some other people might share their feelings about where these helpers should go.

CC @plone/framework-team

Copy link
Member

@ale-rt ale-rt left a comment

Choose a reason for hiding this comment

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

This looks fine to me.
Please wait the other reviewers approval before merging.

src/plone/api/portal.py Outdated Show resolved Hide resolved
as suggested by @ale-rt

Co-authored-by: Alessandro Pisa <[email protected]>
@ale-rt
Copy link
Member

ale-rt commented Feb 13, 2025

@jenkins-plone-org please run jobs

@ale-rt
Copy link
Member

ale-rt commented Feb 14, 2025

@stevepiercy I am merging this, I hope you are fine with that.

@stevepiercy
Copy link
Contributor

@ale-rt please wait for me to complete my review. There is no rush.

@stevepiercy
Copy link
Contributor

I'd like to hold off on merging this PR until @ksuess's PR #558 is merged, as that one affects this PR and it provides welcome improvements.

I'll submit a review after that PR is merged to verify that make test works as expected.

@stevepiercy
Copy link
Contributor

Well, yes, the "contributing" chapter lacks the mentioning of tox -e test.
tox -e test runs all tests, including the doctests.
Will raise a PR.

@ksuess I don't see how tox -e test runs doctests, which is invoked with sphinx-build doctests. What am I missing?

@ksuess
Copy link
Member

ksuess commented Feb 17, 2025

tox -e test runs all tests, including the doctests.

@ksuess I don't see how tox -e test runs doctests, which is invoked with sphinx-build doctests. What am I missing?

Tests in doctests/*.md, both code snippets and invisible code blocks, are tested in https://github.com/plone/plone.api/blob/main/src/plone/api/tests/test_doctests.py. It uses manuel TestSuite.

@stevepiercy
Copy link
Contributor

Tests in doctests/*.md, both code snippets and invisible code blocks, are tested in https://github.com/plone/plone.api/blob/main/src/plone/api/tests/test_doctests.py. It uses manuel TestSuite.

To verify, I altered one of the doctests in contribute.md so that its assertion would fail. make test passed. Maybe I misunderstand what is the purpose of % invisible-code-block: python?

However, when I change a doctest in user.md:

% self.assertEqual(user.getProperty('email'), '[email protected]')

make test fails.

So maybe the test itself does not get called? Ah, there is a missing symlink for contribute.md! Should we test contribute.md as well? I mean, there are doctests in it...

@ksuess
Copy link
Member

ksuess commented Feb 17, 2025

Should we test contribute.md as well? I mean, there are doctests in it...

Yes, it would make sense to test the example tests. Would you be so kind to add a symlink in tests/doctests? Thank you!

@davisagli
Copy link
Member

Yes, it would make sense to test the example tests. Would you be so kind to add a symlink in tests/doctests?

@stevepiercy @ksuess Done in 3d1ae92

Copy link
Contributor

@stevepiercy stevepiercy left a comment

Choose a reason for hiding this comment

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

This looks great! Let's merge when green.

@stevepiercy
Copy link
Contributor

@jenkins-plone-org please run jobs

docs/portal.md Outdated Show resolved Hide resolved
Co-authored-by: Alessandro Pisa <[email protected]>
@stevepiercy
Copy link
Contributor

@jenkins-plone-org please run jobs

@stevepiercy
Copy link
Contributor

Looks like Jenkins does not like some tests. What should we do?

@ujsquared
Copy link
Contributor Author

Looks like Jenkins does not like some tests. What should we do?

Out of curiosity, isn't this the one that failed earlier too? Even locally I'm running into issues when testing on python3.9. Any fixes?

image

@stevepiercy
Copy link
Contributor

And now they're all green. ¯\_(ツ)_/¯ I'm gonna merge.

@stevepiercy stevepiercy merged commit a876d70 into plone:main Feb 18, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Add api.content.get_vocabulary
6 participants