# HG changeset patch # User Thierry Florac # Date 1479484356 -3600 # Node ID d5fa9579f35d43e1df3423afe484fe9f2ed2390f # Parent d70e1629442bb0f0d4fd7c3d3d41f618c37781c6 Updated documentation diff -r d70e1629442b -r d5fa9579f35d docs/source/_static/zeo-add-form.png Binary file docs/source/_static/zeo-add-form.png has changed diff -r d70e1629442b -r d5fa9579f35d docs/source/_static/zeo-add-menu.png Binary file docs/source/_static/zeo-add-menu.png has changed diff -r d70e1629442b -r d5fa9579f35d docs/source/index.rst --- a/docs/source/index.rst Fri Nov 18 16:47:09 2016 +0100 +++ b/docs/source/index.rst Fri Nov 18 16:52:36 2016 +0100 @@ -35,7 +35,6 @@ site traverser tales - locks utilities diff -r d70e1629442b -r d5fa9579f35d docs/source/tales.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/source/tales.rst Fri Nov 18 16:52:36 2016 +0100 @@ -0,0 +1,74 @@ +.. _tales: + +Custom TALES extensions +======================= + +PyAMS defines a custom expression for TALES called *extension*. + +When this expression is encountered, the renderer is looking for an +:py:class:`ITALESExtension ` +multi-adapter for the current *context*, *request* and *view*, for the current +*context* and *request*, or only for the current *context*, in this order. +If an adapter is found, the renderer call it's :py:func:`render` method with +the expression parameters as input parameters. + +For example, the *metas* extension is an *ITALESExtension* adapter defined into +:py:mod:`pyams_skin.metas` module which can be used to include all required headers in +a page template. Extension is used like this in the page layout template: + +.. code-block:: html + + + +This extension is defined like this: + +.. code-block:: python + + from pyams_skin.interfaces.metas import IHTMLContentMetas + from pyams_utils.interfaces.tales import ITALESExtension + from pyramid.interfaces import IRequest + + from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter + + @adapter_config(name='metas', context=(Interface, IRequest, Interface), provides=ITALESExtension) + class MetasTalesExtension(ContextRequestViewAdapter): + '''extension:metas TALES extension''' + + def render(self, context=None): + if context is None: + context = self.context + result = [] + for name, adapter in sorted(self.request.registry.getAdapters((context, self.request, self.view), + IHTMLContentMetas), + key=lambda x: getattr(x[1], 'order', 9999)): + result.extend([meta.render() for meta in adapter.get_metas()]) + return '\n\t'.join(result) + +Some TALES extensions can require or accept arguments. For example, the *absolute_url* extension can accept +a context and a view name: + +.. code-block:: html + + + + + +The extension is defined like this: + +.. code-block:: python + + from persistent.interfaces import IPersistent + from pyams_utils.interfaces.tales import ITALESExtension + + from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter + from pyramid.url import resource_url + from zope.interface import Interface + + @adapter_config(name='absolute_url', context=(IPersistent, Interface, Interface), provides=ITALESExtension) + class AbsoluteUrlTalesExtension(ContextRequestViewAdapter): + '''extension:absolute_url(context, view_name) TALES extension''' + + def render(self, context=None, view_name=None): + if context is None: + context = self.context + return resource_url(context, self.request, view_name) diff -r d70e1629442b -r d5fa9579f35d docs/source/utilities.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/source/utilities.rst Fri Nov 18 16:52:36 2016 +0100 @@ -0,0 +1,57 @@ +.. _utilities: + +Custom PyAMS utilities +====================== + +PyAMS_utils provides a small set of utilities. You can create some of them as global utilities registered in +the global components registry; other ones can be created manually by a site administrator and +are then registered automatically. + + +Server timezone +--------------- + +To manage timezones correctly, and display datetimes based on current server timezone, all datetimes should +be defined and stored in UTC. + +PyAMS_utils provides a :py:class:`ServerTimezoneUtility ` which +allows you to assign a default timezone to your server. + +To display a datetime with correct timezone, you can use the :py:func:`tztime ` function, +which assign server timezone to the given parameter: + +.. code-block:: python + + from datetime import datetime + from pyams_utils.timezone import tztime + + now = datetime.utcnow() + my_date = tztime(now) # converts *now* to server timezone + +We could imagine that datetimes could be displayed with current user timezone. But it's quite impossible to know +the user timazone from a server request. The only options are: + +- you ask an authenticated user to update a timezone setting in his profile + +- you can include Javascript libraries which will try to detect browser timezone from their computer configuration, and + do an AJAX request to update data in their session. + +That should require an update of :py:func:`tzinfo` adapter to get timezone info from session, request or user profile. + + +ZEO connection +-------------- + +Several PyAMS utilities (like the tasks scheduler or the medias converter) are working with dedicated processes, +are connected to main PyAMS process through ØMQ, and use ZEO connections for their PyAMS database access. + +Clients of these processes have to send settings of the ZEO connections that they should use. + +The ZEOConnection utility can be created by the site manager through the web management interface (ZMI) from the +*Control panel*: + +.. image:: _static/zeo-add-menu.png + +ZEO connection creation form allows you to define all settings of a ZEO connection: + +.. image:: _static/zeo-add-form.png diff -r d70e1629442b -r d5fa9579f35d src/pyams_utils/tales.py --- a/src/pyams_utils/tales.py Fri Nov 18 16:47:09 2016 +0100 +++ b/src/pyams_utils/tales.py Fri Nov 18 16:52:36 2016 +0100 @@ -47,74 +47,7 @@ def render_extension(econtext, name): """TALES extension renderer - This renderer can be used to render an *extension:* TALES expression. - When this expression is encountered, the renderer is looking for an - :py:class:`ITALESExtension ` - multi-adapter for the current *context*, *request* and *view*, for the current - *context* and *request*, or only for the current *context*, in this order. - If an adapter is found, the renderer call it's :py:func:`render` method with - the expression parameters as input parameters. - - For example, the *metas* extension is an *ITALESExtension* adapter defined into - :py:mod:`pyams_skin.metas` module which can be used to include all required headers in - a page template. Extension is used like this in the page layout template: - - .. code-block:: html - - - - This extension is defined like this: - - .. code-block:: python - - from pyams_skin.interfaces.metas import IHTMLContentMetas - from pyams_utils.interfaces.tales import ITALESExtension - from pyramid.interfaces import IRequest - - from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter - - @adapter_config(name='metas', context=(Interface, IRequest, Interface), provides=ITALESExtension) - class MetasTalesExtension(ContextRequestViewAdapter): - '''extension:metas TALES extension''' - - def render(self, context=None): - if context is None: - context = self.context - result = [] - for name, adapter in sorted(self.request.registry.getAdapters((context, self.request, self.view), - IHTMLContentMetas), - key=lambda x: getattr(x[1], 'order', 9999)): - result.extend([meta.render() for meta in adapter.get_metas()]) - return '\n\t'.join(result) - - Some TALES extension can require or accept arguments. For example, the *absolute_url* extension can accept - a context and a view name: - - .. code-block:: html - - - - - - The extension is defined like this: - - .. code-block:: python - - from persistent.interfaces import IPersistent - from pyams_utils.interfaces.tales import ITALESExtension - - from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter - from pyramid.url import resource_url - from zope.interface import Interface - - @adapter_config(name='absolute_url', context=(IPersistent, Interface, Interface), provides=ITALESExtension) - class AbsoluteUrlTalesExtension(ContextRequestViewAdapter): - '''extension:absolute_url(context, view_name) TALES extension''' - - def render(self, context=None, view_name=None): - if context is None: - context = self.context - return resource_url(context, self.request, view_name) + See :ref:`tales` for complete description. """ def get_value(econtext, arg):