Source code for plone_client.managers.site

"""Site configuration and maintenance."""

from .base import BaseManager
from collections.abc import Iterable
from collections.abc import Iterator
from collections.abc import Mapping
from typing import Any


[docs] class RegistryManager(BaseManager): """Configuration registry (``@registry``)."""
[docs] def get(self, key: str) -> Any: """Value of a registry record. :param key: Record name, such as ``plone.site_title``. :returns: The value. """ return self._client.get(f"/@registry/{key}")
[docs] def list(self, query: str | None = None) -> Iterator[dict[str, Any]]: """Registry records. :param query: Only records whose name contains this text. :returns: Each record, with ``name``, ``value`` and ``schema``. """ return self._client.iter_items("/@registry", {"q": query, "b_size": 100})
[docs] def update(self, values: Mapping[str, Any]) -> None: """Change registry records. :param values: New values by record name. """ self._client.patch("/@registry", dict(values))
[docs] def set(self, key: str, value: Any) -> None: """Change one registry record. :param key: Record name. :param value: New value. """ self.update({key: value})
[docs] class ControlpanelsManager(BaseManager): """Control panels (``@controlpanels``)."""
[docs] def list(self) -> list[dict[str, Any]]: """Control panels of the site. :returns: ``@id``, ``title`` and ``group`` of each panel. """ return self._client.get("/@controlpanels")
[docs] def get(self, panel: str, item: str | None = None) -> dict[str, Any]: """A control panel, or an item inside it. :param panel: Panel id, such as ``editing`` or ``dexterity-types``. :param item: Item id, such as a content type in ``dexterity-types``. :returns: Its schema and data. """ path = f"/@controlpanels/{panel}/{item}" if item else f"/@controlpanels/{panel}" return self._client.get(path)
[docs] def update( self, panel: str, data: Mapping[str, Any], *, item: str | None = None ) -> None: """Change settings of a control panel, or of an item inside it. :param panel: Panel id. :param data: New values. :param item: Item id. """ path = f"/@controlpanels/{panel}/{item}" if item else f"/@controlpanels/{panel}" self._client.patch(path, dict(data))
[docs] def create(self, panel: str, data: Mapping[str, Any]) -> dict[str, Any]: """Add an item to a control panel, such as a content type. :param panel: Panel id, such as ``dexterity-types``. :param data: Data of the new item. :returns: The new item. """ return self._client.post(f"/@controlpanels/{panel}", dict(data))
[docs] def delete(self, panel: str, item: str) -> None: """Remove an item from a control panel. :param panel: Panel id. :param item: Item id. """ self._client.delete(f"/@controlpanels/{panel}/{item}")
[docs] class AddonsManager(BaseManager): """Add-ons (``@addons``)."""
[docs] def list(self) -> dict[str, Any]: """Add-ons available on the site. :returns: ``items``, each with ``is_installed`` and ``upgrade_info``. """ return self._client.get("/@addons")
[docs] def get(self, addon: str) -> dict[str, Any]: """One add-on. :param addon: Add-on id, such as ``plone.app.multilingual``. :returns: The add-on. """ return self._client.get(f"/@addons/{addon}")
[docs] def install(self, addon: str) -> dict[str, Any]: """Install an add-on. :param addon: Add-on id. :returns: The add-ons, after the change. """ return self._client.post(f"/@addons/{addon}/install")
[docs] def uninstall(self, addon: str) -> dict[str, Any]: """Uninstall an add-on. :param addon: Add-on id. :returns: The add-ons, after the change. """ return self._client.post(f"/@addons/{addon}/uninstall")
[docs] def upgrade(self, addon: str) -> dict[str, Any]: """Run the pending upgrade steps of an add-on. :param addon: Add-on id. :returns: The add-ons, after the change. """ return self._client.post(f"/@addons/{addon}/upgrade")
[docs] def install_profile(self, addon: str, profile: str) -> dict[str, Any]: """Import a GenericSetup profile of an add-on. :param addon: Add-on id. :param profile: Profile name, such as ``default``. :returns: The add-ons, after the change. """ return self._client.post(f"/@addons/{addon}/import/{profile}")
[docs] class ContentRulesManager(BaseManager): """Content rules assigned to a folder (``@content-rules``)."""
[docs] def get(self, ref: str = "/") -> dict[str, Any]: """Rules assigned to a folder, and rules that could be. :param ref: Path or URL of the folder. :returns: ``content-rules`` with ``assigned_rules`` and ``addable_rules``. """ return self._client.get(self._service(ref, "@content-rules"))
[docs] def assign(self, ref: str, rule_id: str) -> None: """Assign a rule to a folder. :param ref: Path or URL of the folder. :param rule_id: Rule id. """ self._client.post(self._service(ref, f"@content-rules/{rule_id}"))
[docs] def unassign(self, ref: str, rule_ids: str | Iterable[str]) -> None: """Remove rules from a folder. :param ref: Path or URL of the folder. :param rule_ids: Rule id, or several. """ ids = [rule_ids] if isinstance(rule_ids, str) else list(rule_ids) self._client.delete(self._service(ref, "@content-rules"), {"rule_ids": ids})
def _buttons(self, ref: str, button: str, rule_ids: str | Iterable[str]) -> None: """Press a button of the rules form for some rules. :param ref: Path or URL of the folder. :param button: ``Enable``, ``Disable``, ``Bubble`` or ``NoBubble``. :param rule_ids: Rule id, or several. """ ids = [rule_ids] if isinstance(rule_ids, str) else list(rule_ids) self._client.patch( self._service(ref, "@content-rules"), {f"form.button.{button}": True, "rule_ids": ids}, )
[docs] def enable(self, ref: str, rule_ids: str | Iterable[str]) -> None: """Enable rules on a folder. :param ref: Path or URL of the folder. :param rule_ids: Rule id, or several. """ self._buttons(ref, "Enable", rule_ids)
[docs] def disable(self, ref: str, rule_ids: str | Iterable[str]) -> None: """Disable rules on a folder. :param ref: Path or URL of the folder. :param rule_ids: Rule id, or several. """ self._buttons(ref, "Disable", rule_ids)
[docs] def apply_to_subfolders( self, ref: str, rule_ids: str | Iterable[str], *, apply: bool = True ) -> None: """Apply rules to the subfolders of a folder, or stop doing so. :param ref: Path or URL of the folder. :param rule_ids: Rule id, or several. :param apply: ``False`` stops applying them to subfolders. """ self._buttons(ref, "Bubble" if apply else "NoBubble", rule_ids)
[docs] def move(self, ref: str, rule_id: str, *, up: bool = True) -> None: """Move a rule up or down in the folder's list. :param ref: Path or URL of the folder. :param rule_id: Rule id. :param up: ``False`` moves it down. """ self._client.patch( self._service(ref, "@content-rules"), {"operation": "move_up" if up else "move_down", "rule_id": rule_id}, )
[docs] class SystemManager(BaseManager): """Information about the site and maintenance tasks."""
[docs] def site(self) -> dict[str, Any]: """Site settings used by frontends (``@site``). :returns: Title, logo, languages and similar settings. """ return self._client.get("/@site")
[docs] def system(self) -> dict[str, Any]: """Versions of Plone, Python, Zope and other components (``@system``). Needs the *Manage portal* permission. :returns: Version numbers and upgrade state. """ return self._client.get("/@system")
[docs] def database(self) -> dict[str, Any]: """Database statistics (``@database``). :returns: Size, object count, cache and connection details. """ return self._client.get("/@database")
[docs] def transactions(self) -> list[dict[str, Any]]: """Recent transactions (``@transactions``). :returns: ``id``, ``time``, ``username`` and ``description`` of each. """ return self._client.get("/@transactions")
[docs] def revert_transactions( self, transaction_ids: str | Iterable[str] ) -> dict[str, Any]: """Undo transactions. :param transaction_ids: Id of a transaction, or several. :returns: A confirmation message. """ ids = ( [transaction_ids] if isinstance(transaction_ids, str) else list(transaction_ids) ) return self._client.patch("/@transactions", {"transaction_ids": ids})
[docs] def upgrade_info(self) -> dict[str, Any]: """Pending upgrade steps of the site (``@upgrade``). :returns: Versions and the upgrade steps to run. """ return self._client.get("/@upgrade")
[docs] def upgrade(self, *, dry_run: bool = True) -> dict[str, Any]: """Run the site's upgrade steps. :param dry_run: Only report what would run. :returns: The upgrade report. """ return self._client.post("/@upgrade", {"dry_run": dry_run})
[docs] def login_providers(self) -> dict[str, Any]: """External authentication providers (``GET @login``). :returns: ``options`` with each provider's ``url``. """ return self._client.get("/@login")
[docs] def email_send( self, to: str, sender: str, message: str, *, subject: str | None = None, name: str | None = None, ) -> None: """Send an email through the site (``@email-send``). :param to: Recipient address. :param sender: Sender address. :param message: Body of the message. :param subject: Subject. :param name: Sender name. """ data = {"to": to, "from": sender, "message": message} data.update({k: v for k, v in (("subject", subject), ("name", name)) if v}) self._client.post("/@email-send", data)
[docs] def email_notification( self, sender: str, message: str, *, subject: str | None = None, name: str | None = None, ) -> None: """Send a message to the site owner, like the contact form does. :param sender: Sender address. :param message: Body of the message. :param subject: Subject. :param name: Sender name. """ data = {"from": sender, "message": message} data.update({k: v for k, v in (("subject", subject), ("name", name)) if v}) self._client.post("/@email-notification", data)