Skip to content

Commit

Permalink
Merge pull request #286 from plone/registry-interface-269
Browse files Browse the repository at this point in the history
Allow to set/get registry settings from an interface
  • Loading branch information
Adam Forsythe-Cheasley committed Nov 30, 2015
2 parents 9a840e7 + 9a06aae commit 8cc89d4
Show file tree
Hide file tree
Showing 4 changed files with 327 additions and 5 deletions.
4 changes: 3 additions & 1 deletion docs/CHANGES.rst
Expand Up @@ -6,7 +6,9 @@ Changelog

New:

- *add item here*
- Allow to set/get registry settings from an interface.
https://github.com/plone/plone.api/issues/269
[gforcada]

Fixes:

Expand Down
48 changes: 48 additions & 0 deletions docs/portal.rst
Expand Up @@ -226,6 +226,30 @@ Plone comes with a package ``plone.app.registry`` that provides a common way to
self.assertTrue(api.portal.get_registry_record('my.package.someoption'))
One common pattern when using registry records is to define an interface with all the settings.
:meth:`api.portal.get_registry_record` also allows you to use this pattern.

.. invisible-code-block: python
from plone.registry.interfaces import IRegistry
from plone.api.tests.test_portal import IMyRegistrySettings
registry = getUtility(IRegistry)
registry.registerInterface(IMyRegistrySettings)
records = registry.forInterface(IMyRegistrySettings)
records.field_one = u'my text'
.. code-block:: python
from plone import api
api.portal.get_registry_record('field_one', interface=IMyRegistrySettings)
.. invisible-code-block: python
self.assertEqual(
api.portal.get_registry_record('field_one', interface=IMyRegistrySettings),
u'my text'
)
.. _portal_set_registry_record_example:

Expand Down Expand Up @@ -255,6 +279,30 @@ Plone comes with a package ``plone.app.registry`` that provides a common way to
self.assertFalse(registry['my.package.someoption'])
One common pattern when using registry records is to define an interface with all the settings.
:meth:`api.portal.set_registry_record` also allows you to use this pattern.


.. invisible-code-block: python
from plone.registry.interfaces import IRegistry
from plone.api.tests.test_portal import IMyRegistrySettings
registry = getUtility(IRegistry)
registry.registerInterface(IMyRegistrySettings)
records = registry.forInterface(IMyRegistrySettings)
.. code-block:: python
from plone import api
api.portal.set_registry_record('field_one', u'new value', interface=IMyRegistrySettings)
.. invisible-code-block: python
self.assertEqual(
api.portal.get_registry_record('field_one', interface=IMyRegistrySettings),
u'new value'
)
Further reading
---------------
Expand Down
69 changes: 65 additions & 4 deletions src/plone/api/portal.py
Expand Up @@ -18,6 +18,7 @@
from zope.component import providedBy
from zope.component.hooks import getSite
from zope.globalrequest import getRequest
from zope.interface.interfaces import IInterface

import pkg_resources

Expand Down Expand Up @@ -249,19 +250,46 @@ def show_message(message=None, request=None, type='info'):


@required_parameters('name')
def get_registry_record(name=None):
def get_registry_record(name=None, interface=None):
"""Get a record value from ``plone.app.registry``
:param name: [required] Name
:type name: string
:param interface: interface whose attributes are plone.app.registry
settings
:type interface: zope.interface.Interface
:returns: Registry record value
:rtype: plone.app.registry registry record
:Example: :ref:`portal_get_registry_record_example`
"""
if not isinstance(name, str):
raise InvalidParameterError(u"The parameter has to be a string")
raise InvalidParameterError(u"The 'name' parameter has to be a string")

if interface is not None and not IInterface.providedBy(interface):
raise InvalidParameterError(
u"The interface parameter has to derive from "
u"zope.interface.Interface"
)

registry = getUtility(IRegistry)

if interface is not None:
records = registry.forInterface(interface)
_marker = object()
if getattr(records, name, _marker) == _marker:
# Show all records on the interface.
records = [key for key in interface.names()]
raise InvalidParameterError(
"Cannot find a record with name '{0}' on interface {1}.\n"
"Did you mean?"
"{2}".format(
name,
interface.__identifier__,
'\n'.join(records)
)
)
return registry['{0}.{1}'.format(interface.__identifier__, name)]

if name not in registry:
# Show all records that 'look like' name.
# We don't dump the whole list, because it 1500+ items.
Expand All @@ -281,19 +309,52 @@ def get_registry_record(name=None):


@required_parameters('name', 'value')
def set_registry_record(name=None, value=None):
def set_registry_record(name=None, value=None, interface=None):
"""Set a record value in the ``plone.app.registry``
:param name: [required] Name of the record
:type name: string
:param value: [required] Value to set
:type value: python primitive
:param interface: interface whose attributes are plone.app.registry
settings
:type interface: zope.interface.Interface
:Example: :ref:`portal_set_registry_record_example`
"""
if not isinstance(name, str):
raise InvalidParameterError(u"The parameter 'name' has to be a string")

if interface is not None and not IInterface.providedBy(interface):
raise InvalidParameterError(
u"The interface parameter has to derive from "
u"zope.interface.Interface"
)

registry = getUtility(IRegistry)
if isinstance(name, str):

if interface is not None:
# confirm that the name exists on the interface
get_registry_record(name=name, interface=interface)

from zope.schema._bootstrapinterfaces import WrongType
try:
registry['{0}.{1}'.format(interface.__identifier__, name)] = value
except WrongType:
field_type = [
f[1]
for f in interface.namesAndDescriptions()
if f[0] == 'field_one'
][0]
raise InvalidParameterError(
u"The value parameter for the field {0} needs to be {1}"
u"instead of {2}".format(
name,
str(field_type.__class__),
type(value)
)
)

elif isinstance(name, str):

# confirm that the record exists before setting the value
get_registry_record(name)
Expand Down

0 comments on commit 8cc89d4

Please sign in to comment.