--- a/src/pyams_utils/attr.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/attr.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,6 +10,13 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.attr module
+
+This module provides an :ref:`ITraversable` adapter which can be used to get access to an object's
+attribute from a browser URL.
+This adapter is actually used to get access to 'file' attributes in PyAMS_file package.
+"""
+
__docformat__ = 'restructuredtext'
from pyramid.exceptions import NotFound
@@ -28,7 +35,7 @@
/path/to/object/++attr++name
- Where *name* is the name of the requested attribute
+ Where *name* is the name of the requested attribute.
"""
def traverse(self, name, furtherpath=None):
--- a/src/pyams_utils/cache.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/cache.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,20 +10,26 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.cache module
+
+This module provides a small set of adapters which can be used to provide a "cache key" value
+to any kind of object.
+
+The goal of such a cache key value is to provide a string representation, as stable as possible,
+of a given object; this string can be used as a cache key, but also to define an object ID inside
+an HTML page.
+A TALES helper extension is also provided to get an object's cache key from a Chameleon template.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
+from persistent.interfaces import IPersistent
+from zope.interface import Interface
-# import interfaces
-from persistent.interfaces import IPersistent
+from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
from pyams_utils.interfaces import ICacheKeyValue
from pyams_utils.interfaces.tales import ITALESExtension
-# import packages
-from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
-from zope.interface import Interface
-
@adapter_config(context=object, provides=ICacheKeyValue)
def object_cache_key_adapter(obj):
--- a/src/pyams_utils/container.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/container.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,22 +10,22 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.container module
+
+This module provides several classes, adapters and functions about containers.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
-
-# import interfaces
-from zope.container.interfaces import IContainer, IContained
+from BTrees.OOBTree import OOBTree
+from persistent.list import PersistentList
+from pyramid.threadlocal import get_current_registry
+from zope.container.interfaces import IContained, IContainer
+from zope.container.ordered import OrderedContainer
from zope.lifecycleevent.interfaces import IObjectMovedEvent
from zope.location.interfaces import ISublocations
-# import packages
-from BTrees.OOBTree import OOBTree
-from persistent.list import PersistentList
-from pyams_utils.adapter import adapter_config, ContextAdapter
-from pyramid.threadlocal import get_current_registry
-from zope.container.ordered import OrderedContainer
+from pyams_utils.adapter import ContextAdapter, adapter_config
class BTreeOrderedContainer(OrderedContainer):
--- a/src/pyams_utils/context.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/context.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,24 +10,26 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
-
+"""PyAMS_utils.context module
-# import standard library
+This module provides a "context" selector which can be used as Pyramid's subscriber
+predicate. Matching argument can be a class or an interface: for subscriber to be actually called,
+subscriber's argument should inherit from it (if it's a class) or implement it (if it's an
+interface).
+"""
-# import interfaces
-
-# import packages
+__docformat__ = 'restructuredtext'
class ContextSelector(object):
"""Interface based context selector
- This selector can be used as a subscriber predicate to define
- an interface that the context must support for the event to be applied::
+ This selector can be used as a predicate to define a class or an interface that the context
+ must inherit from or implement for the subscriber to be called::
.. code-block:: python
+ from zope.lifecycleevent.interfaces import IObjectModifiedEvent
from pyams_utils.interfaces.site import ISiteRoot
@subscriber(IObjectModifiedEvent, context_selector=ISiteRoot)
@@ -41,6 +43,7 @@
self.interfaces = ifaces
def text(self):
+ """Return selector """
return 'context_selector = %s' % str(self.interfaces)
phash = text
--- a/src/pyams_utils/data.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/data.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,7 +10,7 @@
# FOR A PARTICULAR PURPOSE.
#
-"""Object data API module
+"""PyAMS_utils.data module
The *IObjectData* interface is a generic interface which can be used to assign custom data to any object.
This object data may be any object which can be serialized to JSON, and assigned to any HTML *data* attribute.
--- a/src/pyams_utils/date.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/date.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,22 +10,24 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.date module
+
+This module provides several functions concerning conversion, parsing and formatting of
+dates and datetimes.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard packages
from datetime import datetime
-# import interfaces
-from pyams_utils.interfaces.tales import ITALESExtension
+from zope.datetime import parseDatetimetz
from zope.dublincore.interfaces import IZopeDublinCore
+from zope.interface import Interface
-# import packages
-from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
+from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
+from pyams_utils.interfaces.tales import ITALESExtension
from pyams_utils.request import check_request
from pyams_utils.timezone import gmtime, tztime
-from zope.datetime import parseDatetimetz
-from zope.interface import Interface
from pyams_utils import _
--- a/src/pyams_utils/decorator.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/decorator.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,17 +10,17 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.decorator module
+
+This module only provides a single decorator, which can be used to mark a function as
+deprecated.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
import functools
import warnings
-# import interfaces
-
-# import packages
-
def deprecated(*msg):
"""This is a decorator which can be used to mark functions as deprecated.
--- a/src/pyams_utils/dict.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/dict.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,20 +10,20 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.dict module
+
+This helper module only contains a single function which can be used to update an input
+dictionary; if given value argument is a boolean 'true' value, given dictionary's key is created
+or updated, otherwise dictionary is left unchanged.
+"""
+
__docformat__ = 'restructuredtext'
-# import standard library
-
-# import interfaces
-
-# import packages
-
-
-def update_dict(input, key, value):
+def update_dict(input_dict, key, value):
"""Update given mapping if input value is a boolean 'true' value
- :param dict input: input dictionary
+ :param dict input_dict: input dictionary
:param key: mapping key
:param value: new value
@@ -51,4 +51,4 @@
{'key1': 'value2'}
"""
if value:
- input[key] = value
+ input_dict[key] = value
--- a/src/pyams_utils/encoding.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/encoding.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,20 +10,20 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.encoding module
+
+This module defines a vocabulary of available encodings, as well as an "encoding" field.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
+from zope.interface import implementer
+from zope.schema import Choice
+from zope.schema.interfaces import IChoice
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
-# import interfaces
-from zope.schema.interfaces import IChoice
-
-# import packages
from pyams_utils.request import check_request
from pyams_utils.vocabulary import vocabulary_config
-from zope.interface import implementer
-from zope.schema import Choice
-from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
from pyams_utils import _
--- a/src/pyams_utils/factory.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/factory.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,7 +10,7 @@
# FOR A PARTICULAR PURPOSE.
#
-"""Objects factory management
+"""PyAMS_utils.factory module
This module provides a decorator and a small set of functions to handle object factories.
--- a/src/pyams_utils/fanstatic.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/fanstatic.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,6 +10,14 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.fanstatic module
+
+This module is a helper module to handle Fanstatic resources.
+
+It includes several TALES extensions which can be used to include resources from a Chameleon
+template, or to get path of a given resources from a template.
+"""
+
__docformat__ = 'restructuredtext'
from fanstatic import Resource
@@ -22,6 +30,7 @@
def render_js(url, defer=False):
+ """Render tag to include Javascript resource"""
return '<script type="text/javascript" src="%s" %s></script>' % (url, 'defer' if defer else '')
@@ -47,6 +56,7 @@
self.resource_type = path.rsplit('.', 1)[1].lower()
def render(self, library_url):
+ """Render resource tag"""
if self.resource_type == 'css':
return render_css(self.relpath)
elif self.resource_type == 'js':
@@ -61,21 +71,26 @@
return '{0}/{1}'.format(res.library_url(resource.library), resource.relpath)
-@adapter_config(name='resource_path', context=(Interface, Interface, Interface), provides=ITALESExtension)
+@adapter_config(name='resource_path', context=(Interface, Interface, Interface),
+ provides=ITALESExtension)
class FanstaticTalesExtension(ContextRequestViewAdapter):
"""tales:resource_path() TALES extension
This TALES extension generates an URL matching a given Fanstatic resource.
- Resource is given as a string made of package name (in dotted form) followed by a colon and by the resource name.
+ Resource is given as a string made of package name (in dotted form) followed by a colon and
+ by the resource name.
For example::
.. code-block:: html
- <div tal:attributes="data-ams-plugin-pyams_content-src extension:resource_path('pyams_content.zmi:pyams_content')" />
+ <div tal:attributes="data-ams-plugin-pyams_content-src
+ extension:resource_path('pyams_content.zmi:pyams_content')" />
"""
- def render(self, resource):
+ @staticmethod
+ def render(resource):
+ """TALES extension rendering method"""
library, resource_name = resource.split(':')
resolver = DottedNameResolver()
module = resolver.maybe_resolve(library)
@@ -83,13 +98,15 @@
return get_resource_path(resource)
-@adapter_config(name='need_resource', context=(Interface, Interface, Interface), provides=ITALESExtension)
+@adapter_config(name='need_resource', context=(Interface, Interface, Interface),
+ provides=ITALESExtension)
class FanstaticNeededResourceTalesExtension(ContextRequestViewAdapter):
"""tales:need_resource() TALES extension
This extension generates a call to Fanstatic resource.need() function to include given resource
into generated HTML code.
- Resource is given as a string made of package name (in dotted form) followed by a colon and by the resource name.
+ Resource is given as a string made of package name (in dotted form) followed by a colon and by
+ the resource name.
For example::
@@ -98,7 +115,9 @@
<tal:var define="tales:need_resource('pyams_content.zmi:pyams_content')" />
"""
- def render(self, resource):
+ @staticmethod
+ def render(resource):
+ """TALES extension rendering method"""
library, resource_name = resource.split(':')
resolver = DottedNameResolver()
module = resolver.maybe_resolve(library)
--- a/src/pyams_utils/list.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/list.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,6 +10,16 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils list module
+
+This module is dedicated to lists and iterators management. It provides function to extract
+unique values from a list or iterator in their original order, or to iterate over an iterator in
+random order; it also provides a "boolean_iter" function (usable as TALES extension) to check if
+an iterator returns at least one value, without consuming this iterator (the function returns a
+tuple containing a boolean value to specify if iterator is empty or not, and the original
+iterator).
+"""
+
__docformat__ = 'restructuredtext'
from itertools import filterfalse, tee
--- a/src/pyams_utils/session.py Tue Jun 18 16:53:34 2019 +0200
+++ b/src/pyams_utils/session.py Wed Jun 26 10:39:34 2019 +0200
@@ -10,52 +10,19 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils session module
+
+This helper module is used to add a "session_property" method decorator, which can be used to
+store method result into user's session.
+
+It also adds to function to get and set session data.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
-
-# import interfaces
-
-# import packages
from pyams_utils.request import check_request
-_marker = object()
-
-
-def session_property(app, key=None, prefix=None):
- """Define a method decorator used to store result into request's session
-
- If no request is currently running, a new one is created.
-
- :param str app: application identifier used to prefix session keys
- :param str key: session's value key; if *None*, the key will be the method's object; if *key* is a callable
- object, il will be called to get the actual session key
- :param prefix: str; prefix to use for session key; if *None*, the prefix will be the property name
- """
-
- def session_decorator(func):
-
- def wrapper(obj, app, key, *args, **kwargs):
- request = check_request()
- if callable(key):
- key = key(obj, *args, **kwargs)
- if not key:
- key = '{1}::{0!r}'.format(obj, prefix or func.__name__)
- data = get_session_data(request, app, key, _marker)
- if data is _marker:
- data = func
- if callable(data):
- data = data(obj, *args, **kwargs)
- set_session_data(request, app, key, data)
- return data
-
- return lambda x, *args, **kwargs: wrapper(x, app, key, *args, **kwargs)
-
- return session_decorator
-
-
def get_session_data(request, app, key, default=None):
"""Get data associated with current user session
@@ -97,3 +64,39 @@
"""
session = request.session
session['{0}::{1}'.format(app, key)] = value
+
+
+_marker = object()
+
+
+def session_property(app, key=None, prefix=None):
+ """Define a method decorator used to store result into request's session
+
+ If no request is currently running, a new one is created.
+
+ :param str app: application identifier used to prefix session keys
+ :param str key: session's value key; if *None*, the key will be the method's object; if *key*
+ is a callable object, il will be called to get the actual session key
+ :param prefix: str; prefix to use for session key; if *None*, the prefix will be the property
+ name
+ """
+
+ def session_decorator(func):
+
+ def wrapper(obj, app, key, *args, **kwargs):
+ request = check_request()
+ if callable(key):
+ key = key(obj, *args, **kwargs)
+ if not key:
+ key = '{1}::{0!r}'.format(obj, prefix or func.__name__)
+ data = get_session_data(request, app, key, _marker)
+ if data is _marker:
+ data = func
+ if callable(data):
+ data = data(obj, *args, **kwargs)
+ set_session_data(request, app, key, data)
+ return data
+
+ return lambda x, *args, **kwargs: wrapper(x, app, key, *args, **kwargs)
+
+ return session_decorator