Revision 2ce0636e snf-common/synnefo/util/entry_points.py

b/snf-common/synnefo/util/entry_points.py
1
# Copyright 2011 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
1 34
import sys
2 35
import pkg_resources
3 36
import inspect
37
import types
4 38

  
5 39

  
6
def get_entry_ponts(ns, name):
40
def get_entry_points(ns, name):
7 41
    for entry_point in pkg_resources.iter_entry_points(group=ns):
8 42
        if entry_point.name == name:
9 43
            yield entry_point
10 44

  
11 45

  
12
def extend_settings(ns, module_name):
46
def extend_module(module_name, attrs):
47
    module = sys.modules[module_name]
48
    for k,v in attrs.iteritems():
49
        setattr(module, k, v)
50

  
51

  
52
def entry_point_to_object(ep):
53
    object_or_func = ep.load()
54

  
55
    # user defined entry point is a function
56
    # get the return value
57
    obj = object_or_func
58
    if hasattr(object_or_func, '__call__'):
59
        obj = object_or_func()
60

  
61
    if type(obj) == types.ModuleType:
62
        dct = {}
63
        for k in dir(obj):
64
            if k.startswith("__"):
65
                continue
66
            dct[k] = getattr(obj, k)
67

  
68
        obj = dct
69

  
70
    return obj
71

  
72

  
73
def extend_module_from_entry_point(module_name, ns):
13 74
    """
14
    Extend module from entry_point hooks
75
    Extend a settings module from entry_point hooks
15 76
    """
16
    settings = sys.modules[module_name]
17
    # apps hook
18
    app_entry_points = get_entry_ponts(ns, 'apps')
19
    # settings hook
20
    settings_entry_points = get_entry_ponts(ns, 'settings')
21

  
22
    # extend INSTALLED_APPS setting
23
    NEW_INSTALLED_APPS = list(getattr(settings, 'INSTALLED_APPS', []));
24

  
25
    # if failed to execute app hook as function parse it as string
26
    # synnefo.app:get_additional_apps or app1,app2,app3
27
    for e in app_entry_points:
28
        try:
29
            NEW_INSTALLED_APPS = list(e.load()())
30
        except Exception, ex:
31
            NEW_INSTALLED_APPS = NEW_INSTALLED_APPS + \
32
                    e.module_name.split(",")
33

  
34
    # extend additional settings
35
    # TODO: existing settings logic ??
36
    for e in settings_entry_points:
37
        module = e.load()
38
        for k in dir(module):
39
            if k == k.upper():
40
                setattr(settings, k, getattr(module, k))
41

  
42
    setattr(settings, 'INSTALLED_APPS', NEW_INSTALLED_APPS)
77
    for e in get_entry_points(ns, 'default_settings'):
78
        extend_module(module_name, entry_point_to_object(e))
79

  
80

  
81
def extend_dict_from_entry_point(settings_object, ns, entry_point_name):
82
    for e in get_entry_points(ns, entry_point_name):
83
        settings_object.update(entry_point_to_object(e))
84

  
85
    return settings_object
86

  
87

  
88
def extend_list_from_entry_point(settings_object, ns, entry_point_name,
89
        unique=True):
90
    settings_object = list(settings_object)
91
    for e in get_entry_points(ns, entry_point_name):
92
        obj = entry_point_to_object(e)
93
        for row in obj:
94
            if type(row) == dict and (row.get('before', False) or \
95
                    row.get('after', False)):
96
                if row.get('before', False):
97
                    position = settings_object.index(row.get('before'))
98
                    insert_at = position - 1
99
                else:
100
                    position = settings_object.index(row.get('after'))
101
                    insert_at = position + 1
102

  
103
                if insert_at < 0:
104
                    insert_at = 0
105

  
106
                inserts = row.get('insert', [])
107
                if not type(inserts) == list:
108
                    inserts  = [inserts]
109

  
110
                for entry in inserts:
111
                    if not entry in settings_object:
112
                        settings_object.insert(insert_at, entry)
113
                        insert_at = insert_at + 1
114
            else:
115
                settings_object.append(row)
116

  
117
    return settings_object
118

  
119
def extend_settings(mname, ns):
120
    extend_module_from_entry_point(mname, ns)
121

  
122
def extend_urls(patterns, ns):
123
    for e in get_entry_points(ns, 'urls'):
124
        patterns += e.load()
125

  
126
    return patterns
43 127

  

Also available in: Unified diff