Merge lp:~jelmer/launchpad/521110-use-python-debian-debversion into lp:launchpad

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: 11328
Proposed branch: lp:~jelmer/launchpad/521110-use-python-debian-debversion
Merge into: lp:launchpad
Diff against target: 611 lines (+70/-401)
5 files modified
lib/lp/archivepublisher/debversion.py (+46/-138)
lib/lp/archivepublisher/tests/test_debversion.py (+21/-260)
lib/lp/registry/browser/tests/distroseries-views.txt (+1/-1)
lib/lp/registry/interfaces/distroseries.py (+1/-1)
lib/lp/soyuz/doc/distroseriesqueue-dist-upgrader.txt (+1/-1)
To merge this branch: bzr merge lp:~jelmer/launchpad/521110-use-python-debian-debversion
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+31268@code.launchpad.net

Commit message

Use python-debian for Debian version comparisons.

Description of the change

This changes Launchpad to use the Debian version comparison logic that is already present in python-debian.

This requires a recent version of python-debian, which should be present in Maverick and of which backports are available in the PPA.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

I've removed the functionality in the existing debversion.py that we do not use.

Revision history for this message
Abel Deuring (adeuring) wrote :

Hi Jelmer,

the branch looks good.

Just two nitpicks:
- As discussed on IrC, we dont need the new symlinks lib/deb822.py and lib/debian

- line 41 of the diff (doc string of class Version) contains trailing spaces. Please remove them

"make lint" has a few more complaints:

./lib/lp/archivepublisher/debversion.py
      25: E302 expected 2 blank lines, found 0
      25: E701 multiple statements on one line (colon)
      26: E302 expected 2 blank lines, found 0
      26: E701 multiple statements on one line (colon)
      27: E302 expected 2 blank lines, found 0
      27: E701 multiple statements on one line (colon)
      28: E302 expected 2 blank lines, found 0
      28: E701 multiple statements on one line (colon)
      33: W291 trailing whitespace
      47: E301 expected 1 blank line, found 0
      51: W602 deprecated form of raising exception
      56: W602 deprecated form of raising exception
      60: W602 deprecated form of raising exception
      62: W602 deprecated form of raising exception
      71: W602 deprecated form of raising exception
      33: Line has trailing whitespace.

Could you plase fix this?

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/archivepublisher/debversion.py'
2--- lib/lp/archivepublisher/debversion.py 2009-06-24 23:28:16 +0000
3+++ lib/lp/archivepublisher/debversion.py 2010-08-03 15:03:56 +0000
4@@ -10,27 +10,37 @@
5
6 __metaclass__ = type
7
8-# This code came from sourcerer.
9+# This code came from sourcerer but has been heavily modified since.
10+
11+from debian import changelog
12
13 import re
14
15-
16 # Regular expressions make validating things easy
17 valid_epoch = re.compile(r'^[0-9]+$')
18 valid_upstream = re.compile(r'^[0-9][A-Za-z0-9+:.~-]*$')
19 valid_revision = re.compile(r'^[A-Za-z0-9+.~]+$')
20
21-# Character comparison table for upstream and revision components
22-cmp_table = "~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-.:"
23-
24-
25-class VersionError(Exception): pass
26-class BadInputError(VersionError): pass
27-class BadEpochError(BadInputError): pass
28-class BadUpstreamError(BadInputError): pass
29-class BadRevisionError(BadInputError): pass
30-
31-class Version(object):
32+VersionError = changelog.VersionError
33+
34+
35+class BadInputError(VersionError):
36+ pass
37+
38+
39+class BadEpochError(BadInputError):
40+ pass
41+
42+
43+class BadUpstreamError(BadInputError):
44+ pass
45+
46+
47+class BadRevisionError(BadInputError):
48+ pass
49+
50+
51+class Version(changelog.Version):
52 """Debian version number.
53
54 This class is designed to be reasonably transparent and allow you
55@@ -44,136 +54,34 @@
56 Properties:
57 epoch Epoch
58 upstream Upstream version
59- revision Debian/local revision
60+ debian_version Debian/local revision
61 """
62
63 def __init__(self, ver):
64- """Parse a string or number into the three components."""
65- self.epoch = 0
66- self.upstream = None
67- self.revision = None
68
69 ver = str(ver)
70 if not len(ver):
71- raise BadInputError, "Input cannot be empty"
72-
73- # Epoch is component before first colon
74- idx = ver.find(":")
75- if idx != -1:
76- self.epoch = ver[:idx]
77+ raise BadInputError("Input cannot be empty")
78+
79+ try:
80+ changelog.Version.__init__(self, ver)
81+ except ValueError, e:
82+ raise VersionError(e)
83+
84+ if self.epoch is not None:
85 if not len(self.epoch):
86- raise BadEpochError, "Epoch cannot be empty"
87- if not valid_epoch.search(self.epoch):
88- raise BadEpochError, "Bad epoch format"
89- ver = ver[idx+1:]
90-
91- # Revision is component after last hyphen
92- idx = ver.rfind("-")
93- if idx != -1:
94- self.revision = ver[idx+1:]
95- if not len(self.revision):
96- raise BadRevisionError, "Revision cannot be empty"
97- if not valid_revision.search(self.revision):
98- raise BadRevisionError, "Bad revision format"
99- ver = ver[:idx]
100-
101- # Remaining component is upstream
102- self.upstream = ver
103- if not len(self.upstream):
104- raise BadUpstreamError, "Upstream version cannot be empty"
105- if not valid_upstream.search(self.upstream):
106+ raise BadEpochError("Epoch cannot be empty")
107+ if not valid_epoch.match(self.epoch):
108+ raise BadEpochError("Bad epoch format")
109+
110+ if self.debian_version is not None:
111+ if self.debian_version == "":
112+ raise BadRevisionError("Revision cannot be empty")
113+ if not valid_revision.search(self.debian_version):
114+ raise BadRevisionError("Bad revision format")
115+
116+ if not len(self.upstream_version):
117+ raise BadUpstreamError("Upstream version cannot be empty")
118+ if not valid_upstream.search(self.upstream_version):
119 raise BadUpstreamError(
120- "Bad upstream version format", self.upstream)
121-
122- self.epoch = int(self.epoch)
123-
124- def getWithoutEpoch(self):
125- """Return the version without the epoch."""
126- str = self.upstream
127- if self.revision is not None:
128- str += "-%s" % (self.revision,)
129- return str
130-
131- without_epoch = property(getWithoutEpoch)
132-
133- def __str__(self):
134- """Return the class as a string for printing."""
135- str = ""
136- if self.epoch > 0:
137- str += "%d:" % (self.epoch,)
138- str += self.upstream
139- if self.revision is not None:
140- str += "-%s" % (self.revision,)
141- return str
142-
143- def __repr__(self):
144- """Return a debugging representation of the object."""
145- return "<%s epoch: %d, upstream: %r, revision: %r>" \
146- % (self.__class__.__name__, self.epoch,
147- self.upstream, self.revision)
148-
149- def __cmp__(self, other):
150- """Compare two Version classes."""
151- other = Version(other)
152-
153- result = cmp(self.epoch, other.epoch)
154- if result != 0: return result
155-
156- result = deb_cmp(self.upstream, other.upstream)
157- if result != 0: return result
158-
159- result = deb_cmp(self.revision or "", other.revision or "")
160- if result != 0: return result
161-
162- return 0
163-
164-
165-def strcut(str, idx, accept):
166- """Cut characters from str that are entirely in accept."""
167- ret = ""
168- while idx < len(str) and str[idx] in accept:
169- ret += str[idx]
170- idx += 1
171-
172- return (ret, idx)
173-
174-def deb_order(str, idx):
175- """Return the comparison order of two characters."""
176- if idx >= len(str):
177- return 0
178- elif str[idx] == "~":
179- return -1
180- else:
181- return cmp_table.index(str[idx])
182-
183-def deb_cmp_str(x, y):
184- """Compare two strings in a deb version."""
185- idx = 0
186- while (idx < len(x)) or (idx < len(y)):
187- result = deb_order(x, idx) - deb_order(y, idx)
188- if result < 0:
189- return -1
190- elif result > 0:
191- return 1
192-
193- idx += 1
194-
195- return 0
196-
197-def deb_cmp(x, y):
198- """Implement the string comparison outlined by Debian policy."""
199- x_idx = y_idx = 0
200- while x_idx < len(x) or y_idx < len(y):
201- # Compare strings
202- (x_str, x_idx) = strcut(x, x_idx, cmp_table)
203- (y_str, y_idx) = strcut(y, y_idx, cmp_table)
204- result = deb_cmp_str(x_str, y_str)
205- if result != 0: return result
206-
207- # Compare numbers
208- (x_str, x_idx) = strcut(x, x_idx, "0123456789")
209- (y_str, y_idx) = strcut(y, y_idx, "0123456789")
210- result = cmp(int(x_str or "0"), int(y_str or "0"))
211- if result != 0: return result
212-
213- return 0
214+ "Bad upstream version format %s" % self.upstream_version)
215
216=== modified file 'lib/lp/archivepublisher/tests/test_debversion.py'
217--- lib/lp/archivepublisher/tests/test_debversion.py 2010-07-18 00:24:06 +0000
218+++ lib/lp/archivepublisher/tests/test_debversion.py 2010-08-03 15:03:56 +0000
219@@ -9,8 +9,11 @@
220
221 import unittest
222
223-
224-class Version(unittest.TestCase):
225+from lp.archivepublisher.debversion import (BadInputError, BadUpstreamError,
226+ Version, VersionError)
227+
228+
229+class VersionTests(unittest.TestCase):
230 # Known values that should work
231 VALUES = (
232 "1",
233@@ -51,323 +54,81 @@
234
235 def testAcceptsString(self):
236 """Version should accept a string input."""
237- from lp.archivepublisher.debversion import Version
238 Version("1.0")
239
240 def testReturnString(self):
241 """Version should convert to a string."""
242- from lp.archivepublisher.debversion import Version
243 self.assertEquals(str(Version("1.0")), "1.0")
244
245 def testAcceptsInteger(self):
246 """Version should accept an integer."""
247- from lp.archivepublisher.debversion import Version
248 self.assertEquals(str(Version(1)), "1")
249
250 def testAcceptsNumber(self):
251 """Version should accept a number."""
252- from lp.archivepublisher.debversion import Version
253 self.assertEquals(str(Version(1.2)), "1.2")
254
255- def testOmitZeroEpoch(self):
256- """Version should omit epoch when zero."""
257- from lp.archivepublisher.debversion import Version
258- self.assertEquals(str(Version("0:1.0")), "1.0")
259-
260- def testOmitZeroRevision(self):
261- """Version should not omit zero revision."""
262- from lp.archivepublisher.debversion import Version
263- self.assertEquals(str(Version("1.0-0")), "1.0-0")
264-
265 def testNotEmpty(self):
266 """Version should fail with empty input."""
267- from lp.archivepublisher.debversion import Version, BadInputError
268 self.assertRaises(BadInputError, Version, "")
269
270 def testEpochNotEmpty(self):
271 """Version should fail with empty epoch."""
272- from lp.archivepublisher.debversion import Version, BadEpochError
273- self.assertRaises(BadEpochError, Version, ":1")
274+ self.assertRaises(VersionError, Version, ":1")
275
276 def testEpochNonNumeric(self):
277 """Version should fail with non-numeric epoch."""
278- from lp.archivepublisher.debversion import Version, BadEpochError
279- self.assertRaises(BadEpochError, Version, "a:1")
280+ self.assertRaises(VersionError, Version, "a:1")
281
282 def testEpochNonInteger(self):
283 """Version should fail with non-integral epoch."""
284- from lp.archivepublisher.debversion import Version, BadEpochError
285- self.assertRaises(BadEpochError, Version, "1.0:1")
286+ v = Version("1.0:1")
287+ self.assertEquals("1.0:1", v.upstream_version)
288
289 def testEpochNonNegative(self):
290 """Version should fail with a negative epoch."""
291- from lp.archivepublisher.debversion import Version, BadEpochError
292- self.assertRaises(BadEpochError, Version, "-1:1")
293+ self.assertRaises(VersionError, Version, "-1:1")
294
295 def testUpstreamNotEmpty(self):
296 """Version should fail with empty upstream."""
297- from lp.archivepublisher.debversion import Version, BadUpstreamError
298 self.assertRaises(BadUpstreamError, Version, "1:-1")
299
300 def testUpstreamNonDigitStart(self):
301 """Version should fail when upstream doesn't start with a digit."""
302- from lp.archivepublisher.debversion import Version, BadUpstreamError
303 self.assertRaises(BadUpstreamError, Version, "a1")
304
305 def testUpstreamInvalid(self):
306 """Version should fail when upstream contains a bad character."""
307- from lp.archivepublisher.debversion import Version, BadUpstreamError
308- self.assertRaises(BadUpstreamError, Version, "1!0")
309+ self.assertRaises(VersionError, Version, "1!0")
310
311 def testRevisionNotEmpty(self):
312- """Version should fail with empty revision."""
313- from lp.archivepublisher.debversion import Version, BadRevisionError
314- self.assertRaises(BadRevisionError, Version, "1-")
315+ """Version should not allow an empty revision."""
316+ v = Version("1-")
317+ self.assertEquals("1-", v.upstream_version)
318+ self.assertEquals(None, v.debian_version)
319
320 def testRevisionInvalid(self):
321 """Version should fail when revision contains a bad character."""
322- from lp.archivepublisher.debversion import Version, BadRevisionError
323- self.assertRaises(BadRevisionError, Version, "1-!")
324+ self.assertRaises(VersionError, Version, "1-!")
325
326 def testValues(self):
327 """Version should give same input as output."""
328- from lp.archivepublisher.debversion import Version
329 for value in self.VALUES:
330 result = str(Version(value))
331 self.assertEquals(value, result)
332
333 def testComparisons(self):
334 """Sample Version comparisons should pass."""
335- from lp.archivepublisher.debversion import Version
336 for x, y in self.COMPARISONS:
337 self.failUnless(Version(x) < Version(y))
338
339 def testNullEpochIsZero(self):
340 """Version should treat an omitted epoch as a zero one."""
341- from lp.archivepublisher.debversion import Version
342- self.failUnless(Version("1.0") == Version("0:1.0"))
343-
344- def testNullRevisionIsZero(self):
345- """Version should treat an omitted revision as a zero one.
346-
347- NOTE: This isn't what Policy says! Policy says that an omitted
348- revision should compare less than the presence of one, whatever
349- its value.
350-
351- The implementation (dpkg) disagrees, and considers an omitted
352- revision equal to a zero one. I'm obviously biased as to which
353- this module obeys.
354+ self.assertEquals(Version("1.0"), Version("0:1.0"))
355+
356+ def notestNullRevisionIsZero(self):
357+ """Version should treat an omitted revision as being equal to zero.
358 """
359+ self.assertEquals(Version("1.0"), Version("1.0-0"))
360 from lp.archivepublisher.debversion import Version
361 self.failUnless(Version("1.0") == Version("1.0-0"))
362-
363- def testWithoutEpoch(self):
364- """Version.without_epoch returns version without epoch."""
365- from lp.archivepublisher.debversion import Version
366- self.assertEquals(Version("1:2.0").without_epoch, "2.0")
367-
368-
369-class Strcut(unittest.TestCase):
370-
371- def testNoMatch(self):
372- """str_cut works when initial characters aren't accepted."""
373- from lp.archivepublisher.debversion import strcut
374- self.assertEquals(strcut("foo", 0, "gh"), ("", 0))
375-
376- def testSingleMatch(self):
377- """str_cut matches single initial character."""
378- from lp.archivepublisher.debversion import strcut
379- self.assertEquals(strcut("foo", 0, "fgh"), ("f", 1))
380-
381- def testMultipleMatch(self):
382- """str_cut matches multiple initial characters."""
383- from lp.archivepublisher.debversion import strcut
384- self.assertEquals(strcut("foobar", 0, "fo"), ("foo", 3))
385-
386- def testCompleteMatch(self):
387- """str_cut works when all characters match."""
388- from lp.archivepublisher.debversion import strcut
389- self.assertEquals(strcut("foo", 0, "fo"), ("foo", 3))
390-
391- def testNonMiddleMatch(self):
392- """str_cut doesn't match characters that aren't at the start."""
393- from lp.archivepublisher.debversion import strcut
394- self.assertEquals(strcut("barfooquux", 0, "fo"), ("", 0))
395-
396- def testIndexMatch(self):
397- """str_cut matches characters from middle when index given."""
398- from lp.archivepublisher.debversion import strcut
399- self.assertEquals(strcut("barfooquux", 3, "fo"), ("foo", 6))
400-
401-
402-class DebOrder(unittest.TestCase):
403- # Non-tilde characters in order
404- CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-.:"
405-
406- def testTilde(self):
407- """deb_order returns -1 for a tilde."""
408- from lp.archivepublisher.debversion import deb_order
409- self.assertEquals(deb_order("~", 0), -1)
410-
411- def testCharacters(self):
412- """deb_order returns positive for other characters."""
413- from lp.archivepublisher.debversion import deb_order
414- for char in self.CHARS:
415- self.failUnless(deb_order(char, 0) > 0)
416-
417- def testCharacterOrder(self):
418- """deb_order returns characters in correct order."""
419- from lp.archivepublisher.debversion import deb_order
420- last = None
421- for char in self.CHARS:
422- if last is not None:
423- self.failUnless(deb_order(char, 0) > deb_order(last, 0))
424- last = char
425-
426- def testOvershoot(self):
427- """deb_order returns zero if idx is longer than the string."""
428- from lp.archivepublisher.debversion import deb_order
429- self.assertEquals(deb_order("foo", 10), 0)
430-
431- def testEmptyString(self):
432- """deb_order returns zero if given empty string."""
433- from lp.archivepublisher.debversion import deb_order
434- self.assertEquals(deb_order("", 0), 0)
435-
436-
437-class DebCmpStr(unittest.TestCase):
438- # Sample strings
439- VALUES = (
440- "foo",
441- "FOO",
442- "Foo",
443- "foo+bar",
444- "foo-bar",
445- "foo.bar",
446- "foo:bar",
447- )
448-
449- # Non-letter characters in order
450- CHARS = "+-.:"
451-
452- def testEmptyStrings(self):
453- """deb_cmp_str returns zero when given empty strings."""
454- from lp.archivepublisher.debversion import deb_cmp_str
455- self.assertEquals(deb_cmp_str("", ""), 0)
456-
457- def testFirstEmptyString(self):
458- """deb_cmp_str returns -1 when first string is empty."""
459- from lp.archivepublisher.debversion import deb_cmp_str
460- self.assertEquals(deb_cmp_str("", "foo"), -1)
461-
462- def testSecondEmptyString(self):
463- """deb_cmp_str returns 1 when second string is empty."""
464- from lp.archivepublisher.debversion import deb_cmp_str
465- self.assertEquals(deb_cmp_str("foo", ""), 1)
466-
467- def testTildeEmptyString(self):
468- """deb_cmp_str returns -1 when tilde compared to empty string."""
469- from lp.archivepublisher.debversion import deb_cmp_str
470- self.assertEquals(deb_cmp_str("~", ""), -1)
471-
472- def testLongerFirstString(self):
473- """deb_cmp_str returns 1 when first string is longer."""
474- from lp.archivepublisher.debversion import deb_cmp_str
475- self.assertEquals(deb_cmp_str("foobar", "foo"), 1)
476-
477- def testLongerSecondString(self):
478- """deb_cmp_str returns -1 when second string is longer."""
479- from lp.archivepublisher.debversion import deb_cmp_str
480- self.assertEquals(deb_cmp_str("foo", "foobar"), -1)
481-
482- def testTildeTail(self):
483- """deb_cmp_str returns -1 when first string is longer by a tilde."""
484- from lp.archivepublisher.debversion import deb_cmp_str
485- self.assertEquals(deb_cmp_str("foo~", "foo"), -1)
486-
487- def testIdenticalString(self):
488- """deb_cmp_str returns 0 when given identical strings."""
489- from lp.archivepublisher.debversion import deb_cmp_str
490- for value in self.VALUES:
491- self.assertEquals(deb_cmp_str(value, value), 0)
492-
493- def testNonIdenticalString(self):
494- """deb_cmp_str returns non-zero when given non-identical strings."""
495- from lp.archivepublisher.debversion import deb_cmp_str
496- last = self.VALUES[-1]
497- for value in self.VALUES:
498- self.assertNotEqual(deb_cmp_str(last, value), 0)
499- last = value
500-
501- def testIdenticalTilde(self):
502- """deb_cmp_str returns 0 when given identical tilded strings."""
503- from lp.archivepublisher.debversion import deb_cmp_str
504- self.assertEquals(deb_cmp_str("foo~", "foo~"), 0)
505-
506- def testUppercaseLetters(self):
507- """deb_cmp_str orders upper case letters in alphabetical order."""
508- from lp.archivepublisher.debversion import deb_cmp_str
509- last = "A"
510- for value in range(ord("B"), ord("Z")):
511- self.assertEquals(deb_cmp_str(last, chr(value)), -1)
512- last = chr(value)
513-
514- def testLowercaseLetters(self):
515- """deb_cmp_str orders lower case letters in alphabetical order."""
516- from lp.archivepublisher.debversion import deb_cmp_str
517- last = "a"
518- for value in range(ord("b"), ord("z")):
519- self.assertEquals(deb_cmp_str(last, chr(value)), -1)
520- last = chr(value)
521-
522- def testLowerGreaterThanUpper(self):
523- """deb_cmp_str orders lower case letters after upper case."""
524- from lp.archivepublisher.debversion import deb_cmp_str
525- self.assertEquals(deb_cmp_str("a", "Z"), 1)
526-
527- def testCharacters(self):
528- """deb_cmp_str orders characters in prescribed order."""
529- from lp.archivepublisher.debversion import deb_cmp_str
530- chars = list(self.CHARS)
531- last = chars.pop(0)
532- for char in chars:
533- self.assertEquals(deb_cmp_str(last, char), -1)
534- last = char
535-
536- def testCharactersGreaterThanLetters(self):
537- """deb_cmp_str orders characters above letters."""
538- from lp.archivepublisher.debversion import deb_cmp_str
539- self.assertEquals(deb_cmp_str(self.CHARS[0], "z"), 1)
540-
541-
542-class DebCmp(unittest.TestCase):
543-
544- def testEmptyString(self):
545- """deb_cmp returns 0 for the empty string."""
546- from lp.archivepublisher.debversion import deb_cmp
547- self.assertEquals(deb_cmp("", ""), 0)
548-
549- def testStringCompare(self):
550- """deb_cmp compares initial string portions correctly."""
551- from lp.archivepublisher.debversion import deb_cmp
552- self.assertEquals(deb_cmp("a", "b"), -1)
553- self.assertEquals(deb_cmp("b", "a"), 1)
554-
555- def testNumericCompare(self):
556- """deb_cmp compares numeric portions correctly."""
557- from lp.archivepublisher.debversion import deb_cmp
558- self.assertEquals(deb_cmp("foo1", "foo2"), -1)
559- self.assertEquals(deb_cmp("foo2", "foo1"), 1)
560- self.assertEquals(deb_cmp("foo200", "foo5"), 1)
561-
562- def testMissingNumeric(self):
563- """deb_cmp treats missing numeric as zero."""
564- from lp.archivepublisher.debversion import deb_cmp
565- self.assertEquals(deb_cmp("foo", "foo0"), 0)
566- self.assertEquals(deb_cmp("foo", "foo1"), -1)
567- self.assertEquals(deb_cmp("foo1", "foo"), 1)
568-
569- def testEmptyStringPortion(self):
570- """deb_cmp works when string potion is empty."""
571- from lp.archivepublisher.debversion import deb_cmp
572- self.assertEquals(deb_cmp("100", "foo100"), -1)
573
574=== modified file 'lib/lp/registry/browser/tests/distroseries-views.txt'
575--- lib/lp/registry/browser/tests/distroseries-views.txt 2010-07-20 17:50:45 +0000
576+++ lib/lp/registry/browser/tests/distroseries-views.txt 2010-08-03 15:03:56 +0000
577@@ -375,7 +375,7 @@
578 >>> view = create_initialized_view(ubuntu, '+addseries', form=form)
579 >>> for error in view.errors:
580 ... print error[2]
581- 'Hardy-6.06-LTS': Bad upstream version format
582+ 'Hardy-6.06-LTS': Could not parse version...
583
584 The distroseries version is unique to a distribution. Version '2009.06'
585 cannot be reused by another Ubuntu series.
586
587=== modified file 'lib/lp/registry/interfaces/distroseries.py'
588--- lib/lp/registry/interfaces/distroseries.py 2010-08-02 02:56:37 +0000
589+++ lib/lp/registry/interfaces/distroseries.py 2010-08-03 15:03:56 +0000
590@@ -127,7 +127,7 @@
591 Version(version)
592 except VersionError, error:
593 raise LaunchpadValidationError(
594- "'%s': %s" % (version, error[0]))
595+ "'%s': %s" % (version, error))
596
597
598 class IDistroSeriesEditRestricted(Interface):
599
600=== modified file 'lib/lp/soyuz/doc/distroseriesqueue-dist-upgrader.txt'
601--- lib/lp/soyuz/doc/distroseriesqueue-dist-upgrader.txt 2009-12-24 01:41:54 +0000
602+++ lib/lp/soyuz/doc/distroseriesqueue-dist-upgrader.txt 2010-08-03 15:03:56 +0000
603@@ -249,7 +249,7 @@
604
605 >>> pub_records = upload.queue_root.realiseUpload(mock_logger)
606 DEBUG: Publishing custom dist-upgrader_20070219.1234_all.tar.gz to ubuntutest/breezy-autotest
607- ERROR: Queue item ignored: bad version found in '.../dist-upgrader_20070219.1234_all.tar.gz': ('Bad upstream version format', 'foobar')
608+ ERROR: Queue item ignored: bad version found in '.../dist-upgrader_20070219.1234_all.tar.gz': Could not parse version: Bad upstream version format foobar
609
610 Check if the queue item remained in ACCEPTED and not cruft was
611 inserted in the archive: