src/pyams_utils/vocabulary.py
changeset 289 c8e21d7dd685
child 292 b338586588ad
equal deleted inserted replaced
-1:000000000000 289:c8e21d7dd685
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard library
       
    17 import logging
       
    18 logger = logging.getLogger('PyAMS (utils)')
       
    19 
       
    20 import venusian
       
    21 
       
    22 # import interfaces
       
    23 from zope.schema.interfaces import IVocabularyFactory
       
    24 
       
    25 # import packages
       
    26 from zope.interface import directlyProvides
       
    27 from zope.schema.vocabulary import getVocabularyRegistry
       
    28 
       
    29 
       
    30 class vocabulary_config:
       
    31     """Class decorator to define a vocabulary
       
    32 
       
    33     :param str name: name of the registered vocabulary
       
    34 
       
    35     This is, for example, how a vocabulary of registered ZEO connections utilities is created:
       
    36 
       
    37     .. code-block:: python
       
    38 
       
    39         from pyams_utils.interfaces.zeo import IZEOConnection
       
    40 
       
    41         from pyams_utils.registry import get_utilities_for
       
    42         from pyams_utils.vocabulary import vocabulary_config
       
    43         from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
       
    44 
       
    45         @vocabulary_config(name='PyAMS ZEO connections')
       
    46         class ZEOConnectionVocabulary(SimpleVocabulary):
       
    47             '''ZEO connections vocabulary'''
       
    48 
       
    49             def __init__(self, context=None):
       
    50                 terms = [SimpleTerm(name, title=util.name) for name, util in get_utilities_for(IZEOConnection)]
       
    51                 super(ZEOConnectionVocabulary, self).__init__(terms)
       
    52 
       
    53     You can then use such a vocabulary in any schema field:
       
    54 
       
    55     .. code-block:: python
       
    56 
       
    57         from zope.interface import Interface
       
    58         from zope.schema import Choice
       
    59 
       
    60         class MySchema(Interface):
       
    61             '''Custom schema interface'''
       
    62 
       
    63             zeo_connection_name = Choice(title='ZEO connection name',
       
    64                                          description='Please select a registered ZEO connection',
       
    65                                          vocabulary='PyAMS ZEO connections',
       
    66                                          required=False)
       
    67     """
       
    68 
       
    69     venusian = venusian
       
    70 
       
    71     def __init__(self, name, **settings):
       
    72         self.name = name
       
    73         self.__dict__.update(settings)
       
    74 
       
    75     def __call__(self, wrapped):
       
    76         settings = self.__dict__.copy()
       
    77         depth = settings.pop('_depth', 0)
       
    78 
       
    79         def callback(context, name, ob):
       
    80             logger.debug('Registering class {0} as vocabulary with name "{1}"'.format(str(ob), self.name))
       
    81             directlyProvides(ob, IVocabularyFactory)
       
    82             getVocabularyRegistry().register(self.name, ob)
       
    83 
       
    84         info = self.venusian.attach(wrapped, callback, category='pyams_vocabulary',
       
    85                                     depth=depth + 1)
       
    86 
       
    87         if info.scope == 'class':
       
    88             # if the decorator was attached to a method in a class, or
       
    89             # otherwise executed at class scope, we need to set an
       
    90             # 'attr' into the settings if one isn't already in there
       
    91             if settings.get('attr') is None:
       
    92                 settings['attr'] = wrapped.__name__
       
    93 
       
    94         settings['_info'] = info.codeinfo  # fbo "action_method"
       
    95         return wrapped