--- a/buildout.cfg Wed May 16 12:00:26 2018 +0200
+++ b/buildout.cfg Wed May 16 14:06:43 2018 +0200
@@ -1,5 +1,5 @@
[buildout]
-extensions = buildout.wheel
+#extensions = buildout.wheel
eggs-directory = /var/local/env/pyams/eggs
extends = http://download.ztfy.org/pyams/pyams-dev.cfg
find-links = http://download.ztfy.org/eggs
@@ -10,12 +10,6 @@
show-picked-versions = true
newest = false
-allow-hosts =
- bitbucket.org
- *.python.org
- *.sourceforge.net
- github.com
-
versions = versions
develop =
.
@@ -86,6 +80,7 @@
pyams_zmi
pyams_zmq
pyams_zodbbrowser
+ repoze.lru
zc.lockfile
interpreter = ${buildout:directory}/bin/py
@@ -93,6 +88,7 @@
recipe = collective.recipe.sphinxbuilder
eggs =
${package:eggs}
+ repoze.sphinx.autointerface
sphinx_rtd_theme
source = ${buildout:directory}/src/source
build = ${buildout:directory}/src/build
--- a/requirements.txt Wed May 16 12:00:26 2018 +0200
+++ b/requirements.txt Wed May 16 14:06:43 2018 +0200
@@ -38,6 +38,7 @@
pyramid-fanstatic==0.5
pyramid-zodbconn==0.7
pyzmq==16.0.4
+repoze.lru = 0.7
repoze.sphinx.autointerface==0.8
Sphinx==1.6.7
sphinx_rtd_theme==0.2.4
--- a/setup.py Wed May 16 12:00:26 2018 +0200
+++ b/setup.py Wed May 16 14:06:43 2018 +0200
@@ -62,7 +62,9 @@
extras_require=dict(test=tests_require),
install_requires=[
'setuptools',
- 'sphinx_rtd_theme'
+ 'repoze.lru',
+ 'repoze.sphinx.autointerface',
+ 'sphinx_rtd_theme',
# -*- Extra requirements: -*-
],
entry_points={})
--- a/src/pyams_user_guide.egg-info/requires.txt Wed May 16 12:00:26 2018 +0200
+++ b/src/pyams_user_guide.egg-info/requires.txt Wed May 16 14:06:43 2018 +0200
@@ -1,4 +1,6 @@
setuptools
+repoze.lru
+repoze.sphinx.autointerface
sphinx_rtd_theme
[test]
--- a/src/source/appextend.rst Wed May 16 12:00:26 2018 +0200
+++ b/src/source/appextend.rst Wed May 16 14:06:43 2018 +0200
@@ -5,59 +5,51 @@
**Portlets** are pluggable user interface software components that are managed and displayed in a web portal,
for example an enterprise portal or a web CMS. A portlet can aggregate (integrate) and personalize content from
-different sources within a web page. A portlet responds to requests from a web client with and generates dynamic content.
-(*reference:* `Wiki portlet`_)
+different sources within a web page. A portlet responds to requests from a web client and generates dynamic content
+(*reference:* `Wiki portlet`_).
.. _`wiki portlet`: https://en.wikipedia.org/wiki/Portlet
-**Pyams Portal** provides predefined portlets that to compose and organize the structure of a website.
+**PyAMS Portal** provides the portal engine but only a very small set of predefined portlets that can be used to compose
+and organize the structure of a web page; additional portlets are provided by other packages, like
+:ref:`pyams_content`.
+
-1. Define a Portlet setting
-'''''''''''''''''''''''''''
+1. Define portlet settings
+''''''''''''''''''''''''''
-Portlet setting interface are defined in ``interfaces.py``, you can use IPortletSettings or extend the interface
-by adding an additional properties for example:
+Portlet settings interface are defined in ``interfaces.py``, you can use :py:class:`pyams_portal.interfaces.IPortletSettings`
+or extend the interface by adding additional properties for example:
.. code-block:: python
from zope.schema import Text
+ NEW_PORTLET_NAME = 'new.portlet'
+
class INewPortletSettings(IPortletSettings):
comment = Text(title=_("Comment"),
- required=True,
- default=True)
+ required=True)
-PortletSetting component does what IPortletSettings describes. This is usually referred to as the implementation
-of IPortletSettings.
+
+A :py:class:`pyams_portal.portlet.PortletSettings` persistent subclass then implements what IPortletSettings describes:
.. code-block:: python
- @implementer(IPortletSettings)
- class ImagePortletSettings(PortletSettings):
- """Image portlet settings"""
-
- _image = FileProperty(IImagePortletSettings['image'])
+ @implementer(INewPortletSettings)
+ class NewPortletSettings(PortletSettings):
+ """Portlet settings"""
- @property
- def image(self):
- return self._image
-
- @image.setter
- def image(self, value):
- self._image = value
- if (value is not None) and (value is not DELETED_FILE):
- alsoProvides(self._image, IResponsiveImage)
-
+ comment = FieldProperty(INewPortletSettings['comment'])
2. Create Portlet
'''''''''''''''''
-The Porltet component is a utility, it implement the IPortlet interface and it registered by the portlet_config adapter
-
-To register a new portlet you must specify the settings_class associated
+The Portlet component is a utility, which implements the :py:class:`pyams_portal.interfaces.IPortlet` interface and is
+registered by the :py:func:`pyams_portal.portlet.portlet_config` decorator;
.. code-block:: python
@@ -65,51 +57,111 @@
class ImagePortlet(Portlet):
"""Image portlet"""
- name = IMAGE_PORTLET_NAME
- label = _("Image")
+ name = NEW_PORTLET_NAME
+ label = _("New portlet")
toolbar_image = None
toolbar_css_class = 'fa fa-fw fa-2x fa-picture-o'
- settings_class = ImagePortletSettings
+ settings_class = NewPortletSettings
-
-4. Create HTML template
-'''''''''''''''''''''''
+Where:
+ - **permission**: permission required to display this portlet content
+ - **name**: internal name given to this portlet. This name must be unique between all portlets, so using your own
+ namespace into this name is generally a good option!
+ - **label**: user label given to this portlet
+ - **toolbar_image**: URL of an image used to display portlet button into ZMI toolbar, if any
+ - **toolbar_css_class**: CSS class used to display portlet button into ZMI toolbar, if any
+ - **settings_class**: class used to store portlet settings.
-.. code-block:: genshi
+3. Create portlet settings edit form
+''''''''''''''''''''''''''''''''''''
+
+Portlet settings have to be updated through management interface via a :py:class:`pyams_portal.zmi.portlet.PortletSettingsEditor`
+subform:
- <span>${view.settings.comment}</span>
+.. code-block:: python
+
+ @pagelet_config(name='properties.html', context=INewPortletSettings, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+ class NewPortletSettingsEditor(PortletSettingsEditor):
+ """New portlet settings editor"""
+
+ settings = INewPortletSettings
+ @adapter_config(name='properties.json', context=(INewPortletSettings, IPyAMSLayer), provides=IPagelet)
+ class NewPortletSettingsAJAXEditor(AJAXEditForm, NewPortletSettingsEditor):
+ """New portlet settings editor, JSON renderer"""
-5. Renderer
-'''''''''''
+
+4. Previewing portlet content
+'''''''''''''''''''''''''''''
+
+A *previewer* is used into ZMI to display portlet content into portal template definition page:
.. code-block:: python
- @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, IImagePortletSettings), provides=IPortletRenderer)
- @template_config(template='image.pt', layer=IPyAMSLayer)
- class ImagePortletRenderer(PortletRenderer):
- """Image portlet renderer"""
-
- label = _("Responsive image renderer")
+ @adapter_config(context=(Interface, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletPreviewer)
+ @template_config(template='my-portlet-preview.pt', layer=IPyAMSLayer)
+ class NewPortletPreviewer(PortletPreviewer):
+ """New portlet previewer"""
+The previewer template is a Chameleon template:
-6. Zmi integration module
-'''''''''''''''''''''''''
+.. code-block:: genshi
+
+ <tal:var define="settings view.settings">
+ <tal:if condition="settings.visible">
+ <div tal:content="settings.comment">Comment</div>
+ </tal:if>
+ <tal:if condition="not settings.visible">
+ <div class="text-center padding-y-5">
+ <span class="fa-stack fa-lg">
+ <i class="fa fa-eye fa-stack-1x"></i>
+ <i class="fa fa-ban fa-stack-2x text-danger"></i>
+ </span>
+ </div>
+ </tal:if>
+ </tal:var>
+
+Here we check if portlet is visible or not to display a small icon when hidden; otherwise we display entered comment.
+
+
+5. Rendering portlet content
+''''''''''''''''''''''''''''
+
+A *renderer* is used to display portlet content into rendered page content:
.. code-block:: python
- @pagelet_config(name='properties.html', context=IImagePortletSettings, request_type=IPyAMSLayer,
- permission=VIEW_SYSTEM_PERMISSION)
- class ImagePortletSettingsEditor(PortletSettingsEditor):
- """Image portlet settings editor"""
+ @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletRenderer)
+ @template_config(template='my-portlet-render.pt', layer=IPyAMSLayer)
+ class NewPortletRenderer(PortletRenderer):
+ """New portlet renderer"""
- settings = IImagePortletSettings
+ label = _("Default comment renderer")
+Each renderer template is also a Chameleon template:
+.. code-block:: genshi
+
+ <div class="comment" tal:content="view.settings.comment">Comment</div>
+
+
+This is the configuration of a *default* renderer defined for this portlet; you can provide several renderers for a
+given portlet by given distinct names to the adapters:
+
+.. code-block:: python
+
+ @adapter_config(name='another-renderer',
+ context=(IPortalContext, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletRenderer)
+ @template_config(template='my-portlet-render-2.pt', layer=IPyAMSLayer)
+ class AnotherNewPortletRenderer(PortletRenderer):
+ """Another new portlet renderer"""
+
+ label = _("Another comment renderer")
--- a/src/source/appinstall.rst Wed May 16 12:00:26 2018 +0200
+++ b/src/source/appinstall.rst Wed May 16 14:06:43 2018 +0200
@@ -242,7 +242,3 @@
This process requires that every package is correctly included into *pyramid.includes* directive from selected
configuration file.
-
-
-
-
--- a/src/source/appmanage.rst Wed May 16 12:00:26 2018 +0200
+++ b/src/source/appmanage.rst Wed May 16 14:06:43 2018 +0200
@@ -16,7 +16,6 @@
Local registry utilities
''''''''''''''''''''''''
-
One of PyAMS pre-requisites is to use the ZODB, at least to store the site root application,
it's configuration and a set of local utilities.
@@ -29,27 +28,38 @@
to delete an index before recreating it by running the database upgrade script another time (see :ref:`scripts`).
**Internal IDs** utility:
- List of unique identifier used to localise and access easily to a resource or object declared in zo database.
+ The catalog object doesn't store direct references to objects, but their internal IDs which are generated by this
+ utility.
**Language negotiator**:
- Allows the management of several languages for different contents
+ As a web site or application can be localized, this utility allows you to define priorities between language
+ definition options (between *user session*, *browser* end *server*), and to define which languages are available
+ to your users (which is particularly important when managing potentially multi-lingual contents).
+
+ .. tip::
+ Static texts like those displayed into PyAMS management interface are always translated to the language defined
+ into browser language, if available.
**Portal templates** container:
- Allows you to define and save, one or more reuse template.
- These templates can be shared with the entire application for build new site.
+ Portal templates are used to define *presentation templates* based on *portlets* (see :ref:`pyams_portal`). You can
+ create *local* templates, or create *shared templates* into this utility which can then be reused into several
+ places in your web site.
**Security manager**:
- Manage role and permission grant to a user
+ This utility is used to define authentication sources which will be available to authenticate your users.
+ :ref:`pyams_security` package provides several authentication modules (like local users, or via OAuth/OAuth2
+ providers); :ref:`pyams_ldap` add authentication plug-in via an LDAP directory.
**Sequential IDs** utility:
-
+ This utility is used to assign simple sequential IDs to site contents (like sites, news, topics and more); these
+ IDs are simple to identify a given content; several versions of a given content handle by workflow share the same
+ sequential ID.
**Server timezone** utility:
- Setup the timezone server
+ Define the timezone server to display date and time accordingly.
**User profiles** container:
-
-
+ This utility is used to store information associated to principals through their user profile.
Optional utilities can also include:
--- a/src/source/plugins.rst Wed May 16 12:00:26 2018 +0200
+++ b/src/source/plugins.rst Wed May 16 14:06:43 2018 +0200
@@ -1,16 +1,16 @@
.. _plugins:
PyAMS additional features and services
-++++++++++++++++++++++++++++++++++++++
+======================================
-Elasticsearch 5.4
-=================
+Elasticsearch
++++++++++++++
-At first you need to install ElasticSearch (ES), currently PyAMS is compatible with the version 5.4, the Ingest attachment
+At first you need to install ElasticSearch (ES); PyAMS is actually compatible with version 5.4. The Ingest attachment
plug-in is also required to handle attachments correctly.
-Visit https://www.elastic.co/ to learn how to install Elasticsearch Server, and how install `ingest-attachment` plug-in
+Visit https://www.elastic.co/ to learn how to install Elasticsearch Server and `ingest-attachment` plug-in
.. tip:: Documentation for installing ElasticSearch 5.4
@@ -19,7 +19,8 @@
- https://www.elastic.co/guide/en/elasticsearch/plugins/5.4/ingest-attachment.html
-After ElasticSearch installation, following steps describe how to configure ES with PyAMS;
+After Elasticsearch installation, following steps describe how to configure ES with PyAMS.
+
Initializing Elasticsearch index
--------------------------------
@@ -28,30 +29,48 @@
Elasticsearch integration is defined through the *PyAMS_content_es* package.
-1. Enable Service:
-''''''''''''''''''
+1. Enable service
+'''''''''''''''''
-In Pyramid INI application file *(etc/development.ini)*:
+In Pyramid INI application files (*etc/development.ini* and *etc/production.ini*):
-.. code-block:: bash
+.. code-block:: ini
- # ElasticSearch settings
+ # Elasticsearch server settings
elastic.server = http://127.0.0.1:9200
elastic.index = pyams
-.. code-block:: bash
+Where:
+ - **elastic.server**: address of Elasticsearch server; you can include authentication arguments in the form
+ *http://login:password@w.x.y.z:9200*
+ - **elastic.index**: name of Elasticsearch index.
+
- # PyAMS content elasticsearch index settings
+On startup, main PyAMS application process can start in *indexer* process which will handle indexing requests in
+asynchronous mode; this process settings are defined like this:
+
+.. code-block:: ini
+
+ # PyAMS content Elasticsearch indexer process settings
pyams_content.es.tcp_handler = 127.0.0.1:5557
pyams_content.es.start_handler = false
pyams_content.es.allow_auth = admin:admin
pyams_content.es.allow_clients = 127.0.0.1
+Where:
+ - **pyams_content.es.tcp_handler**: IP address and listening port of PyAMS indexer process
+ - **pyams_content.es.start_handler**: if *true*, the indexer process is started on PyAMS startup; otherwise (typically
+ in a cluster configuration), the process is supposed to be started from another *master* server
+ - **pyams_content.es.allow_auth**: login and password to be used to connect to indexer process (settings are defined
+ in the same way on indexer process and on all it's clients)
+ - **pyams_content.es.allow_clients**: list of IP addresses allowed to connect to indexer process.
-2. Initialize Elasticsearch Database:
-'''''''''''''''''''''''''''''''''''''
-Configuration files for attachment pipeline, index settings and mappings are available `pyams_content_es` package or in PyAMS installation folder:
+2. Initialize Elasticsearch database
+''''''''''''''''''''''''''''''''''''
+
+Configuration files for attachment pipeline, index and mappings settings are available into `pyams_content_es` source
+package or in PyAMS installation folder:
.. code-block:: bash
@@ -60,7 +79,7 @@
(env) $ curl --noproxy localhost -XPUT http://localhost:9200/_ingest/pipeline/attachment -d @attachment-pipeline.json
-With ``elastic.index = pyams`` defined as Elasticsearch index name : *"http://localhost:9200/pyams"* :
+And with ``elastic.index = pyams`` defined as Elasticsearch index name: *"http://localhost:9200/pyams"*:
.. code-block:: shell
@@ -73,13 +92,14 @@
(env) $ curl -XPUT http://localhost:9200/pyams/WfBlogPost/_mapping -d @mappings/WfBlogPost.json
-*Troubleshooting*: If you have a 406 error try to add ``-H 'Content-Type: application/json'`` in curl option
+*Troubleshooting*: If you have a 406 error try to add ``-H 'Content-Type: application/json'`` in Curl command lines.
-3. Create or update index:
-''''''''''''''''''''''''''
+3. Update index contents
+''''''''''''''''''''''''
-You have to Update ElasticSearch indexes with all database contents with ``pymas_es_index``. From a shell:
+If your ZODB database already store contents, you can update ElasticSearch indexes with all these contents with
+``pymas_es_index`` command line script. From a shell:
.. code-block:: bash
@@ -87,29 +107,25 @@
--------------------------------
+Natural Language Toolkit - NLTK
++++++++++++++++++++++++++++++++
-Natural Language Toolkit - NLTK
-===============================
-
-
-PyAMS enjoy the NLTK features through the *PyAMS_calalog*
+PyAMS is using NLTK features through the *PyAMS_calalog*.
.. seealso::
Visit https://www.nltk.org/ to learn more about NLTK
-
-Initializing NLTK (Natural Language Toolkit)
+Initializing NLTK (Natural Language ToolKit)
--------------------------------------------
-Some NLTK Collections like **tokenizers** and **stopwords** utilities are used to index fulltext contents
-elements. You can enhanced NTKL indexation according to your own needs. This package requires downloading and
+Some NLTK collections like **tokenizers** and **stopwords** utilities are used to index fulltext contents
+elements. You can enhance NLTK indexation according to your own needs. This package requires downloading and
configuration of several elements which are done as follow:
-*1. Run the Python shell with PyAMS environment:*
+*1. Run the Python shell into PyAMS environment:*
.. code-block:: bash
@@ -132,7 +148,7 @@
Pyramid application), '*/usr/share/nltk_data*', '*/usr/local/share/nltk_data*', '*/usr/lib/nltk_data*' and
'*/usr/local/lib/nltk_data*'
- Please check if you have permission to write to this directory
+ Please check if you have permission to write to this directory!
.. code-block:: shell
@@ -190,4 +206,4 @@
.. tip::
- The full list of NTLK Collection are displayable with the ``l) list`` option
+ The full list of NTLK Collection can be displayed with the ``l) list`` option.