upload tizen1.0 source
[kernel/linux-2.6.36.git] / debian / lib / python / debian_linux / debian.py
1 import itertools, os.path, re, utils
2
3 class Changelog(list):
4     _rules = r"""
5 ^
6 (?P<source>
7     \w[-+0-9a-z.]+
8 )
9
10 \(
11 (?P<version>
12     [^\(\)\ \t]+
13 )
14 \)
15 \s+
16 (?P<distribution>
17     [-+0-9a-zA-Z.]+
18 )
19 \;
20 """
21     _re = re.compile(_rules, re.X)
22
23     class Entry(object):
24         __slot__ = 'distribution', 'source', 'version'
25
26         def __init__(self, distribution, source, version):
27             self.distribution, self.source, self.version = distribution, source, version
28
29     def __init__(self, dir = '', version = None):
30         if version is None:
31             version = Version
32         f = file(os.path.join(dir, "debian/changelog"))
33         while True:
34             line = f.readline()
35             if not line:
36                 break
37             match = self._re.match(line)
38             if not match:
39                 continue
40             try:
41                 v = version(match.group('version'))
42             except Exception:
43                 if not len(self):
44                     raise
45                 v = Version(match.group('version'))
46             self.append(self.Entry(match.group('distribution'), match.group('source'), v))
47
48 class Version(object):
49     _version_rules = ur"""
50 ^
51 (?:
52     (?P<epoch>
53         \d+
54     )
55     :
56 )?
57 (?P<upstream>
58     .+?
59 )   
60 (?:
61     -
62     (?P<revision>[^-]+)
63 )?
64 $
65 """
66     _version_re = re.compile(_version_rules, re.X)
67
68     def __init__(self, version):
69         match = self._version_re.match(version)
70         if match is None:
71             raise RuntimeError, "Invalid debian version"
72         self.epoch = None
73         if match.group("epoch") is not None:
74             self.epoch = int(match.group("epoch"))
75         self.upstream = match.group("upstream")
76         self.revision = match.group("revision")
77
78     def __str__(self):
79         return self.complete
80
81     @property
82     def complete(self):
83         if self.epoch is not None:
84             return "%d:%s" % (self.epoch, self.complete_noepoch)
85         return self.complete_noepoch
86
87     @property
88     def complete_noepoch(self):
89         if self.revision is not None:
90             return "%s-%s" % (self.upstream, self.revision)
91         return self.upstream
92
93     @property
94     def debian(self):
95         from warnings import warn
96         warn("debian argument was replaced by revision", DeprecationWarning, stacklevel = 2)
97         return self.revision
98
99 class VersionLinux(Version):
100     _version_linux_rules = ur"""
101 ^
102 (?P<version>
103     (?P<major>\d+\.\d+)
104     \.
105     \d+
106 )
107 (?:
108     ~
109     (?P<modifier>
110         .+?
111     )
112 )?
113 (?:
114     \.dfsg\.
115     (?P<dfsg>
116         \d+
117     )
118 )?
119 -
120 \d+
121 (\.\d+)?
122 (?:
123     (?P<revision_experimental>
124         ~experimental\.\d+
125     )
126     |
127     (?P<revision_other>
128         [^-]+
129     )
130 )?
131 $
132 """
133     _version_linux_re = re.compile(_version_linux_rules, re.X)
134
135     def __init__(self, version):
136         super(VersionLinux, self).__init__(version)
137         match = self._version_linux_re.match(version)
138         if match is None:
139             raise RuntimeError, "Invalid debian linux version"
140         d = match.groupdict()
141         self.linux_major = d['major']
142         self.linux_modifier = d['modifier']
143         self.linux_version = d['version']
144         if d['modifier'] is not None:
145             self.linux_upstream = '-'.join((d['version'], d['modifier']))
146         else:
147             self.linux_upstream = d['version']
148         self.linux_dfsg = d['dfsg']
149         self.linux_revision_experimental = match.group('revision_experimental') and True
150         self.linux_revision_other = match.group('revision_other') and True
151  
152 class PackageFieldList(list):
153     def __init__(self, value = None):
154         self.extend(value)
155
156     def __str__(self):
157         return ' '.join(self)
158
159     def _extend(self, value):
160         if value is not None:
161             self.extend([j.strip() for j in re.split('\s', value.strip())])
162
163     def extend(self, value):
164         if isinstance(value, str):
165             self._extend(value)
166         else:
167             super(PackageFieldList, self).extend(value)
168
169 class PackageDescription(object):
170     __slots__ = "short", "long"
171
172     def __init__(self, value = None):
173         self.short = []
174         self.long = []
175         if value is not None:
176             short, long = value.split("\n", 1)
177             self.append(long)
178             self.append_short(short)
179
180     def __str__(self):
181         wrap = utils.TextWrapper(width = 74, fix_sentence_endings = True).wrap
182         short = ', '.join(self.short)
183         long_pars = []
184         for i in self.long:
185             long_pars.append(wrap(i))
186         long = '\n .\n '.join(['\n '.join(i) for i in long_pars])
187         return short + '\n ' + long
188
189     def append(self, str):
190         str = str.strip()
191         if str:
192             self.long.extend(str.split("\n.\n"))
193
194     def append_short(self, str):
195         for i in [i.strip() for i in str.split(",")]:
196             if i:
197                 self.short.append(i)
198
199     def extend(self, desc):
200         if isinstance(desc, PackageDescription):
201             self.short.extend(desc.short)
202             self.long.extend(desc.long)
203         else:
204             raise TypeError
205
206 class PackageRelation(list):
207     def __init__(self, value=None, override_arches=None):
208         if value:
209             self.extend(value, override_arches)
210
211     def __str__(self):
212         return ', '.join([str(i) for i in self])
213
214     def _search_value(self, value):
215         for i in self:
216             if i._search_value(value):
217                 return i
218         return None
219
220     def append(self, value, override_arches=None):
221         if isinstance(value, basestring):
222             value = PackageRelationGroup(value, override_arches)
223         elif not isinstance(value, PackageRelationGroup):
224             raise ValueError, "got %s" % type(value)
225         j = self._search_value(value)
226         if j:
227             j._update_arches(value)
228         else:
229             super(PackageRelation, self).append(value)
230
231     def extend(self, value, override_arches=None):
232         if isinstance(value, basestring):
233             value = [j.strip() for j in re.split(',', value.strip())]
234         elif not isinstance(value, (list, tuple)):
235             raise ValueError, "got %s" % type(value)
236         for i in value:
237             self.append(i, override_arches)
238
239 class PackageRelationGroup(list):
240     def __init__(self, value=None, override_arches=None):
241         if value:
242             self.extend(value, override_arches)
243
244     def __str__(self):
245         return ' | '.join([str(i) for i in self])
246
247     def _search_value(self, value):
248         for i, j in itertools.izip(self, value):
249             if i.name != j.name or i.version != j.version:
250                 return None
251         return self
252
253     def _update_arches(self, value):
254         for i, j in itertools.izip(self, value):
255             if i.arches:
256                 for arch in j.arches:
257                     if arch not in i.arches:
258                         i.arches.append(arch)
259
260     def append(self, value, override_arches=None):
261         if isinstance(value, basestring):
262             value = PackageRelationEntry(value, override_arches)
263         elif not isinstance(value, PackageRelationEntry):
264             raise ValueError
265         super(PackageRelationGroup, self).append(value)
266
267     def extend(self, value, override_arches=None):
268         if isinstance(value, basestring):
269             value = [j.strip() for j in re.split('\|', value.strip())]
270         elif not isinstance(value, (list, tuple)):
271             raise ValueError
272         for i in value:
273             self.append(i, override_arches)
274
275 class PackageRelationEntry(object):
276     __slots__ = "name", "operator", "version", "arches"
277
278     _re = re.compile(r'^(\S+)(?: \((<<|<=|=|!=|>=|>>)\s*([^)]+)\))?(?: \[([^]]+)\])?$')
279
280     class _operator(object):
281         OP_LT = 1; OP_LE = 2; OP_EQ = 3; OP_NE = 4; OP_GE = 5; OP_GT = 6
282         operators = { '<<': OP_LT, '<=': OP_LE, '=':  OP_EQ, '!=': OP_NE, '>=': OP_GE, '>>': OP_GT }
283         operators_neg = { OP_LT: OP_GE, OP_LE: OP_GT, OP_EQ: OP_NE, OP_NE: OP_EQ, OP_GE: OP_LT, OP_GT: OP_LE }
284         operators_text = dict([(b, a) for a, b in operators.iteritems()])
285
286         __slots__ = '_op',
287
288         def __init__(self, value):
289             self._op = self.operators[value]
290
291         def __neg__(self):
292             return self.__class__(self.operators_text[self.operators_neg[self._op]])
293
294         def __str__(self):
295             return self.operators_text[self._op]
296
297     def __init__(self, value=None, override_arches=None):
298         if not isinstance(value, basestring):
299             raise ValueError
300
301         self.parse(value)
302
303         if override_arches:
304             self.arches = list(override_arches)
305
306     def __str__(self):
307         ret = [self.name]
308         if self.operator is not None and self.version is not None:
309             ret.extend([' (', str(self.operator), ' ', self.version, ')'])
310         if self.arches:
311             ret.extend([' [', ' '.join(self.arches), ']'])
312         return ''.join(ret)
313
314     def parse(self, value):
315         match = self._re.match(value)
316         if match is None:
317             raise RuntimeError, "Can't parse dependency %s" % value
318         match = match.groups()
319         self.name = match[0]
320         if match[1] is not None:
321             self.operator = self._operator(match[1])
322         else:
323             self.operator = None
324         self.version = match[2]
325         if match[3] is not None:
326             self.arches = re.split('\s+', match[3])
327         else:
328             self.arches = []
329
330 class Package(dict):
331     _fields = utils.SortedDict((
332         ('Package', str),
333         ('Source', str),
334         ('Architecture', PackageFieldList),
335         ('Section', str),
336         ('Priority', str),
337         ('Maintainer', str),
338         ('Uploaders', str),
339         ('Standards-Version', str),
340         ('Build-Depends', PackageRelation),
341         ('Build-Depends-Indep', PackageRelation),
342         ('Provides', PackageRelation),
343         ('Pre-Depends', PackageRelation),
344         ('Depends', PackageRelation),
345         ('Recommends', PackageRelation),
346         ('Suggests', PackageRelation),
347         ('Replaces', PackageRelation),
348         ('Conflicts', PackageRelation),
349         ('Description', PackageDescription),
350     ))
351
352     def __setitem__(self, key, value):
353         try:
354             cls = self._fields[key]
355             if not isinstance(value, cls):
356                 value = cls(value)
357         except KeyError: pass
358         super(Package, self).__setitem__(key, value)
359
360     def iterkeys(self):
361         keys = set(self.keys())
362         for i in self._fields.iterkeys():
363             if self.has_key(i):
364                 keys.remove(i)
365                 yield i
366         for i in keys:
367             yield i
368
369     def iteritems(self):
370         for i in self.iterkeys():
371             yield (i, self[i])
372
373     def itervalues(self):
374         for i in self.iterkeys():
375             yield self[i]
376