source: products/quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/interfacemanager.py @ 1539

Last change on this file since 1539 was 1539, checked in by mylan, 14 years ago

Restrict export interfaces by object to directly provided only

  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
1import os.path
2from xml.dom import minidom
3
4from zope.interface import classProvides, implements
5from zope.interface import directlyProvidedBy, alsoProvides
6from zope.annotation.interfaces import IAnnotations
7
8from Products.CMFCore import utils
9
10from collective.transmogrifier.interfaces import ISection, ISectionBlueprint
11from collective.transmogrifier.utils import defaultMatcher
12
13from quintagroup.transmogrifier.logger import VALIDATIONKEY
14
15class InterfacesExporterSection(object):
16    classProvides(ISectionBlueprint)
17    implements(ISection)
18
19    def __init__(self, transmogrifier, name, options, previous):
20        self.previous = previous
21        self.context = transmogrifier.context
22
23        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
24        self.fileskey = options.get('files-key', '_files').strip()
25
26        self.excludekey = defaultMatcher(options, 'exclude-key', name, 'excluded_interfaces')
27        self.exclude = filter(None, [i.strip() for i in
28                              options.get('exclude', '').splitlines()])
29
30        self.includekey = defaultMatcher(options, 'include-key', name, 'included_interfaces')
31        self.include = filter(None, [i.strip() for i in
32                              options.get('include', '').splitlines()])
33
34        self.doc = minidom.Document()
35
36    def __iter__(self):
37        for item in self.previous:
38            pathkey = self.pathkey(*item.keys())[0]
39
40            if not pathkey:
41                yield item; continue
42
43            path = item[pathkey]
44            obj = self.context.unrestrictedTraverse(path, None)
45            if obj is None:         # path doesn't exist
46                yield item; continue
47
48            ifaces = self.getInterfaces(obj)
49
50            if ifaces:
51                files = item.setdefault('_files', {})
52                item[self.fileskey]['interfaces'] = {
53                    'name': '.interfaces.xml',
54                    'data': ifaces,
55                }
56
57            yield item
58
59    def getInterfaces(self, obj):
60        if not obj:
61            return None
62
63        doc = self.doc
64        root = doc.createElement('interfaces')
65
66        ifaces = [i.__identifier__ for i in directlyProvidedBy(obj)]
67        if self.include:
68            ifaces = filter(lambda i: i in self.include, ifaces)
69        elif self.exclude:
70            ifaces = filter(lambda i: not i in self.include, ifaces)
71
72        if ifaces == []:
73            return None
74
75        for iface in ifaces:
76            # create record
77            record = doc.createElement('record')
78
79            # add object interface
80            text = doc.createTextNode(iface)
81            record.appendChild(text)
82
83            root.appendChild(record)
84
85        doc.appendChild(root)
86
87        try:
88            data = doc.toprettyxml(indent='  ', encoding='utf-8')
89        except UnicodeDecodeError, e:
90            # all comments are strings encoded in 'utf-8' and they will properly
91            # saved in xml file, but if we explicitly give 'utf-8' encoding
92            # UnicodeDecodeError will be raised when they have non-ascii chars
93            data = doc.toprettyxml(indent='  ')
94
95        doc.unlink()
96        return data
97
98
99class InterfacesImporterSection(object):
100    classProvides(ISectionBlueprint)
101    implements(ISection)
102
103    def __init__(self, transmogrifier, name, options, previous):
104        self.previous = previous
105        self.context = transmogrifier.context
106
107        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
108        self.fileskey = defaultMatcher(options, 'files-key', name, 'files')
109
110        self.excludekey = defaultMatcher(options, 'exclude-key', name, 'excluded_properties')
111        self.exclude = filter(None, [i.strip() for i in
112                            options.get('exclude', '').splitlines()])
113
114        self.includekey = defaultMatcher(options, 'include-key', name, 'included_properties')
115        self.include = filter(None, [i.strip() for i in
116                              options.get('include', '').splitlines()])
117
118        self.catalog = utils.getToolByName(self.context, 'portal_catalog')
119
120    def __iter__(self):
121
122        for item in self.previous:
123            pathkey = self.pathkey(*item.keys())[0]
124            fileskey = self.fileskey(*item.keys())[0]
125
126            if not (pathkey and fileskey):
127                yield item; continue
128            if 'interfaces' not in item[fileskey]:
129                yield item; continue
130
131            path = item[pathkey]
132            obj = self.context.unrestrictedTraverse(path, None)
133            if obj is None:         # path doesn't exist
134                yield item; continue
135
136            ifaces = self.extractIfaces(obj, item[fileskey]['interfaces']['data'])
137
138            if ifaces == []:         # no interfaces
139                yield item; continue
140
141            alsoProvides(obj, *ifaces)
142
143            yield item
144
145        self.catalog.reindexIndex('object_provides', None)
146
147
148    def extractIfaces(self, obj, data):
149        doc = minidom.parseString(data)
150        ifaces = []
151        for record in doc.getElementsByTagName('record'):
152            iface_name = str(record.firstChild.nodeValue.strip())
153
154            # filter interfaces
155            if self.include and not iface_name in self.include:
156                continue
157            elif self.exclude and iface_name in self.exclude:
158                continue
159               
160            iface = self.getIfaceById(iface_name)
161            if iface:
162                ifaces.append(iface)
163        return ifaces
164
165
166    def getIfaceById(self, name):
167        components = name.split('.'); components.reverse()
168        try:
169            obj = __import__(components.pop())
170        except (ImportError, ValueError):
171            return None
172        while obj is not None and components:
173            obj = getattr(obj, components.pop(), None)
174        return obj
175
Note: See TracBrowser for help on using the repository browser.