1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
#!/usr/bin/python
## Version: 0.20051107
import re, string
class deb822:
def __init__(self, fp):
self.map = {}
self.keys = []
single = re.compile("^(?P<key>\S+):\s+(?P<data>\S.*)$")
multi = re.compile("^(?P<key>\S+):\s*$")
multidata = re.compile("^\s(?P<data>.*)$")
ws = re.compile("^\s*$")
curkey = None
content = ""
for line in fp.readlines():
if ws.match(line):
if curkey:
self.map[curkey] = content[:-1]
curkey = None
content = ""
continue
m = single.match(line)
if m:
if curkey:
self.map[curkey] = content[:-1]
curkey = m.group('key')
self.keys.append(curkey)
self.map[curkey] = m.group('data')
curkey = None
content = ""
continue
m = multi.match(line)
if m:
if curkey:
self.map[curkey] = content[:-1]
curkey = m.group('key')
self.keys.append(curkey)
content = "\n"
continue
m = multidata.match(line)
if m:
content = content + line
continue
if curkey:
self.map[curkey] = content[:-1]
def dump(self, fd):
for key in self.keys:
fd.write(key + ": " + self.map[key] + "\n")
def isSingleLine(self, s):
if s.count("\n"):
return False
else:
return True
def isMultiLine(self, s):
return not self.isSingleLine(s)
def _mergeFields(self, s1, s2):
if not s2:
return s1
if not s1:
return s2
if self.isSingleLine(s1) and self.isSingleLine(s2):
## some fields are delimited by a single space, others
## a comma followed by a space. this heuristic assumes
## that there are multiple items in one of the string fields
## so that we can pick up on the delimiter being used
delim = ' '
if (s1 + s2).count(', '):
delim = ', '
L = (s1 + delim + s2).split(delim)
L.sort()
prev = merged = L[0]
for item in L[1:]:
## skip duplicate entries
if item == prev:
continue
merged = merged + delim + item
prev = item
return merged
if self.isMultiLine(s1) and self.isMultiLine(s2):
for item in s2.splitlines(True):
if item not in s1.splitlines(True):
s1 = s1 + "\n" + item
return s1
raise ValueError
def mergeFields(self, key, d1, d2 = None):
## this method can work in two ways - abstract that away
if d2 == None:
x1 = self
x2 = d1
else:
x1 = d1
x2 = d2
## we only have to do work if both objects contain our key
## otherwise, we just take the one that does, or raise an
## exception if neither does
if key in x1.keys and key in x1.keys:
merged = self._mergeFields(x1.map[key], x2.map[key])
elif key in x1.keys:
merged = x1[key]
elif key in x2.keys:
merged = x2[key]
else:
raise KeyError
## back to the two different ways - if this method was called
## upon an object, update that object in place.
## return nothing in this case, to make the author notice a
## problem if she assumes the object itself will not be modified
if d2 == None:
self.map[key] = merged
return None
return merged
def hasField(self, key):
if key in self.keys:
return True
return False
def addField(self, key, value):
if key in self.keys:
## key is already there
raise KeyError
else:
self.keys.append(key)
self.map[key] = value
## methods that changes and dsc files have in common
class _dscchanges(deb822):
"""A base class; not intended for direct use"""
## Specialty class for dealing with .dsc files
class dsc(_dscchanges):
def files(self):
fileList = []
for fileEntry in self.map["Files"].splitlines():
file = {}
if fileEntry:
fields = fileEntry.split()
file["md5sum"] = fields[0]
file["size"] = fields[1]
file["name"] = fields[2]
fileList.append(file)
return fileList
class changes(_dscchanges):
def files(self):
fileList = []
for fileEntry in self.map["Files"].splitlines():
file = {}
if fileEntry:
fields = fileEntry.split()
file["md5sum"] = fields[0]
file["size"] = fields[1]
file["section"] = fields[2]
file["priority"] = fields[3]
file["name"] = fields[4]
fileList.append(file)
return fileList
|