Add Create a backend add-on section in the Developer guide with GenericSetup#1757
Add Create a backend add-on section in the Developer guide with GenericSetup#1757stevepiercy wants to merge 28 commits into
GenericSetup#1757Conversation
- Add term reference for Buildout
GenericSetup
|
I'm ready to close this issue as won't fix. Does anyone on @plone/classicui-team care about the topic of how to add or create a backend add-on section in the Developer guide with GenericSetup? If so, speak up, and let's get this finished. |
|
@stevepiercy will have a look at this. |
|
I've created a basic "addon creation documentation" and moved the old docs for GenericSetup here. I've also removed several outdated parts/link and tried to update the XML examples. Not finished yet though. I would recommend to place these docs all inside "Backend" and make a link from "Developer guide / Develop backend add-ons" -> "Backend / Add-ons" (like its done for Volto add-ons) Further we can add references for several What do you think? |
|
what's also missing is something like "Installing backend Add-on" ... at least I didn't find it... would also make sense to add it to "Backend / Add-ons" chapter. EDIT: I mean adding a pypi package or source checkout to cookieplone/buildout project ... |
Was this what you couldn't find? https://6.docs.plone.org/admin-guide/add-ons.html The plan is to merge the Admin section into Develop section so that people don't have to think of what role they're in versus the task they want to perform. See #1997. |
Co-authored-by: Mikel Larreategi <mlarreategi@codesyntax.com>
@petschki I don't see a commit to remove the outdated bits. Did you forget to push it? Please let me know. Thank you! |
|
I would use plonecli for all, after @erral did the final release in the comming days. example: uv tool install plonecli
plonecli create addon collective.myaddon
cd collective.myaddon
plonecli add content_type
...
We could even create a full cookieplone project with plonecli. plonecli create volto-projector plonecli create cookieplone-projector plonecli create plone-projectit doesn't matter and we are flexible to replace part under it, with the next cool tool, someone creates, without destroing exiting docs and api's. my 50cent... |
|
@MrTango I had documente the I think, due to the fact that the whole plone installation and theme development documentation uses cookieplone, we should at least use it for the inital addon package creation too ... when adding further features inside the addon, we can document this with using |
|
@petschki @MrTango sorry for the mess... with plonecli right now we can create an add-on calling I haven't checked to do the same for volto addon, project, etc, but could be done, and it is not that hard. If we do that we can document everything to use plonecli indeed, and But we also have documentation to create Volto projects using |
|
cookieplone is the framework with utils to full manage a Plone project while plonecli is a client that implements the frameworks (past and present). |
|
What are the use cases that we're trying to solve with this page of documentation? Maybe that answer will help us give a direction. Would y'all agree there are essentially two scenarios?
Neither Cookieplone nor plonecli are going away anytime soon. If we have two or more ways of doing the same thing, that's fine, too, provided we give sufficient information for the reader to choose which tool is best for them. For an example of that, see Choose a user interface. It's also OK if we use one tool to do one part, such as using Cookieplone to create a monorepo with all the things, and another tool to do another part, such as add new features to the backend add-on. Does this help at all? |
davisagli
left a comment
There was a problem hiding this comment.
Let's see if we can get this over the finish line.
There was a problem hiding this comment.
I just skimmed through to check that this is still accurate/relevant information. It is and we should prioritize getting this merged. It does need some editing to match current doc styles.
|
I have just released new versions for mr.bob, plonecli and bobtemplates removing all pkg_resources style namespaces. I tested the three of them together and it works as expected. I will review this PR tomorrow to check that everything is Ok. |
erral
left a comment
There was a problem hiding this comment.
I have checked the output of uvx plonecli and it is a bit different than the previous version.
|
|
||
| --> Package description [An add-on for Plone]: | ||
|
|
||
| --> Plone version [6.0.0]: | ||
|
|
||
| --> Python version for virtualenv [python3]: | ||
|
|
||
| --> Do you want me to activate VS Code support? (y/n) [y]: | ||
|
|
||
|
|
||
|
|
||
| isort-apply: successful: | ||
| isort-apply: install_deps> python -I -m pip install isort -c constraints.txt | ||
| isort-apply: commands[0]> isort /Users/<username>/Development/collective.addon/src | ||
| /Users/<username>/Development/collective.addon/setup.py | ||
| Fixing /Users/<username>/Development/collective.addon/src/collective/addon/testing.py | ||
| Fixing /Users/<username>/Development/collective.addon/src/collective/addon/tests/test_setup.py | ||
| isort-apply: OK (2.57=setup[1.94]+cmd[0.63] seconds) | ||
| congratulations :) (2.59 seconds) | ||
|
|
||
|
|
||
| Identified `/` as project root containing a file system root. | ||
| Sources to be formatted: "Users/<username>/Development/collective.addon/src", | ||
| "Users/<username>/Development/collective.addon/setup.py" | ||
| src/collective/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/browser/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/locales/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/tests/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/interfaces.py already well formatted, good job. | ||
| reformatted src/collective/addon/__init__.py | ||
| reformatted src/collective/addon/setuphandlers.py | ||
| reformatted src/collective/addon/testing.py | ||
| reformatted setup.py | ||
| reformatted src/collective/addon/locales/update.py | ||
| reformatted src/collective/addon/tests/test_setup.py | ||
|
|
||
| All done! ✨ 🍰 ✨ | ||
| 6 files reformatted, 5 files left unchanged. | ||
|
|
||
| black-enforce: successful: | ||
| black-enforce: install_deps> python -I -m pip install black -c constraints.txt | ||
| black-enforce: commands[0]> black -v src setup.py | ||
| black-enforce: OK (2.60=setup[2.12]+cmd[0.48] seconds) | ||
| congratulations :) (2.61 seconds) | ||
|
|
||
|
|
||
| git init is disabled! | ||
| Generated file structure at /Users/<username>/Development/collective.addon/collective.addon | ||
| ``` |
There was a problem hiding this comment.
| --> Package description [An add-on for Plone]: | |
| --> Plone version [6.0.0]: | |
| --> Python version for virtualenv [python3]: | |
| --> Do you want me to activate VS Code support? (y/n) [y]: | |
| isort-apply: successful: | |
| isort-apply: install_deps> python -I -m pip install isort -c constraints.txt | |
| isort-apply: commands[0]> isort /Users/<username>/Development/collective.addon/src | |
| /Users/<username>/Development/collective.addon/setup.py | |
| Fixing /Users/<username>/Development/collective.addon/src/collective/addon/testing.py | |
| Fixing /Users/<username>/Development/collective.addon/src/collective/addon/tests/test_setup.py | |
| isort-apply: OK (2.57=setup[1.94]+cmd[0.63] seconds) | |
| congratulations :) (2.59 seconds) | |
| Identified `/` as project root containing a file system root. | |
| Sources to be formatted: "Users/<username>/Development/collective.addon/src", | |
| "Users/<username>/Development/collective.addon/setup.py" | |
| src/collective/__init__.py wasn't modified on disk since last run. | |
| src/collective/addon/browser/__init__.py wasn't modified on disk since last run. | |
| src/collective/addon/locales/__init__.py wasn't modified on disk since last run. | |
| src/collective/addon/tests/__init__.py wasn't modified on disk since last run. | |
| src/collective/addon/interfaces.py already well formatted, good job. | |
| reformatted src/collective/addon/__init__.py | |
| reformatted src/collective/addon/setuphandlers.py | |
| reformatted src/collective/addon/testing.py | |
| reformatted setup.py | |
| reformatted src/collective/addon/locales/update.py | |
| reformatted src/collective/addon/tests/test_setup.py | |
| All done! ✨ 🍰 ✨ | |
| 6 files reformatted, 5 files left unchanged. | |
| black-enforce: successful: | |
| black-enforce: install_deps> python -I -m pip install black -c constraints.txt | |
| black-enforce: commands[0]> black -v src setup.py | |
| black-enforce: OK (2.60=setup[2.12]+cmd[0.48] seconds) | |
| congratulations :) (2.61 seconds) | |
| git init is disabled! | |
| Generated file structure at /Users/<username>/Development/collective.addon/collective.addon | |
| ``` | |
| RUN: bobtemplates.plone:addon -O collective.addon | |
| Welcome to mr.bob interactive mode. Before we generate directory structure, some questions need to be answered. | |
| Answer with a question mark to display help. | |
| Values in square brackets at the end of the questions show the default value if there is no answer. | |
| --> Author's name [Mikel Larreategi]: | |
| --> Author's email [mlarreategi@codesyntax.com]: | |
| --> Author's GitHub username: | |
| --> Package description [An add-on for Plone]: | |
| --> Do you want me to initialize a GIT repository in your new package? (y/n) [y]: | |
| --> Plone version [6.0.0]: | |
| --> Python version for virtualenv [python3]: | |
| --> Do you want me to activate VS Code support? (y/n) [y]: | |
| ╭──────────────────────────────── cookieplone ─────────────────────────────────╮ | |
| │ │ | |
| │ ******* │ | |
| │ *************** │ | |
| │ *** *** │ | |
| │ *** *** *** │ | |
| │ *** ***** *** │ | |
| │ *** *** *** │ | |
| │ *** *** *** │ | |
| │ *** ***** *** │ | |
| │ *** *** *** *** │ | |
| │ *** ***** *** │ | |
| │ *** *** *** │ | |
| │ *** *** │ | |
| │ *************** │ | |
| │ ******* │ | |
| │ │ | |
| ╰──────────────────────────────────────────────────────────────────────────────╯ | |
| ╭──────────────────────────────── Plone Addon ─────────────────────────────────╮ | |
| │ │ | |
| │ Creating a new Plone Addon │ | |
| │ │ | |
| │ Sanity check results: │ | |
| │ │ | |
| │ - Cookieplone: ✓ │ | |
| │ - uv: ✓ │ | |
| │ - git: ✓ │ | |
| │ │ | |
| ╰──────────────────────────────────────────────────────────────────────────────╯ | |
| -> Remove files used in classic UI setup | |
| -> Create namespace packages | |
| -> Format code | |
| -> Initialize Git repository | |
| -> Generate documentation scaffold | |
| -> Setup VSCode configuration | |
| -> Setup GitHub CI | |
| ╭────────────────────────── New addon was generated ───────────────────────────╮ | |
| │ │ | |
| │ collective.addon │ | |
| │ │ | |
| │ Now, enter the repository, start coding, and push to your organization. │ | |
| │ │ | |
| │ Sorry for the convenience, │ | |
| │ The Plone Community. │ | |
| │ │ | |
| │ https://plone.org/ │ | |
| ╰──────────────────────────────────────────────────────────────────────────────╯ | |
| Done | |
| Generated file structure at /tmp/collective.addon |
There was a problem hiding this comment.
Thanks @erral! The terminal output is very wide, though. The code block area when rendered in the docs starts to wrap at the 90th character, requiring users to horizontal scroll back and forth to view the output. Would you please narrow your terminal session window and run it again?
stevepiercy
left a comment
There was a problem hiding this comment.
I started a review, and I'm not sure what remains in here about archetypes. Anyone know?
I'm also slowly going through this to pass editorial review, which will be in subsequent commits.
| ```{todo} | ||
| remove archetypes example code everywhere | ||
| ``` | ||
|
|
There was a problem hiding this comment.
Either remove this todo or remove the code to which it refers.
|
|
||
| --> Package description [An add-on for Plone]: | ||
|
|
||
| --> Plone version [6.0.0]: | ||
|
|
||
| --> Python version for virtualenv [python3]: | ||
|
|
||
| --> Do you want me to activate VS Code support? (y/n) [y]: | ||
|
|
||
|
|
||
|
|
||
| isort-apply: successful: | ||
| isort-apply: install_deps> python -I -m pip install isort -c constraints.txt | ||
| isort-apply: commands[0]> isort /Users/<username>/Development/collective.addon/src | ||
| /Users/<username>/Development/collective.addon/setup.py | ||
| Fixing /Users/<username>/Development/collective.addon/src/collective/addon/testing.py | ||
| Fixing /Users/<username>/Development/collective.addon/src/collective/addon/tests/test_setup.py | ||
| isort-apply: OK (2.57=setup[1.94]+cmd[0.63] seconds) | ||
| congratulations :) (2.59 seconds) | ||
|
|
||
|
|
||
| Identified `/` as project root containing a file system root. | ||
| Sources to be formatted: "Users/<username>/Development/collective.addon/src", | ||
| "Users/<username>/Development/collective.addon/setup.py" | ||
| src/collective/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/browser/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/locales/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/tests/__init__.py wasn't modified on disk since last run. | ||
| src/collective/addon/interfaces.py already well formatted, good job. | ||
| reformatted src/collective/addon/__init__.py | ||
| reformatted src/collective/addon/setuphandlers.py | ||
| reformatted src/collective/addon/testing.py | ||
| reformatted setup.py | ||
| reformatted src/collective/addon/locales/update.py | ||
| reformatted src/collective/addon/tests/test_setup.py | ||
|
|
||
| All done! ✨ 🍰 ✨ | ||
| 6 files reformatted, 5 files left unchanged. | ||
|
|
||
| black-enforce: successful: | ||
| black-enforce: install_deps> python -I -m pip install black -c constraints.txt | ||
| black-enforce: commands[0]> black -v src setup.py | ||
| black-enforce: OK (2.60=setup[2.12]+cmd[0.48] seconds) | ||
| congratulations :) (2.61 seconds) | ||
|
|
||
|
|
||
| git init is disabled! | ||
| Generated file structure at /Users/<username>/Development/collective.addon/collective.addon | ||
| ``` |
There was a problem hiding this comment.
Thanks @erral! The terminal output is very wide, though. The code block area when rendered in the docs starts to wrap at the 90th character, requiring users to horizontal scroll back and forth to view the output. Would you please narrow your terminal session window and run it again?
stevepiercy
left a comment
There was a problem hiding this comment.
After performing an editorial review and creating a separate PR against this one, then reading through these latest two sections, there is no way that this PR can be merged. It refers to obsolete practices, things that don't actually work, and it wanders without clear direction or context.
I understand it's the result of decades of copy paste and ad hoc contributions. It's going to take a lot of collaboration between those with the technical and historical knowledge and me to make it understandable for readers who don't have decades of experience with Plone.
To move this forward, please take a look at #2083 and add your comments there. Thank you!
| ## Metadata version numbers | ||
|
|
||
| Some old add-on packages may have a `metadata.xml` without version number, but this is considered bad practice. | ||
|
|
||
| What should the version number in your `metadata.xml` be? | ||
|
|
||
| This mostly matters when you are adding upgrade steps, see also the [Upgrade steps] section. | ||
|
|
||
| Upgrade steps have a sort order in which they are executed. This used to be alphabetical sorting. | ||
|
|
||
| When you had eleven upgrade steps, marked from 1 through 11, alphabetical sorting meant this order: 1, 10, 11, 2, 3, etc. | ||
|
|
||
| If you are seeing this, then you are using an old version of GenericSetup. | ||
|
|
||
| You want numerical sorting here, which is correctly done currently. Versions with dots work fine too. | ||
|
|
||
| They get ordered just like they would when used for packages on PyPI. | ||
|
|
||
| Best practice for all versions of GenericSetup is this: | ||
|
|
||
| - Start with 1000. | ||
| This avoids problems with ancient GenericSetup that used alphabetical sorting. | ||
| - Simply increase the version by 1 each time you need a new metadata version. | ||
| For example: 1001, 1002, etc. | ||
| - If your add-on package version number changes, but your profile stays the same and no upgrade step is needed, you should **not** change the metadata version. | ||
| There is no need. | ||
| - If you make changes for a new major release, you should increase the metadata version significantly. | ||
| This leaves room for small metadata version increases on a maintenance branch. | ||
| Example: | ||
| You have branch master with version 1025. | ||
| You make backwards incompatible changes and you increase the version to 2000. | ||
| You create a maintenance branch where the next metadata version will be 1026. |
There was a problem hiding this comment.
This section is too much. I think it should be rewritten to promote Python version specifiers as described in https://packaging.python.org/en/latest/specifications/version-specifiers/, and mention that if there are integer numbers or none, then use Python version specifiers.
Would that break anything? @mauritsvanrees or anyone else with historical knowledge on this topic.
There was a problem hiding this comment.
@stevepiercy I think this section is an accurate, if a bit informal, description of how GenericSetup profile versions are used in practice. I have never seen one that is not an integer....this claims that works, but I can't confirm that without trying it. I would be very surprised if more complex Python version specifiers (with e.g. dev/a/b/rc) worked here.
There was a problem hiding this comment.
@davisagli thanks for the feedback. This is what I latched onto.
... Versions with dots work fine too.
They get ordered just like they would when used for packages on PyPI.
Which implies the sort order is by Python version specifiers, not alphabetic, numeric, or alphanumeric. But then a version with a dot could also be a decimal. Agh! GenericSetup's change log was no help to me either.
It would be nice to be certain of what is actually supported. If certainty is not possible, then I can simplify this section to specify integers only, while dropping mention of dots or PyPI versions for metadata versions. It might not be complete, but accuracy and clarity take precedence.
| ## Custom Installer Code (`setuphandlers.py`) | ||
|
|
||
| Besides out-of-the-box XML steps which provide both install and uninstall, | ||
| GenericSetup provides a way to run custom Python code when your add-on package is installed and uninstalled. | ||
|
|
||
| In `configure.zcml`: | ||
|
|
||
| ``` | ||
| <configure | ||
| xmlns="http://namespaces.zope.org/zope" | ||
| xmlns:genericsetup="http://namespaces.zope.org/genericsetup" | ||
| i18n_domain="your.addonpackage"> | ||
|
|
||
| <genericsetup:registerProfile | ||
| name="default" | ||
| title="Your Add-on Package" | ||
| directory="profiles/default" | ||
| description="A useful package" | ||
| provides="Products.GenericSetup.interfaces.EXTENSION" | ||
| pre_handler="your.addonpackage.setuphandlers.run_before" | ||
| post_handler="your.addonpackage.setuphandlers.run_after" | ||
| /> | ||
|
|
||
| </configure> | ||
| ``` | ||
|
|
||
| In `setuphandlers.py`: | ||
|
|
||
| ```python | ||
| def run_before(context): | ||
| # This is run before running the first import step of | ||
| # the default profile. context is portal_setup. | ||
| # If you need the same context as you would get in | ||
| # an import step, like setup_various below, do this: | ||
| profile_id = 'profile-your.addonpackage:default' | ||
| good_old_context = context._getImportContext(profile_id) | ||
| ... | ||
|
|
||
| def run_after(context): | ||
| # This is run after running the last import step of | ||
| # the default profile. context is portal_setup. | ||
| ... | ||
| ``` | ||
|
|
||
| The best practice is to create a `setuphandlers.py` file which contains a function `setup_various()` which runs the required Python code | ||
| to make changes to Plone site object. | ||
|
|
||
| This function is registered as a custom `genericsetup:importStep` in XML. | ||
|
|
||
| ```{note} | ||
| When you write a custom `importStep`, remember to write uninstallation code as well. | ||
| ``` | ||
|
|
||
| However, the trick is that all GenericSetup import steps, including your custom step, are run for *every* add-on package when they are installed. | ||
|
|
||
| If your need to run code which is **specific to your add-on install only** you need to use a marker text file which is checked by the GenericSetup context. | ||
|
|
||
| Also you need to register this custom import step in `configure.zcml`: | ||
|
|
||
| ```xml | ||
| <configure | ||
| xmlns="http://namespaces.zope.org/zope" | ||
| xmlns:genericsetup="http://namespaces.zope.org/genericsetup"> | ||
|
|
||
| <genericsetup:importStep | ||
| name="your.addonpackage" | ||
| title="your.addonpackage special import handlers" | ||
| description="" | ||
| handler="your.addonpackage.setuphandlers.setup_various" | ||
| /> | ||
|
|
||
| </configure> | ||
| ``` |
There was a problem hiding this comment.
This section is also confusing. First we say "do this", then later say "do this best practice." This section should be rewritten to provide a single example as the best way to do it first, then follow it with variations in subsequent examples.
See #1748 (comment)
Closes #1754.
Ping @petschki to take it from here.
📚 Documentation preview 📚: https://plone6--1757.org.readthedocs.build/