--- a/src/pyams_utils/__init__.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/__init__.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,14 +10,16 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils package
+
+This package provides several small modules dedicated to generic features
+for which dedicated packages are not provided. These features can concern
+date and times management, strings and unicode, lists and dictionaries,
+custom decorators to define several kinds of properties, and so on.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
-
-# import interfaces
-
-# import packages
from zope.schema.fieldproperty import FieldProperty
from pyramid.i18n import TranslationStringFactory
@@ -25,6 +27,7 @@
def get_field_doc(self):
+ """Try to get FieldProperty field docstring from field interface"""
field = self._FieldProperty__field
if field.title and field.description:
return '{0}: {1}'.format(field.title, field.description)
--- a/src/pyams_utils/data.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/data.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,9 +10,9 @@
# FOR A PARTICULAR PURPOSE.
#
-__doc__ = """Object data API module
+"""Object data API module
-The *IObjectData* interface is a generic interface which can be used to assign custom data to nay object.
+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.
It can typically be used to set a *data-ams-data* attribute to objects, which is afterwards converted to
classic *data-* attributes by **MyAMS.js** framework.
@@ -36,19 +36,15 @@
__docformat__ = 'restructuredtext'
-
-# import standard library
import json
-# import interfaces
+from pyramid.interfaces import IRequest
+from zope.interface import Interface
+from zope.publisher.interfaces.browser import IBrowserRequest
+
+from pyams_utils.adapter import ContextAdapter, ContextRequestViewAdapter, adapter_config
from pyams_utils.interfaces.data import IObjectData, IObjectDataRenderer
from pyams_utils.interfaces.tales import ITALESExtension
-from pyramid.interfaces import IRequest
-from zope.publisher.interfaces.browser import IBrowserRequest
-
-# import packages
-from pyams_utils.adapter import ContextAdapter, ContextRequestViewAdapter, adapter_config
-from zope.interface import Interface
@adapter_config(context=IObjectData, provides=IObjectDataRenderer)
--- a/src/pyams_utils/i18n.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/i18n.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,12 +10,15 @@
# FOR A PARTICULAR PURPOSE.
#
+"""I18n module used to get browser language from request"""
+
__docformat__ = 'restructuredtext'
import locale
def normalize_lang(lang):
+ """Normalize input languages string"""
lang = lang.strip().lower()
lang = lang.replace('_', '-')
lang = lang.replace(' ', '')
@@ -36,17 +39,17 @@
accepts = []
for index, lang in enumerate(accept_langs):
- l = lang.split(';', 2)
+ lang_item = lang.split(';', 2)
# If not supplied, quality defaults to 1...
quality = 1.0
- if len(l) == 2:
- q = l[1]
- if q.startswith('q='):
- q = q.split('=', 2)[1]
+ if len(lang_item) == 2:
+ qual = lang_item[1]
+ if qual.startswith('q='):
+ qual = qual.split('=', 2)[1]
try:
- quality = float(q)
+ quality = float(qual)
except ValueError:
# malformed quality value, skip it.
continue
@@ -58,7 +61,7 @@
# defined, and items with quality defined as 1.
quality = 1.9 - (0.001 * index)
- accepts.append((quality, l[0]))
+ accepts.append((quality, lang_item[0]))
# Filter langs with q=0, which means
# unwanted lang according to the spec
@@ -68,7 +71,7 @@
accepts.sort()
accepts.reverse()
- return [lang for qual, lang in accepts][0] if accepts else None
+ return [lang for _, lang in accepts][0] if accepts else None
def set_locales(config):
--- a/src/pyams_utils/inherit.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/inherit.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,18 +10,20 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.inherit module
+
+This module is used to manage a generic inheritance between a content and
+it's parent container. It also defines a custom InheritedFieldProperty which
+allows to automatically manage inherited properties.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
-
-from zope.interface import implementer, Interface
+from zope.interface import Interface, implementer
from zope.location import Location
from zope.schema.fieldproperty import FieldProperty
-# import interfaces
from pyams_utils.interfaces.inherit import IInheritInfo
-# import packages
from pyams_utils.traversing import get_parent
from pyams_utils.zodb import volatile_property
@@ -37,32 +39,39 @@
@volatile_property
def parent(self):
+ """Get current parent"""
return get_parent(self.__parent__, self.target_interface, allow_context=False)
@property
def can_inherit(self):
+ """Check if inheritance is possible"""
return self.target_interface.providedBy(self.parent)
@property
def inherit(self):
+ """Check if inheritance is possible and activated"""
return self._inherit if self.can_inherit else False
@inherit.setter
def inherit(self, value):
+ """Activate inheritance"""
if self.can_inherit:
self._inherit = value
del self.parent
@property
def no_inherit(self):
+ """Inverted boolean value to check if inheritance is possible and activated"""
return not bool(self.inherit)
@no_inherit.setter
def no_inherit(self, value):
+ """Inverted inheritance setter"""
self.inherit = not bool(value)
@property
def inherit_from(self):
+ """Get current parent from which we inherit"""
if not self.inherit:
return self
parent = self.parent
--- a/src/pyams_utils/interfaces/__init__.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/interfaces/__init__.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,18 +10,18 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils interfaces module
+
+This module defines several generic constants and interfaces.
+It is also used to provide translations to common zope.schema exceptions.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
-
-# import interfaces
-from zope.schema.interfaces import WrongContainedType, NotUnique, SchemaNotFullyImplemented, SchemaNotProvided, \
- InvalidURI, InvalidId, InvalidDottedName, Unbound, RequiredMissing, WrongType, TooBig, TooSmall, TooLong, \
- TooShort, InvalidValue, ConstraintNotSatisfied, NotAContainer, NotAnIterator
-
-# import packages
from zope.interface import Interface
+from zope.schema.interfaces import ConstraintNotSatisfied, InvalidDottedName, InvalidId, InvalidURI, InvalidValue, \
+ NotAContainer, NotAnIterator, NotUnique, RequiredMissing, SchemaNotFullyImplemented, SchemaNotProvided, TooBig, \
+ TooLong, TooShort, TooSmall, Unbound, WrongContainedType, WrongType
from pyams_utils import _
@@ -56,7 +56,7 @@
#
FORBIDDEN_PERMISSION = 'system.forbidden'
-'''Custom permission which is never granted to any user'''
+'''Custom permission which is never granted to any user, even system manager'''
PUBLIC_PERMISSION = 'public'
'''Public permission which is granted to every principal'''
--- a/src/pyams_utils/interfaces/data.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/interfaces/data.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,20 +10,25 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils data interface
+
+This interface allows to define custom "data" properties on any object providing
+IObjectData interface. These properties are used to render "data" attributes into
+HTML code.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
-
-# import interfaces
-
-# import packages
from zope.interface import Interface
from zope.schema import Dict
class IObjectData(Interface):
- """Object data generic interface"""
+ """Object data generic interface
+
+ Objects providing this interface can create an 'object_data' dictionary attribute which
+ will be used to create matching HTML data attributes.
+ """
object_data = Dict(title="Data associated with this object",
required=False)
--- a/src/pyams_utils/lock.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/lock.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,16 +10,17 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.lock module
+
+This module is use to manage shared locks; these locks can be used accross several
+processes; the lock relies on a shared value stored info Beaker's cache.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
import time
from threading import local
-# import interfaces
-
-# import packages
from beaker import cache
@@ -89,9 +90,11 @@
"""
def lock_decorator(func):
+
def wrapper(*args, **kwargs):
with CacheLock(name, wait):
return func(*args, **kwargs)
+
return wrapper
return lock_decorator
--- a/src/pyams_utils/tests/__init__.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/tests/__init__.py Fri Jun 14 12:41:06 2019 +0200
@@ -1,1 +1,31 @@
+# -*- coding: utf-8 -*- ######################################################
+##############################################################################
+#
+# Copyright (c) 2008-2010 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+Generic Test case for ztfy.utils doctest
+"""
+__docformat__ = 'restructuredtext'
+
+import os
+import sys
+
+
+def get_package_dir(input):
+ """Get package directory"""
+
+ package_dir = os.path.split(input)[0]
+ if package_dir not in sys.path:
+ sys.path.append(package_dir)
+ return package_dir
--- a/src/pyams_utils/tests/test_utilsdocs.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/tests/test_utilsdocs.py Fri Jun 14 12:41:06 2019 +0200
@@ -1,4 +1,4 @@
-### -*- coding: utf-8 -*- ####################################################
+# -*- coding: utf-8 -*- ######################################################
##############################################################################
#
# Copyright (c) 2008-2010 Thierry Florac <tflorac AT ulthar.net>
@@ -16,15 +16,18 @@
"""
Generic Test case for ztfy.utils doctest
"""
+
__docformat__ = 'restructuredtext'
+import doctest
+import os
import unittest
-import doctest
-import sys
-import os
+
+from pyams_utils.tests import get_package_dir
-current_dir = os.path.dirname(__file__)
+CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
+
def doc_suite(test_dir, setUp=None, tearDown=None, globs=None):
"""Returns a test suite, based on doctests found in /doctest."""
@@ -35,10 +38,7 @@
flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_ONLY_FIRST_FAILURE)
- package_dir = os.path.split(test_dir)[0]
- if package_dir not in sys.path:
- sys.path.append(package_dir)
-
+ package_dir = get_package_dir(test_dir)
doctest_dir = os.path.join(package_dir, 'doctests')
# filtering files on extension
@@ -53,9 +53,11 @@
return unittest.TestSuite(suite)
+
def test_suite():
"""returns the test suite"""
- return doc_suite(current_dir)
+ return doc_suite(CURRENT_DIR)
+
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
--- a/src/pyams_utils/tests/test_utilsdocstrings.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/tests/test_utilsdocstrings.py Fri Jun 14 12:41:06 2019 +0200
@@ -1,4 +1,4 @@
-### -*- coding: utf-8 -*- ####################################################
+# -*- coding: utf-8 -*- ######################################################
##############################################################################
#
# Copyright (c) 2008-2010 Thierry Florac <tflorac AT ulthar.net>
@@ -16,15 +16,18 @@
"""
Generic Test case for pyams_utils doc strings
"""
+
__docformat__ = 'restructuredtext'
+import doctest
+import os
import unittest
-import doctest
-import sys
-import os
+
+from pyams_utils.tests import get_package_dir
-current_dir = os.path.abspath(os.path.dirname(__file__))
+CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
+
def doc_suite(test_dir, globs=None):
"""Returns a test suite, based on doc tests strings found in /*.py"""
@@ -35,9 +38,7 @@
flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_ONLY_FIRST_FAILURE)
- package_dir = os.path.split(test_dir)[0]
- if package_dir not in sys.path:
- sys.path.append(package_dir)
+ package_dir = get_package_dir(test_dir)
# filtering files on extension
docs = [doc for doc in
@@ -57,9 +58,11 @@
return unittest.TestSuite(suite)
+
def test_suite():
"""returns the test suite"""
- return doc_suite(current_dir)
+ return doc_suite(CURRENT_DIR)
+
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
--- a/src/pyams_utils/vocabulary.py Wed Jun 12 20:06:45 2019 +0200
+++ b/src/pyams_utils/vocabulary.py Fri Jun 14 12:41:06 2019 +0200
@@ -10,21 +10,22 @@
# FOR A PARTICULAR PURPOSE.
#
+"""PyAMS_utils.vocabulary module
+
+This module is used to handle vocabularies.
+"""
+
__docformat__ = 'restructuredtext'
-
-# import standard library
import logging
-logger = logging.getLogger('PyAMS (utils)')
import venusian
-
-# import interfaces
+from zope.interface import directlyProvides
from zope.schema.interfaces import IVocabularyFactory
+from zope.schema.vocabulary import getVocabularyRegistry
-# import packages
-from zope.interface import directlyProvides
-from zope.schema.vocabulary import getVocabularyRegistry
+
+logger = logging.getLogger('PyAMS (utils)')
class vocabulary_config: