1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """
23 small common functions used by all processes
24 """
25
26
27
28
29
30
31
32
33
34
35
36 import os
37
38
39
40
41 from flumotion.common.python import makedirs
42 from flumotion.configure import configure
43
44 __version__ = "$Rev: 7096 $"
45
47 """
48 Print a version block for the flumotion binaries.
49
50 @arg binary: name of the binary
51 @type binary: string
52 """
53
54 block = []
55 block.append("%s %s" % (binary, configure.version))
56 block.append("part of Flumotion - a streaming media server")
57 block.append("(C) Copyright 2004,2005,2006,2007 Fluendo")
58 return "\n".join(block)
59
74
75
76
77
79 """
80 Create a path string out of the name of a component and its parent.
81
82 @depreciated: Use @componentId instead
83 """
84 return '/%s/%s' % (parentName, componentName)
85
87 """
88 Create a C{componentId} based on the C{parentName} and C{componentName}.
89
90 A C{componentId} uniquely identifies a component within a planet.
91
92 @since: 0.3.1
93
94 @rtype: str
95 """
96 return '/%s/%s' % (parentName, componentName)
97
99 """
100 Parses a component id ("/flowName/componentName") into its parts.
101
102 @since: 0.3.1
103
104 @rtype: tuple of (str, str)
105 @return: tuple of (flowName, componentName)
106 """
107 assert componentId is not None, "componentId should not be None"
108 l = componentId.split("/")
109 assert len(l) == 3, \
110 "componentId %s should have exactly two parts" % componentId
111 assert l[0] == '', \
112 "componentId %s should start with /" % componentId
113 return (l[1], l[2])
114
115 -def feedId(componentName, feedName):
116 """
117 Create a C{feedId} based on the C{componentName} and C{feedName}.
118
119 A C{feedId} uniquely identifies a feed within a flow or atmosphere.
120 It identifies the feed from a feeder to an eater.
121
122 @since: 0.3.1
123
124 @rtype: str
125 """
126 return "%s:%s" % (componentName, feedName)
127
129 """
130 @since: 0.3.1
131
132 @rtype: tuple of (str, str)
133 @return: tuple of (componentName, feedName)
134 """
135 assert not feedId.startswith('/'), \
136 "feedId must not start with '/': %s" % feedId
137 parts = feedId.split(":")
138 assert len(parts) == 2, "feedId %s should contain exactly one ':'" % feedId
139 return (parts[0], parts[1])
140
141 -def fullFeedId(flowName, componentName, feedName):
142 """
143 Create a C{fullFeedId} based on the C{flowName}, C{componentName} and
144 C{feedName}.
145
146 A C{fullFeedId} uniquely identifies a feed within a planet.
147
148 @since: 0.3.1
149
150 @rtype: str
151 """
152 return feedId(componentId(flowName, componentName), feedName)
153
155 """
156 @since: 0.3.1
157
158 @rtype: tuple of (str, str, str)
159 @return: tuple of (flowName, componentName, feedName)
160 """
161 parts = fullFeedId.split(":")
162 assert len(parts) == 2
163 flowName, componentName = parseComponentId(parts[0])
164 return (flowName, componentName, parts[1])
165
167 """
168 Return a string giving the fully qualified class of the given object.
169 """
170 c = object.__class__
171 return "%s.%s" % (c.__module__, c.__name__)
172
174 """
175 Convert the given (relative) path to the python module it would have to
176 be imported as.
177
178 Return None if the path is not a valid python module
179 """
180
181 valid = False
182 suffixes = ['.pyc', '.pyo', '.py', os.path.sep + '__init__']
183 for s in suffixes:
184 if path.endswith(s):
185 path = path[:-len(s)]
186 valid = True
187
188
189 if not '.' in path:
190 valid = True
191
192 if not valid:
193 return None
194
195 return ".".join(path.split(os.path.sep))
196
198 """
199 Compares two version strings. Returns -1, 0 or 1 if first is smaller than,
200 equal to or larger than second.
201
202 @type first: str
203 @type second: str
204
205 @rtype: int
206 """
207 if first == second:
208 return 0
209
210 firsts = first.split(".")
211 seconds = second.split(".")
212
213 while firsts or seconds:
214 f = 0
215 s = 0
216 try:
217 f = int(firsts[0])
218 del firsts[0]
219 except IndexError:
220 pass
221 try:
222 s = int(seconds[0])
223 del seconds[0]
224 except IndexError:
225 pass
226
227 if f < s:
228 return -1
229 if f > s:
230 return 1
231
232 return 0
233
235 """Checks if two versions are compatible.
236
237 Versions are compatible if they are from the same minor release. In
238 addition, unstable (odd) releases are treated as compatible with
239 their subsequent stable (even) releases.
240
241 @param version: version to check
242 @type version: tuple of int
243 @param against: version against which we are checking. For versions
244 of core Flumotion, this may be obtained by
245 L{flumotion.configure.configure.version}.
246 @type against: tuple of int
247 @returns: True if a configuration from version is compatible with
248 against.
249 """
250 if version == against:
251 return True
252 elif version > against:
253
254
255 return False
256 elif len(version) < 2 or len(against) < 2:
257 return False
258 elif version[0] != against[0]:
259 return False
260 else:
261 round2 = lambda x: ((x + 1) // 2) * 2
262 return round2(version[1]) == round2(against[1])
263
265 """
266 Converts a version tuple to a string. If the tuple has a zero nano number,
267 it is dropped from the string.
268
269 @since: 0.4.1
270
271 @type versionTuple: tuple
272
273 @rtype: str
274 """
275 if len(versionTuple) == 4 and versionTuple[3] == 0:
276 versionTuple = versionTuple[:3]
277
278 return ".".join([str(i) for i in versionTuple])
279
280 -def _uniq(l, key=lambda x: x):
281 """
282 Filters out duplicate entries in a list.
283 """
284 out = []
285 for x in l:
286 if key(x) not in [key(y) for y in out]:
287 out.append(x)
288 return out
289
291 mro = type(obj).__mro__
292 if not subclass_first:
293
294
295 mro = list(mro)
296 mro.reverse()
297 procs = []
298 for c in mro:
299 if hasattr(c, method):
300 proc = getattr(c, method)
301 assert callable(proc) and hasattr(proc, 'im_func'),\
302 'attr %s of class %s is not a method' % (method, c)
303 procs.append(proc)
304
305
306
307
308 return _uniq(procs, lambda proc: proc.im_func)
309
311 """
312 Invoke all implementations of a method on an object.
313
314 Searches for method implementations in the object's class and all of
315 the class' superclasses. Calls the methods in method resolution
316 order, which goes from subclasses to superclasses.
317 """
318 for proc in get_all_methods(obj, method, True):
319 proc(obj, *args, **kwargs)
320
322 """
323 Invoke all implementations of a method on an object.
324
325 Like call_each_method, but calls the methods in reverse method
326 resolution order, from superclasses to subclasses.
327 """
328 for proc in get_all_methods(obj, method, False):
329 proc(obj, *args, **kwargs)
330
332 """
333 A mixin class to help with object initialization.
334
335 In some class hierarchies, __init__ is only used for initializing
336 instance variables. In these cases it is advantageous to avoid the
337 need to "chain up" to a parent implementation of a method. Adding
338 this class to your hierarchy will, for each class in the object's
339 class hierarchy, call the class's init() implementation on the
340 object.
341
342 Note that the function is called init() without underscrores, and
343 that there is no need to chain up to superclasses' implementations.
344
345 Uses call_each_method_reversed() internally.
346 """
347
350
352 """
353 @type string: str
354
355 @return: True if the string represents a value we interpret as true.
356 """
357 if string in ('True', 'true', '1', 'yes'):
358 return True
359
360 return False
361
363 """Assert that twisted has support for SSL connections.
364 """
365 from twisted.internet import posixbase
366 from flumotion.common import errors
367
368 if not posixbase.sslEnabled:
369 raise errors.NoSSLError()
370
371
372
373
374
375
376
377
378