|
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
3 # |
|
4 # This file is part of CubicWeb. |
|
5 # |
|
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
|
7 # terms of the GNU Lesser General Public License as published by the Free |
|
8 # Software Foundation, either version 2.1 of the License, or (at your option) |
|
9 # any later version. |
|
10 # |
|
11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
|
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
|
14 # details. |
|
15 # |
|
16 # You should have received a copy of the GNU Lesser General Public License along |
|
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
|
18 """data source related entities""" |
|
19 |
|
20 __docformat__ = "restructuredtext en" |
|
21 |
|
22 import re |
|
23 from socket import gethostname |
|
24 |
|
25 from logilab.common.textutils import text_to_dict |
|
26 from logilab.common.configuration import OptionError |
|
27 |
|
28 from cubicweb import ValidationError |
|
29 from cubicweb.entities import AnyEntity, fetch_config |
|
30 |
|
31 class _CWSourceCfgMixIn(object): |
|
32 @property |
|
33 def dictconfig(self): |
|
34 return self.config and text_to_dict(self.config) or {} |
|
35 |
|
36 def update_config(self, skip_unknown=False, **config): |
|
37 from cubicweb.server import SOURCE_TYPES |
|
38 from cubicweb.server.serverconfig import (SourceConfiguration, |
|
39 generate_source_config) |
|
40 cfg = self.dictconfig |
|
41 cfg.update(config) |
|
42 options = SOURCE_TYPES[self.type].options |
|
43 sconfig = SourceConfiguration(self._cw.vreg.config, options=options) |
|
44 for opt, val in cfg.iteritems(): |
|
45 try: |
|
46 sconfig.set_option(opt, val) |
|
47 except OptionError: |
|
48 if skip_unknown: |
|
49 continue |
|
50 raise |
|
51 cfgstr = unicode(generate_source_config(sconfig), self._cw.encoding) |
|
52 self.set_attributes(config=cfgstr) |
|
53 |
|
54 |
|
55 class CWSource(_CWSourceCfgMixIn, AnyEntity): |
|
56 __regid__ = 'CWSource' |
|
57 fetch_attrs, fetch_order = fetch_config(['name', 'type']) |
|
58 |
|
59 @property |
|
60 def host_config(self): |
|
61 dictconfig = self.dictconfig |
|
62 host = gethostname() |
|
63 for hostcfg in self.host_configs: |
|
64 if hostcfg.match(host): |
|
65 self.info('matching host config %s for source %s', |
|
66 hostcfg.match_host, self.name) |
|
67 dictconfig.update(hostcfg.dictconfig) |
|
68 return dictconfig |
|
69 |
|
70 @property |
|
71 def host_configs(self): |
|
72 return self.reverse_cw_host_config_of |
|
73 |
|
74 def init_mapping(self, mapping): |
|
75 for key, options in mapping: |
|
76 if isinstance(key, tuple): # relation definition |
|
77 assert len(key) == 3 |
|
78 restrictions = ['X relation_type RT, RT name %(rt)s'] |
|
79 kwargs = {'rt': key[1]} |
|
80 if key[0] != '*': |
|
81 restrictions.append('X from_entity FT, FT name %(ft)s') |
|
82 kwargs['ft'] = key[0] |
|
83 if key[2] != '*': |
|
84 restrictions.append('X to_entity TT, TT name %(tt)s') |
|
85 kwargs['tt'] = key[2] |
|
86 rql = 'Any X WHERE %s' % ','.join(restrictions) |
|
87 schemarset = self._cw.execute(rql, kwargs) |
|
88 elif key[0].isupper(): # entity type |
|
89 schemarset = self._cw.execute('CWEType X WHERE X name %(et)s', |
|
90 {'et': key}) |
|
91 else: # relation type |
|
92 schemarset = self._cw.execute('CWRType X WHERE X name %(rt)s', |
|
93 {'rt': key}) |
|
94 for schemaentity in schemarset.entities(): |
|
95 self._cw.create_entity('CWSourceSchemaConfig', |
|
96 cw_for_source=self, |
|
97 cw_schema=schemaentity, |
|
98 options=options) |
|
99 |
|
100 |
|
101 class CWSourceHostConfig(_CWSourceCfgMixIn, AnyEntity): |
|
102 __regid__ = 'CWSourceHostConfig' |
|
103 fetch_attrs, fetch_order = fetch_config(['match_host', 'config']) |
|
104 |
|
105 def match(self, hostname): |
|
106 return re.match(self.match_host, hostname) |
|
107 |
|
108 |
|
109 class CWSourceSchemaConfig(AnyEntity): |
|
110 __regid__ = 'CWSourceSchemaConfig' |
|
111 fetch_attrs, fetch_order = fetch_config(['cw_for_source', 'cw_schema', 'options']) |
|
112 |
|
113 def dc_title(self): |
|
114 return self._cw._(self.__regid__) + ' #%s' % self.eid |
|
115 |
|
116 @property |
|
117 def schema(self): |
|
118 return self.cw_schema[0] |
|
119 |
|
120 @property |
|
121 def source(self): |
|
122 """repository only property, not available from the web side (eg |
|
123 self._cw is expected to be a server session) |
|
124 """ |
|
125 return self._cw.repo.sources_by_eid[self.cw_for_source[0].eid] |