1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """
22 Support for RIP files.
23
24 RIP files are files containing registering information for schemas,
25 and extension classes customized for these schemas (like importers,
26 exporters, citation formatters,...)
27
28 First, you need to parse a few RIP repositories with L{parse}, then
29 you can browse the results with L{schemas}, L{getSchema} and L{get}.
30 """
31
32 import os, re
33
34 from ConfigParser import SafeConfigParser as Parser
35
36 from Pyblio import Schema
37
38 from gettext import gettext as _
39
40
41
42 _schema = {}
43
44
45
46 import Pyblio
47
48 _base = os.path.abspath(os.path.dirname(Pyblio.__file__))
49 _user = os.path.expanduser('~/.pyblio')
50
51 RIP_dirs = {
52 'system': os.path.join(_base, 'RIP'),
53 'user': _user,
54 }
55
56
57 -def get(schema, category):
58 """ Return the extensions in a given category, for a given schema."""
59
60 try:
61 return _schema[schema][category]
62 except KeyError:
63 return []
64
66 """ Return the L{Pyblio.Schema.Schema} corresponding to an
67 identifier returned by L{schemas}."""
68
69 rip = _schema[schema]
70
71 s = Schema.Schema(open(rip.path))
72
73 assert s.id == schema, _('schema %s has not the same id %s as in the RIP files') % (
74 rip.path, schema)
75 return s
76
77
79 """ Return the list of known schemas."""
80
81 return [k for k in _schema.keys() if _schema[k].path]
82
83
85 """ Forget all the schemas and extensions previously parsed with
86 L{parse}.
87 """
88
89 global _schema
90 _schema = {}
91
92
94
95 """ A RIP object represents a dynamic class that can be loaded on
96 demand, and that has been registered via the Registry system.
97
98 These objects are usually not instanciated by the user, but
99 returned by L{get}."""
100
101 - def __init__(self, schema, category, name):
102 self.schema = schema
103 self.category = category
104 self.name = name
105 self._module = None
106 return
107
109 """ When the RIP is called, it returns the dynamic class it
110 refers to, or raises an ImportError exception.
111 """
112
113 if not self._module:
114 parts = self.name.split('.')
115
116 module = __import__('.'.join(parts[:-1]))
117
118 for comp in parts[1:]:
119 module = getattr (module, comp)
120
121 self._module = module
122
123 return self._module
124
126 """ Return some help associated with the corresponding dynamic class.
127
128 Warning: this forces loading of the class.
129 """
130
131 m = self()
132
133 doc = m.__doc__
134
135 if not doc:
136 doc = _('undocumented %s' % repr(self.name))
137 else:
138 doc = doc.lstrip()
139 doc = doc.split('\n')[0].rstrip(' .\n')
140
141 return doc
142
144 """ A special RIP that keeps the description of an Adapter."""
145
146 - def __init__(self, schema, category, name, target):
151
152 _adapt_re = re.compile(r'([\w\d.]+)\s*->\s*([\w\d./]+)')
153
160
161
163 """ Parse the specified directory, and load all the .rip files it
164 contains."""
165
166 for f in os.listdir(directory):
167 base, ext = os.path.splitext(f)
168 if ext != '.rip': continue
169
170 name = os.path.join(directory, f)
171
172 allvars = {}
173 allvars.update(RIP_dirs)
174 allvars['cwd'] = directory
175
176 p = Parser(allvars)
177 p.readfp(open(name), name)
178
179 for schema in p.sections():
180 for cat in p.options(schema):
181 value = p.get(schema, cat).strip()
182
183
184
185 if cat == 'path':
186 if _schema.has_key(schema):
187 s = _schema[schema]
188 assert (s.path is None or
189 s.path == value), \
190 _('Schema %s is available in %s and %s') % (
191 schema, s.path, value)
192
193 s.path = value
194
195 else:
196 r = _RIPCategory(schema)
197 r.path = value
198
199 _schema[schema] = r
200
201 continue
202
203 if cat == 'adapters':
204 names = []
205 for m, t in _adapt_re.findall(value):
206 names.append(AdapterRIP(schema, cat, m, t))
207
208
209 else:
210 names = [RIP(schema, cat, x.strip())
211 for x in value.split('\n') ]
212
213
214
215 try:
216 _schema[schema].setdefault(cat,[]).extend(names)
217
218 except KeyError:
219 r = _RIPCategory(schema)
220 r[cat] = names
221
222 _schema[schema] = r
223
224 return
225
227 """Load the RIP files contained in the default system-wide and
228 user-specific directories.
229
230 The system directory is in '<installation prefix>/Pyblio/RIP', and
231 the user directory is '~/.pyblio'.
232 """
233 for d in RIP_dirs.values():
234 try:
235 load_settings(d)
236 except OSError:
237 pass
238 return
239