]> git.donarmstrong.com Git - dak.git/commitdiff
Merge commit 'lamby/master' into merge
authorJoerg Jaspert <joerg@debian.org>
Sun, 1 Nov 2009 09:06:47 +0000 (10:06 +0100)
committerJoerg Jaspert <joerg@debian.org>
Sun, 1 Nov 2009 09:06:47 +0000 (10:06 +0100)
* commit 'lamby/master': (23 commits)
  Add tests for process_gpgv_output
  Remove some of the Table boilerplate
  Heh, someone fixed these issues since 2001.
  Add dak.conf for tests as utilities parse it.
  Port old tests to unittest; currently 18 failures.
  Add a 'fixture' utility to generate a path to a fixture.
  Tidy daklib.utils.which_conf_file
  Use a custom dak.conf during tests - now we can import daklib.utils.
  Drop executable bits on libraries.
  Prefer the "Borg" pattern over the GoF singleton pattern.
  Remove empty docstring.
  Make daklib.lintian work on the named groups, not the "flat" groups
  Use named groups in lintian regex.
  Alter generate_reject_messages to return a generator.
  Tidy upload.check_lintian.
  Generate lintian reject messages in daklib.lintian + tests
  Add a docstring for parse_lintian_output
  An empty output is handled fine.
  Move lintian parsing to daklib.lintian and add tests.
  Rename warning/error in lintian autorejects to nonfatal/fatal.
  ...

Signed-off-by: Joerg Jaspert <joerg@debian.org>
55 files changed:
config/debian/lintian.tags
dak/test/001/1.dsc [deleted file]
dak/test/001/2.dsc [deleted file]
dak/test/001/3.dsc [deleted file]
dak/test/001/4.dsc [deleted file]
dak/test/001/5.dsc [deleted file]
dak/test/001/6.dsc [deleted file]
dak/test/001/test.py [deleted file]
dak/test/002/empty.changes [deleted file]
dak/test/002/test.py [deleted file]
dak/test/003/krb5_1.2.2-4_m68k.changes [deleted file]
dak/test/003/test.py [deleted file]
dak/test/004/test.py [deleted file]
dak/test/005/bogus-post.changes [deleted file]
dak/test/005/bogus-pre.changes [deleted file]
dak/test/005/test.py [deleted file]
dak/test/005/valid.changes [deleted file]
dak/test/006/test.py [deleted file]
daklib/binary.py [changed mode: 0755->0644]
daklib/changes.py [changed mode: 0755->0644]
daklib/config.py [changed mode: 0755->0644]
daklib/dak_exceptions.py [changed mode: 0755->0644]
daklib/daklog.py [changed mode: 0755->0644]
daklib/dbconn.py [changed mode: 0755->0644]
daklib/holding.py [changed mode: 0755->0644]
daklib/lintian.py [new file with mode: 0644]
daklib/queue.py [changed mode: 0755->0644]
daklib/regexes.py [changed mode: 0755->0644]
daklib/singleton.py [deleted file]
daklib/summarystats.py [changed mode: 0755->0644]
daklib/textutils.py [changed mode: 0755->0644]
daklib/urgencylog.py [changed mode: 0755->0644]
daklib/utils.py [changed mode: 0755->0644]
tests/base_test.py [new file with mode: 0644]
tests/fixtures/changes/1.changes [new file with mode: 0644]
tests/fixtures/changes/2.changes [new file with mode: 0644]
tests/fixtures/changes/bogus-post.changes [new file with mode: 0644]
tests/fixtures/changes/bogus-pre.changes [new file with mode: 0644]
tests/fixtures/changes/valid.changes [new file with mode: 0644]
tests/fixtures/dak.conf [new file with mode: 0644]
tests/fixtures/dsc/1.dsc [new file with mode: 0644]
tests/fixtures/dsc/2.dsc [new file with mode: 0644]
tests/fixtures/dsc/3.dsc [new file with mode: 0644]
tests/fixtures/dsc/4.dsc [new file with mode: 0644]
tests/fixtures/dsc/5.dsc [new file with mode: 0644]
tests/fixtures/dsc/6.dsc [new file with mode: 0644]
tests/fixtures/dsc/7.dsc [new file with mode: 0644]
tests/test_extract_component_from_section.py [new file with mode: 0755]
tests/test_fix_maintainer.py [new file with mode: 0755]
tests/test_formats.py
tests/test_lintian.py [new file with mode: 0755]
tests/test_parse_changes.py [new file with mode: 0755]
tests/test_process_gpgv_output.py [new file with mode: 0755]
tests/test_regexes.py
tests/test_srcformats.py

index bf489144599b2392f0bdcc11492af22caf8359fd..e736be35d82ce114ddea4b95a6191a2a577ea963 100644 (file)
@@ -1,5 +1,5 @@
 lintian:
-  warning:
+  nonfatal:
     - statically-linked-binary
     - arch-independent-package-contains-binary-or-object
     - arch-dependent-file-in-usr-share
@@ -12,7 +12,7 @@ lintian:
     - mknod-in-maintainer-script
     - package-contains-info-dir-file
     - copyright-lists-upstream-authors-with-dh_make-boilerplate
-  error:
+  fatal:
     - wrong-file-owner-uid-or-gid
     - bad-relation
     - FSSTND-dir-in-usr
diff --git a/dak/test/001/1.dsc b/dak/test/001/1.dsc
deleted file mode 100644 (file)
index dfdd92f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-Format: 1.0
-Source: amaya
-Version: 3.2.1-1
-Binary: amaya
-Maintainer: Steve Dunham <dunham@debian.org>
-Architecture: any
-Standards-Version: 2.4.0.0
-Files: 
- 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
- da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.2 (GNU/Linux)
-Comment: For info see http://www.gnupg.org
-
-iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
-rhYnRmVuNMa8oYSvL4hl/Yw=
-=EFAA
------END PGP SIGNATURE-----
diff --git a/dak/test/001/2.dsc b/dak/test/001/2.dsc
deleted file mode 100644 (file)
index a6c9d85..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-Format: 1.0
-Source: amaya
-Version: 3.2.1-1
-Binary: amaya
-Maintainer: Steve Dunham <dunham@debian.org>
-Architecture: any
-Standards-Version: 2.4.0.0
-Files: 
- 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
- da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.2 (GNU/Linux)
-Comment: For info see http://www.gnupg.org
-
-iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
-rhYnRmVuNMa8oYSvL4hl/Yw=
-=EFAA
------END PGP SIGNATURE-----
diff --git a/dak/test/001/3.dsc b/dak/test/001/3.dsc
deleted file mode 100644 (file)
index 211340e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-Format: 1.0
-Source: amaya
-Version: 3.2.1-1
-Binary: amaya
-Maintainer: Steve Dunham <dunham@debian.org>
-Architecture: any
-Standards-Version: 2.4.0.0
-Files: 
- 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
- da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.2 (GNU/Linux)
-Comment: For info see http://www.gnupg.org
-
-iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
-rhYnRmVuNMa8oYSvL4hl/Yw=
-=EFAA
------END PGP SIGNATURE-----
diff --git a/dak/test/001/4.dsc b/dak/test/001/4.dsc
deleted file mode 100644 (file)
index 91e361f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-Format: 1.0
-Source: amaya
-Version: 3.2.1-1
-Binary: amaya
-Maintainer: Steve Dunham <dunham@debian.org>
-Architecture: any
-Standards-Version: 2.4.0.0
-Files: 
- 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
- da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.2 (GNU/Linux)
-Comment: For info see http://www.gnupg.org
-iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
-rhYnRmVuNMa8oYSvL4hl/Yw=
-=EFAA
------END PGP SIGNATURE-----
diff --git a/dak/test/001/5.dsc b/dak/test/001/5.dsc
deleted file mode 100644 (file)
index db9d8d3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-Format: 1.0
-Source: amaya
-Version: 3.2.1-1
-Binary: amaya
-Maintainer: Steve Dunham <dunham@debian.org>
-Architecture: any
-Standards-Version: 2.4.0.0
-Files: 
- 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
- da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
-
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.2 (GNU/Linux)
-Comment: For info see http://www.gnupg.org
-
-iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
-rhYnRmVuNMa8oYSvL4hl/Yw=
-=EFAA
------END PGP SIGNATURE-----
diff --git a/dak/test/001/6.dsc b/dak/test/001/6.dsc
deleted file mode 100644 (file)
index ae36d64..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-
-Format: 1.0
-Source: amaya
-Version: 3.2.1-1
-Binary: amaya
-Maintainer: Steve Dunham <dunham@debian.org>
-Architecture: any
-Standards-Version: 2.4.0.0
-Files: 
- 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
- da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.2 (GNU/Linux)
-Comment: For info see http://www.gnupg.org
-
-iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
-rhYnRmVuNMa8oYSvL4hl/Yw=
-=EFAA
------END PGP SIGNATURE-----
diff --git a/dak/test/001/test.py b/dak/test/001/test.py
deleted file mode 100644 (file)
index 8238c20..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python
-
-# Check utils.parse_changes()'s .dsc file validation
-# Copyright (C) 2000, 2006  James Troup <james@nocrew.org>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-import os, sys
-
-sys.path.append(os.path.abspath('../../'))
-
-import utils
-
-################################################################################
-
-def fail(message):
-    sys.stderr.write("%s\n" % (message))
-    sys.exit(1)
-
-################################################################################
-
-def main ():
-    # Valid .dsc
-    utils.parse_changes('1.dsc',1)
-
-    # Missing blank line before signature body
-    try:
-        utils.parse_changes('2.dsc',1)
-    except utils.invalid_dsc_format_exc, line:
-        if line != 14:
-            fail("Incorrect line number ('%s') for test #2." % (line))
-    else:
-        fail("Test #2 wasn't recognised as invalid.")
-
-    # Missing blank line after signature header
-    try:
-        utils.parse_changes('3.dsc',1)
-    except utils.invalid_dsc_format_exc, line:
-        if line != 14:
-            fail("Incorrect line number ('%s') for test #3." % (line))
-    else:
-        fail("Test #3 wasn't recognised as invalid.")
-
-    # No blank lines at all
-    try:
-        utils.parse_changes('4.dsc',1)
-    except utils.invalid_dsc_format_exc, line:
-        if line != 19:
-            fail("Incorrect line number ('%s') for test #4." % (line))
-    else:
-        fail("Test #4 wasn't recognised as invalid.")
-
-    # Extra blank line before signature body
-    try:
-        utils.parse_changes('5.dsc',1)
-    except utils.invalid_dsc_format_exc, line:
-        if line != 15:
-            fail("Incorrect line number ('%s') for test #5." % (line))
-    else:
-        fail("Test #5 wasn't recognised as invalid.")
-
-    # Extra blank line after signature header
-    try:
-        utils.parse_changes('6.dsc',1)
-    except utils.invalid_dsc_format_exc, line:
-        if line != 5:
-            fail("Incorrect line number ('%s') for test #6." % (line))
-    else:
-        fail("Test #6 wasn't recognised as invalid.")
-
-    # Valid .dsc ; ignoring errors
-    utils.parse_changes('1.dsc', 0)
-
-    # Invalid .dsc ; ignoring errors
-    utils.parse_changes('2.dsc', 0)
-
-################################################################################
-
-if __name__ == '__main__':
-    main()
diff --git a/dak/test/002/empty.changes b/dak/test/002/empty.changes
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/dak/test/002/test.py b/dak/test/002/test.py
deleted file mode 100644 (file)
index 919a70a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-
-# Check utils.parse_changes()'s for handling empty files
-# Copyright (C) 2000, 2006  James Troup <james@nocrew.org>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-import os, sys
-
-sys.path.append(os.path.abspath('../../'))
-
-import utils
-
-################################################################################
-
-def fail(message):
-    sys.stderr.write("%s\n" % (message))
-    sys.exit(1)
-
-################################################################################
-
-def main ():
-    # Empty .changes file; should raise a 'parse error' exception.
-    try:
-        utils.parse_changes('empty.changes', 0)
-    except utils.changes_parse_error_exc, line:
-        if line != "[Empty changes file]":
-            fail("Returned exception with unexcpected error message `%s'." % (line))
-    else:
-        fail("Didn't raise a 'parse error' exception for a zero-length .changes file.")
-
-################################################################################
-
-if __name__ == '__main__':
-    main()
diff --git a/dak/test/003/krb5_1.2.2-4_m68k.changes b/dak/test/003/krb5_1.2.2-4_m68k.changes
deleted file mode 100644 (file)
index 9d264c1..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-
-Format: 1.7
-Date: Fri, 20 Apr 2001 02:47:21 -0400
-Source: krb5
-Binary: krb5-kdc krb5-doc krb5-rsh-server libkrb5-dev libkrb53 krb5-ftpd
- krb5-clients krb5-user libkadm54 krb5-telnetd krb5-admin-server
-Architecture: m68k
-Version: 1.2.2-4
-Distribution: unstable
-Urgency: low
-Maintainer: buildd m68k user account <buildd@ax.westfalen.de>
-Changed-By: Sam Hartman <hartmans@debian.org>
-Description: 
- krb5-admin-server - Mit Kerberos master server (kadmind)
- krb5-clients - Secure replacements for ftp, telnet and rsh using MIT Kerberos
- krb5-ftpd  - Secure FTP server supporting MIT Kerberos
- krb5-kdc   - Mit Kerberos key server (KDC)
- krb5-rsh-server - Secure replacements for rshd and rlogind  using MIT Kerberos
- krb5-telnetd - Secure telnet server supporting MIT Kerberos
- krb5-user  - Basic programs to authenticate using MIT Kerberos
- libkadm54  - MIT Kerberos administration runtime libraries
- libkrb5-dev - Headers and development libraries for MIT Kerberos
- libkrb53   - MIT Kerberos runtime libraries
-Closes: 94407
-Changes: 
- krb5 (1.2.2-4) unstable; urgency=low
- .
-   * Fix shared libraries to build with gcc not ld to properly include
-     -lgcc symbols, closes: #94407
-Files: 
- 563dac1cdd3ba922f9301fe074fbfc80 65836 non-us/main optional libkadm54_1.2.2-4_m68k.deb
- bb620f589c17ab0ebea1aa6e10ca52ad 272198 non-us/main optional libkrb53_1.2.2-4_m68k.deb
- 40af6e64b3030a179e0de25bd95c95e9 143264 non-us/main optional krb5-user_1.2.2-4_m68k.deb
- ffe4e5e7b2cab162dc608d56278276cf 141870 non-us/main optional krb5-clients_1.2.2-4_m68k.deb
- 4fe01d1acb4b82ce0b8b72652a9a15ae 54592 non-us/main optional krb5-rsh-server_1.2.2-4_m68k.deb
- b3c8c617ea72008a33b869b75d2485bf 41292 non-us/main optional krb5-ftpd_1.2.2-4_m68k.deb
- 5908f8f60fe536d7bfc1ef3fdd9d74cc 42090 non-us/main optional krb5-telnetd_1.2.2-4_m68k.deb
- 650ea769009a312396e56503d0059ebc 160236 non-us/main optional krb5-kdc_1.2.2-4_m68k.deb
- 399c9de4e9d7d0b0f5626793808a4391 160392 non-us/main optional krb5-admin-server_1.2.2-4_m68k.deb
- 6f962fe530c3187e986268b4e4d27de9 398662 non-us/main optional libkrb5-dev_1.2.2-4_m68k.deb
-
------BEGIN PGP SIGNATURE-----
-Version: 2.6.3i
-Charset: noconv
-
-iQCVAwUBOvVPPm547I3m3eHJAQHyaQP+M7RXVEqZ2/xHiPzaPcZRJ4q7o0zbMaU8
-qG/Mi6kuR1EhRNMjMH4Cp6ctbhRDHK5FR/8v7UkOd+ETDAhiw7eqJnLC60EZxZ/H
-CiOs8JklAXDERkQ3i7EYybv46Gxx91pIs2nE4xVKnG16d/wFELWMBLY6skF1B2/g
-zZju3cuFCCE=
-=Vm59
------END PGP SIGNATURE-----
-
-
diff --git a/dak/test/003/test.py b/dak/test/003/test.py
deleted file mode 100755 (executable)
index ce07c11..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-
-# Check utils.parse_changes()'s for handling of multi-line fields
-# Copyright (C) 2000, 2006  James Troup <james@nocrew.org>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-# The deal here is that for the first 6 months of dak's
-# implementation it has been misparsing multi-line fields in .changes
-# files; specifically multi-line fields where there _is_ data on the
-# first line. So, for example:
-
-# Foo: bar baz
-#  bat bant
-
-# Became "foo: bar bazbat bant" rather than "foo: bar baz\nbat bant"
-
-################################################################################
-
-import os, sys
-
-sys.path.append(os.path.abspath('../../'))
-
-import utils
-
-################################################################################
-
-def fail(message):
-    sys.stderr.write("%s\n" % (message))
-    sys.exit(1)
-
-################################################################################
-
-def main ():
-    # Valid .changes file with a multi-line Binary: field
-    try:
-        changes = utils.parse_changes('krb5_1.2.2-4_m68k.changes', 0)
-    except utils.changes_parse_error_exc, line:
-        fail("parse_changes() returned an exception with error message `%s'." % (line))
-
-    o = changes.get("binary", "")
-    if o != "":
-        del changes["binary"]
-    changes["binary"] = {}
-    for j in o.split():
-        changes["binary"][j] = 1
-
-    if not changes["binary"].has_key("krb5-ftpd"):
-        fail("parse_changes() is broken; 'krb5-ftpd' is not in the Binary: dictionary.")
-
-################################################################################
-
-if __name__ == '__main__':
-    main()
diff --git a/dak/test/004/test.py b/dak/test/004/test.py
deleted file mode 100755 (executable)
index 4aa6b48..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env python
-
-# Check utils.extract_component_from_section()
-# Copyright (C) 2000, 2006  James Troup <james@nocrew.org>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-import os, sys
-
-sys.path.append(os.path.abspath('../../'))
-
-import utils
-
-################################################################################
-
-def fail(message):
-    sys.stderr.write("%s\n" % (message))
-    sys.exit(1)
-
-################################################################################
-
-# prefix: non-US
-# component: main, contrib, non-free
-# section: games, admin, libs, [...]
-
-# [1] Order is as above.
-# [2] Prefix is optional for the default archive, but mandatory when
-#     uploads are going anywhere else.
-# [3] Default component is main and may be omitted.
-# [4] Section is optional.
-# [5] Prefix is case insensitive
-# [6] Everything else is case sensitive.
-
-def test(input, output):
-    result = utils.extract_component_from_section(input)
-    if result != output:
-        fail ("%s -> %r [should have been %r]" % (input, result, output))
-
-def main ():
-    # Err, whoops?  should probably be "utils", "main"...
-    input = "main/utils"; output = ("main/utils", "main")
-    test (input, output)
-
-
-    # Validate #3
-    input = "utils"; output = ("utils", "main")
-    test (input, output)
-
-    input = "non-free/libs"; output = ("non-free/libs", "non-free")
-    test (input, output)
-
-    input = "contrib/net"; output = ("contrib/net", "contrib")
-    test (input, output)
-
-
-    # Validate #3 with a prefix
-    input = "non-US"; output = ("non-US", "non-US/main")
-    test (input, output)
-
-
-    # Validate #4
-    input = "main"; output = ("main", "main")
-    test (input, output)
-
-    input = "contrib"; output = ("contrib", "contrib")
-    test (input, output)
-
-    input = "non-free"; output = ("non-free", "non-free")
-    test (input, output)
-
-
-    # Validate #4 with a prefix
-    input = "non-US/main"; output = ("non-US/main", "non-US/main")
-    test (input, output)
-
-    input = "non-US/contrib"; output = ("non-US/contrib", "non-US/contrib")
-    test (input, output)
-
-    input = "non-US/non-free"; output = ("non-US/non-free", "non-US/non-free")
-    test (input, output)
-
-
-    # Validate #5
-    input = "non-us"; output = ("non-us", "non-US/main")
-    test (input, output)
-
-    input = "non-us/contrib"; output = ("non-us/contrib", "non-US/contrib")
-    test (input, output)
-
-
-    # Validate #6 (section)
-    input = "utIls"; output = ("utIls", "main")
-    test (input, output)
-
-    # Others..
-    input = "non-US/libs"; output = ("non-US/libs", "non-US/main")
-    test (input, output)
-    input = "non-US/main/libs"; output = ("non-US/main/libs", "non-US/main")
-    test (input, output)
-    input = "non-US/contrib/libs"; output = ("non-US/contrib/libs", "non-US/contrib")
-    test (input, output)
-    input = "non-US/non-free/libs"; output = ("non-US/non-free/libs", "non-US/non-free")
-    test (input, output)
-
-################################################################################
-
-if __name__ == '__main__':
-    main()
diff --git a/dak/test/005/bogus-post.changes b/dak/test/005/bogus-post.changes
deleted file mode 100644 (file)
index 95e5a1f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-Format: 1.7
-Date: Tue,  9 Sep 2003 01:16:01 +0100
-Source: gawk
-Binary: gawk
-Architecture: source i386
-Version: 1:3.1.3-2
-Distribution: unstable
-Urgency: low
-Maintainer: James Troup <james@nocrew.org>
-Changed-By: James Troup <james@nocrew.org>
-Description: 
- gawk       - GNU awk, a pattern scanning and processing language
-Closes: 204699 204701
-Changes: 
- gawk (1:3.1.3-2) unstable; urgency=low
- .
-   * debian/control (Standards-Version): bump to 3.6.1.0.
- .
-   * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]].
-     Thanks to <vle@gmx.net> for reporting the bug and forwarding it
-     upstream.  Closes: #204701
- .
-   * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix
-     [\x80-\xff].  Thanks to <vle@gmx.net> for reporting the bug and
-     forwarding it upstream.  Closes: #204699
-Files: 
- 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc
- 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz
- 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.6 (GNU/Linux)
-
-iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau
-fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB
-=O7Gh
------END PGP SIGNATURE-----
-You: have been 0wned
diff --git a/dak/test/005/bogus-pre.changes b/dak/test/005/bogus-pre.changes
deleted file mode 100644 (file)
index 0234d8b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-You: have been 0wned
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-Format: 1.7
-Date: Tue,  9 Sep 2003 01:16:01 +0100
-Source: gawk
-Binary: gawk
-Architecture: source i386
-Version: 1:3.1.3-2
-Distribution: unstable
-Urgency: low
-Maintainer: James Troup <james@nocrew.org>
-Changed-By: James Troup <james@nocrew.org>
-Description: 
- gawk       - GNU awk, a pattern scanning and processing language
-Closes: 204699 204701
-Changes: 
- gawk (1:3.1.3-2) unstable; urgency=low
- .
-   * debian/control (Standards-Version): bump to 3.6.1.0.
- .
-   * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]].
-     Thanks to <vle@gmx.net> for reporting the bug and forwarding it
-     upstream.  Closes: #204701
- .
-   * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix
-     [\x80-\xff].  Thanks to <vle@gmx.net> for reporting the bug and
-     forwarding it upstream.  Closes: #204699
-Files: 
- 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc
- 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz
- 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.6 (GNU/Linux)
-
-iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau
-fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB
-=O7Gh
------END PGP SIGNATURE-----
diff --git a/dak/test/005/test.py b/dak/test/005/test.py
deleted file mode 100755 (executable)
index b5d3bbc..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-
-# Check utils.parse_changes() correctly ignores data outside the signed area
-# Copyright (C) 2004, 2006  James Troup <james@nocrew.org>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-import os, sys
-
-sys.path.append(os.path.abspath('../../'))
-
-import utils
-
-################################################################################
-
-def fail(message):
-    sys.stderr.write("%s\n" % (message))
-    sys.exit(1)
-
-################################################################################
-
-def main ():
-    for file in [ "valid", "bogus-pre", "bogus-post" ]:
-        for strict_whitespace in [ 0, 1 ]:
-            try:
-                changes = utils.parse_changes("%s.changes" % (file), strict_whitespace)
-            except utils.changes_parse_error_exc, line:
-                fail("%s[%s]: parse_changes() returned an exception with error message `%s'." % (file, strict_whitespace, line))
-            oh_dear = changes.get("you")
-            if oh_dear:
-                fail("%s[%s]: parsed and accepted unsigned data!" % (file, strict_whitespace))
-
-################################################################################
-
-if __name__ == '__main__':
-    main()
diff --git a/dak/test/005/valid.changes b/dak/test/005/valid.changes
deleted file mode 100644 (file)
index 0e77d27..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-Format: 1.7
-Date: Tue,  9 Sep 2003 01:16:01 +0100
-Source: gawk
-Binary: gawk
-Architecture: source i386
-Version: 1:3.1.3-2
-Distribution: unstable
-Urgency: low
-Maintainer: James Troup <james@nocrew.org>
-Changed-By: James Troup <james@nocrew.org>
-Description: 
- gawk       - GNU awk, a pattern scanning and processing language
-Closes: 204699 204701
-Changes: 
- gawk (1:3.1.3-2) unstable; urgency=low
- .
-   * debian/control (Standards-Version): bump to 3.6.1.0.
- .
-   * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]].
-     Thanks to <vle@gmx.net> for reporting the bug and forwarding it
-     upstream.  Closes: #204701
- .
-   * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix
-     [\x80-\xff].  Thanks to <vle@gmx.net> for reporting the bug and
-     forwarding it upstream.  Closes: #204699
-Files: 
- 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc
- 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz
- 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.0.6 (GNU/Linux)
-
-iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau
-fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB
-=O7Gh
------END PGP SIGNATURE-----
diff --git a/dak/test/006/test.py b/dak/test/006/test.py
deleted file mode 100755 (executable)
index 51a3317..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Test textutils.fix_maintainer()
-# Copyright (C) 2004, 2006  James Troup <james@nocrew.org>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-import os, sys
-
-sys.path.append(os.path.abspath('../../'))
-
-import textutils
-
-################################################################################
-
-def fail(message):
-    sys.stderr.write("%s\n" % (message))
-    sys.exit(1)
-
-################################################################################
-
-def check_valid(s, xa, xb, xc, xd):
-    (a, b, c, d) = textutils.fix_maintainer(s)
-    if a != xa:
-        fail("rfc822_maint: %s (returned) != %s (expected [From: '%s']" % (a, xa, s))
-    if b != xb:
-        fail("rfc2047_maint: %s (returned) != %s (expected [From: '%s']" % (b, xb, s))
-    if c != xc:
-        fail("name: %s (returned) != %s (expected [From: '%s']" % (c, xc, s))
-    if d != xd:
-        fail("email: %s (returned) != %s (expected [From: '%s']" % (d, xd, s))
-
-def check_invalid(s):
-    try:
-        textutils.fix_maintainer(s)
-        fail("%s was parsed successfully but is expected to be invalid." % (s))
-    except utils.ParseMaintError, unused:
-        pass
-
-def main ():
-    # Check Valid UTF-8 maintainer field
-    s = "Noèl Köthe <noel@debian.org>"
-    xa = "Noèl Köthe <noel@debian.org>"
-    xb = "=?utf-8?b?Tm/DqGwgS8O2dGhl?= <noel@debian.org>"
-    xc = "Noèl Köthe"
-    xd = "noel@debian.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check valid ISO-8859-1 maintainer field
-    s = "Noèl Köthe <noel@debian.org>"
-    xa = "Noèl Köthe <noel@debian.org>"
-    xb = "=?iso-8859-1?q?No=E8l_K=F6the?= <noel@debian.org>"
-    xc = "Noèl Köthe"
-    xd = "noel@debian.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check valid ASCII maintainer field
-    s = "James Troup <james@nocrew.org>"
-    xa = "James Troup <james@nocrew.org>"
-    xb = "James Troup <james@nocrew.org>"
-    xc = "James Troup"
-    xd = "james@nocrew.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check "Debian vs RFC822" fixup of names with '.' or ',' in them
-    s = "James J. Troup <james@nocrew.org>"
-    xa = "james@nocrew.org (James J. Troup)"
-    xb = "james@nocrew.org (James J. Troup)"
-    xc = "James J. Troup"
-    xd = "james@nocrew.org"
-    check_valid(s, xa, xb, xc, xd)
-    s = "James J, Troup <james@nocrew.org>"
-    xa = "james@nocrew.org (James J, Troup)"
-    xb = "james@nocrew.org (James J, Troup)"
-    xc = "James J, Troup"
-    xd = "james@nocrew.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check just-email form
-    s = "james@nocrew.org"
-    xa = " <james@nocrew.org>"
-    xb = " <james@nocrew.org>"
-    xc = ""
-    xd = "james@nocrew.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check bracketed just-email form
-    s = "<james@nocrew.org>"
-    xa = " <james@nocrew.org>"
-    xb = " <james@nocrew.org>"
-    xc = ""
-    xd = "james@nocrew.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check Krazy quoted-string local part email address
-    s = "Cris van Pelt <\"Cris van Pelt\"@tribe.eu.org>"
-    xa = "Cris van Pelt <\"Cris van Pelt\"@tribe.eu.org>"
-    xb = "Cris van Pelt <\"Cris van Pelt\"@tribe.eu.org>"
-    xc = "Cris van Pelt"
-    xd = "\"Cris van Pelt\"@tribe.eu.org"
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check empty string
-    s = xa = xb = xc = xd = ""
-    check_valid(s, xa, xb, xc, xd)
-
-    # Check for missing email address
-    check_invalid("James Troup")
-    # Check for invalid email address
-    check_invalid("James Troup <james@nocrew.org")
-
-################################################################################
-
-if __name__ == '__main__':
-    main()
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 2f24cd3..2d0b8e8
@@ -32,25 +32,27 @@ import os
 import apt_pkg
 import socket
 
-from singleton import Singleton
-
 ################################################################################
 
 default_config = "/etc/dak/dak.conf" #: default dak config, defines host properties
 
 def which_conf_file():
-    if os.getenv("DAK_CONFIG"):
-        return os.getenv("DAK_CONFIG")
-    else:
-        return default_config
+    return os.getenv("DAK_CONFIG", default_config)
 
-class Config(Singleton):
+class Config(object):
     """
     A Config object is a singleton containing
     information about the DAK configuration
     """
+
+    __shared_state = {}
+
     def __init__(self, *args, **kwargs):
-        super(Config, self).__init__(*args, **kwargs)
+        self.__dict__ = self.__shared_state
+
+        if not getattr(self, 'initialised', False):
+            self.initialised = True
+            self._readconf()
 
     def _readconf(self):
         apt_pkg.init()
@@ -74,9 +76,6 @@ class Config(Singleton):
         self.Find = self.Cnf.Find
         self.FindB = self.Cnf.FindB
 
-    def _startup(self, *args, **kwargs):
-        self._readconf()
-
     def has_key(self, name):
         return self.Cnf.has_key(name)
 
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 26191ae..adf119b
@@ -51,7 +51,6 @@ from sqlalchemy.exc import *
 from sqlalchemy.orm.exc import NoResultFound
 
 from config import Config
-from singleton import Singleton
 from textutils import fix_maintainer
 
 ################################################################################
@@ -2502,65 +2501,72 @@ __all__.append('UploadBlock')
 
 ################################################################################
 
-class DBConn(Singleton):
+class DBConn(object):
     """
     database module init.
     """
+    __shared_state = {}
+
     def __init__(self, *args, **kwargs):
-        super(DBConn, self).__init__(*args, **kwargs)
+        self.__dict__ = self.__shared_state
 
-    def _startup(self, *args, **kwargs):
-        self.debug = False
-        if kwargs.has_key('debug'):
-            self.debug = True
-        self.__createconn()
+        if not getattr(self, 'initialised', False):
+            self.initialised = True
+            self.debug = kwargs.has_key('debug')
+            self.__createconn()
 
     def __setuptables(self):
-        self.tbl_architecture = Table('architecture', self.db_meta, autoload=True)
-        self.tbl_archive = Table('archive', self.db_meta, autoload=True)
-        self.tbl_bin_associations = Table('bin_associations', self.db_meta, autoload=True)
-        self.tbl_binaries = Table('binaries', self.db_meta, autoload=True)
-        self.tbl_binary_acl = Table('binary_acl', self.db_meta, autoload=True)
-        self.tbl_binary_acl_map = Table('binary_acl_map', self.db_meta, autoload=True)
-        self.tbl_build_queue = Table('build_queue', self.db_meta, autoload=True)
-        self.tbl_build_queue_files = Table('build_queue_files', self.db_meta, autoload=True)
-        self.tbl_component = Table('component', self.db_meta, autoload=True)
-        self.tbl_config = Table('config', self.db_meta, autoload=True)
-        self.tbl_content_associations = Table('content_associations', self.db_meta, autoload=True)
-        self.tbl_content_file_names = Table('content_file_names', self.db_meta, autoload=True)
-        self.tbl_content_file_paths = Table('content_file_paths', self.db_meta, autoload=True)
-        self.tbl_changes_pending_binary = Table('changes_pending_binaries', self.db_meta, autoload=True)
-        self.tbl_changes_pending_files = Table('changes_pending_files', self.db_meta, autoload=True)
-        self.tbl_changes_pending_files_map = Table('changes_pending_files_map', self.db_meta, autoload=True)
-        self.tbl_changes_pending_source = Table('changes_pending_source', self.db_meta, autoload=True)
-        self.tbl_changes_pending_source_files = Table('changes_pending_source_files', self.db_meta, autoload=True)
-        self.tbl_changes_pool_files = Table('changes_pool_files', self.db_meta, autoload=True)
-        self.tbl_dsc_files = Table('dsc_files', self.db_meta, autoload=True)
-        self.tbl_files = Table('files', self.db_meta, autoload=True)
-        self.tbl_fingerprint = Table('fingerprint', self.db_meta, autoload=True)
-        self.tbl_keyrings = Table('keyrings', self.db_meta, autoload=True)
-        self.tbl_changes = Table('changes', self.db_meta, autoload=True)
-        self.tbl_keyring_acl_map = Table('keyring_acl_map', self.db_meta, autoload=True)
-        self.tbl_location = Table('location', self.db_meta, autoload=True)
-        self.tbl_maintainer = Table('maintainer', self.db_meta, autoload=True)
-        self.tbl_new_comments = Table('new_comments', self.db_meta, autoload=True)
-        self.tbl_override = Table('override', self.db_meta, autoload=True)
-        self.tbl_override_type = Table('override_type', self.db_meta, autoload=True)
-        self.tbl_pending_content_associations = Table('pending_content_associations', self.db_meta, autoload=True)
-        self.tbl_policy_queue = Table('policy_queue', self.db_meta, autoload=True)
-        self.tbl_priority = Table('priority', self.db_meta, autoload=True)
-        self.tbl_section = Table('section', self.db_meta, autoload=True)
-        self.tbl_source = Table('source', self.db_meta, autoload=True)
-        self.tbl_source_acl = Table('source_acl', self.db_meta, autoload=True)
-        self.tbl_src_associations = Table('src_associations', self.db_meta, autoload=True)
-        self.tbl_src_format = Table('src_format', self.db_meta, autoload=True)
-        self.tbl_src_uploaders = Table('src_uploaders', self.db_meta, autoload=True)
-        self.tbl_suite = Table('suite', self.db_meta, autoload=True)
-        self.tbl_suite_architectures = Table('suite_architectures', self.db_meta, autoload=True)
-        self.tbl_suite_src_formats = Table('suite_src_formats', self.db_meta, autoload=True)
-        self.tbl_suite_build_queue_copy = Table('suite_build_queue_copy', self.db_meta, autoload=True)
-        self.tbl_uid = Table('uid', self.db_meta, autoload=True)
-        self.tbl_upload_blocks = Table('upload_blocks', self.db_meta, autoload=True)
+        tables = (
+            'architecture',
+            'archive',
+            'bin_associations',
+            'binaries',
+            'binary_acl',
+            'binary_acl_map',
+            'build_queue',
+            'build_queue_files',
+            'component',
+            'config',
+            'content_associations',
+            'content_file_names',
+            'content_file_paths',
+            'changes_pending_binaries',
+            'changes_pending_files',
+            'changes_pending_files_map',
+            'changes_pending_source',
+            'changes_pending_source_files',
+            'changes_pool_files',
+            'dsc_files',
+            'files',
+            'fingerprint',
+            'keyrings',
+            'changes',
+            'keyring_acl_map',
+            'location',
+            'maintainer',
+            'new_comments',
+            'override',
+            'override_type',
+            'pending_content_associations',
+            'policy_queue',
+            'priority',
+            'section',
+            'source',
+            'source_acl',
+            'src_associations',
+            'src_format',
+            'src_uploaders',
+            'suite',
+            'suite_architectures',
+            'suite_src_formats',
+            'suite_build_queue_copy',
+            'uid',
+            'upload_blocks',
+        )
+
+        for table_name in tables:
+            table = Table('tbl_%s' % table_name, self.db_meta, autoload=True)
+            setattr(self, table_name, table)
 
     def __setupmappers(self):
         mapper(Architecture, self.tbl_architecture,
old mode 100755 (executable)
new mode 100644 (file)
index 0c472d1..b637738
@@ -30,19 +30,22 @@ import os
 from errno import ENOENT, EEXIST, EACCES
 import shutil
 
-from singleton import Singleton
 from config import Config
 from utils import fubar
 
 ###############################################################################
 
-class Holding(Singleton):
+class Holding(object):
+    __shared_state = {}
+
     def __init__(self, *args, **kwargs):
-        super(Holding, self).__init__(*args, **kwargs)
+        self.__dict__ = self.__shared_state
 
-    def _startup(self):
-        self.in_holding = {}
-        self.holding_dir = Config()["Dir::Queue::Holding"]
+        if not getattr(self, 'initialised', False):
+            self.initialised = True
+
+            self.in_holding = {}
+            self.holding_dir = Config()["Dir::Queue::Holding"]
 
     def copy_to_holding(self, filename):
         base_filename = os.path.basename(filename)
diff --git a/daklib/lintian.py b/daklib/lintian.py
new file mode 100644 (file)
index 0000000..3d1afc8
--- /dev/null
@@ -0,0 +1,58 @@
+from regexes import re_parse_lintian
+
+def parse_lintian_output(output):
+    """
+    Parses Lintian output and returns a generator with the data.
+
+    >>> list(parse_lintian_output('W: pkgname: some-tag path/to/file'))
+    [('W', 'pkgname', 'some-tag', 'path/to/file')]
+    """
+
+    for line in output.split('\n'):
+        m = re_parse_lintian.match(line)
+        if m:
+            yield m.groupdict()
+
+def generate_reject_messages(parsed_tags, tag_definitions, log=lambda *args: args):
+    """
+    Generates package reject messages by comparing parsed lintian output with
+    tag definitions. Returns a generator containing the reject messages.
+    """
+
+    tags = set()
+    for values in tag_definitions.values():
+        for tag_name in values:
+            tags.add(tag_name)
+
+    for tag in parsed_tags:
+        tag_name = tag['tag']
+
+        if tag_name not in tags:
+            continue
+
+        # Was tag overridden?
+        if tag['level'] == 'O':
+
+            if tag_name in tag_definitions['nonfatal']:
+                # Overriding this tag is allowed.
+                pass
+
+            elif tag_name in tag_definitions['fatal']:
+                # Overriding this tag is NOT allowed.
+
+                log('ftpmaster does not allow tag to be overridable', tag_name)
+                yield "%(package)s: Overriden tag %(tag)s found, but this " \
+                    "tag may not be overridden." % tag
+
+        else:
+            # Tag is known and not overridden; reject
+            yield "%(package)s: lintian output: '%(tag)s %(description)s', " \
+                "automatically rejected package." % tag
+
+            # Now tell if they *might* override it.
+            if tag_name in tag_definitions['nonfatal']:
+                log("auto rejecting", "overridable", tag_name)
+                yield "%(package)s: If you have a good reason, you may " \
+                   "override this lintian tag." % tag
+            else:
+                log("auto rejecting", "not overridable", tag_name)
old mode 100755 (executable)
new mode 100644 (file)
index 9526852..a91bcdf
@@ -54,6 +54,7 @@ from summarystats import SummaryStats
 from utils import parse_changes, check_dsc_files
 from textutils import fix_maintainer
 from binary import Binary
+from lintian import parse_lintian_output, generate_reject_messages
 
 ###############################################################################
 
@@ -1247,6 +1248,11 @@ class Upload(object):
     ###########################################################################
 
     def check_lintian(self):
+        """
+        Extends self.rejects by checking the output of lintian against tags
+        specified in Dinstall::LintianTags.
+        """
+
         cnf = Config()
 
         # Don't reject binary uploads
@@ -1254,24 +1260,22 @@ class Upload(object):
             return
 
         # Only check some distributions
-        valid_dist = False
         for dist in ('unstable', 'experimental'):
             if dist in self.pkg.changes['distribution']:
-                valid_dist = True
                 break
-
-        if not valid_dist:
+        else:
             return
 
+        # If we do not have a tagfile, don't do anything
         tagfile = cnf.get("Dinstall::LintianTags")
         if tagfile is None:
-            # We don't have a tagfile, so just don't do anything.
             return
 
         # Parse the yaml file
         sourcefile = file(tagfile, 'r')
         sourcecontent = sourcefile.read()
         sourcefile.close()
+
         try:
             lintiantags = yaml.load(sourcecontent)['lintian']
         except yaml.YAMLError, msg:
@@ -1281,78 +1285,42 @@ class Upload(object):
         # Try and find all orig mentioned in the .dsc
         symlinked = self.ensure_orig()
 
-        # Now setup the input file for lintian. lintian wants "one tag per line" only,
-        # so put it together like it. We put all types of tags in one file and then sort
-        # through lintians output later to see if its a fatal tag we detected, or not.
-        # So we only run lintian once on all tags, even if we might reject on some, but not
-        # reject on others.
-        # Additionally build up a set of tags
-        tags = set()
-        (fd, temp_filename) = utils.temp_filename()
+        # Setup the input file for lintian
+        fd, temp_filename = utils.temp_filename()
         temptagfile = os.fdopen(fd, 'w')
-        for tagtype in lintiantags:
-            for tag in lintiantags[tagtype]:
-                temptagfile.write("%s\n" % tag)
-                tags.add(tag)
+        for tags in lintiantags.values():
+            temptagfile.writelines(['%s\n' % x for x in tags])
         temptagfile.close()
 
-        # So now we should look at running lintian at the .changes file, capturing output
-        # to then parse it.
-        command = "lintian --show-overrides --tags-from-file %s %s" % (temp_filename, self.pkg.changes_file)
-        (result, output) = commands.getstatusoutput(command)
+        try:
+            cmd = "lintian --show-overrides --tags-from-file %s %s" % \
+                (temp_filename, self.pkg.changes_file)
 
-        # We are done with lintian, remove our tempfile and any symlinks we created
-        os.unlink(temp_filename)
-        for symlink in symlinked:
-            os.unlink(symlink)
+            result, output = commands.getstatusoutput(cmd)
+        finally:
+            # Remove our tempfile and any symlinks we created
+            os.unlink(temp_filename)
 
-        if (result == 2):
-            utils.warn("lintian failed for %s [return code: %s]." % (self.pkg.changes_file, result))
-            utils.warn(utils.prefix_multi_line_string(output, " [possible output:] "))
+            for symlink in symlinked:
+                os.unlink(symlink)
 
-        if len(output) == 0:
-            return
+        if result == 2:
+            utils.warn("lintian failed for %s [return code: %s]." % \
+                (self.pkg.changes_file, result))
+            utils.warn(utils.prefix_multi_line_string(output, \
+                " [possible output:] "))
 
         def log(*txt):
             if self.logger:
-                self.logger.log([self.pkg.changes_file, "check_lintian"] + list(txt))
-
-        # We have output of lintian, this package isn't clean. Lets parse it and see if we
-        # are having a victim for a reject.
-        # W: tzdata: binary-without-manpage usr/sbin/tzconfig
-        for line in output.split('\n'):
-            m = re_parse_lintian.match(line)
-            if m is None:
-                continue
-
-            etype = m.group(1)
-            epackage = m.group(2)
-            etag = m.group(3)
-            etext = m.group(4)
-
-            # So lets check if we know the tag at all.
-            if etag not in tags:
-                continue
+                self.logger.log(
+                    [self.pkg.changes_file, "check_lintian"] + list(txt)
+                )
 
-            if etype == 'O':
-                # We know it and it is overriden. Check that override is allowed.
-                if etag in lintiantags['warning']:
-                    # The tag is overriden, and it is allowed to be overriden.
-                    # Don't add a reject message.
-                    pass
-                elif etag in lintiantags['error']:
-                    # The tag is overriden - but is not allowed to be
-                    self.rejects.append("%s: Overriden tag %s found, but this tag may not be overwritten." % (epackage, etag))
-                    log("ftpmaster does not allow tag to be overridable", etag)
-            else:
-                # Tag is known, it is not overriden, direct reject.
-                self.rejects.append("%s: Found lintian output: '%s %s', automatically rejected package." % (epackage, etag, etext))
-                # Now tell if they *might* override it.
-                if etag in lintiantags['warning']:
-                    log("auto rejecting", "overridable", etag)
-                    self.rejects.append("%s: If you have a good reason, you may override this lintian tag." % (epackage))
-                else:
-                    log("auto rejecting", "not overridable", etag)
+        # Generate messages
+        parsed_tags = parse_lintian_output(output)
+        self.rejects.extend(
+            generate_reject_messages(parsed_tags, lintiantags, log=log)
+        )
 
     ###########################################################################
     def check_urgency(self):
@@ -2362,8 +2330,6 @@ distribution."""
     ################################################################################
 
     def check_source_against_db(self, filename, session):
-        """
-        """
         source = self.pkg.dsc.get("source")
         version = self.pkg.dsc.get("version")
 
old mode 100755 (executable)
new mode 100644 (file)
index 6be9997..9040e21
@@ -112,4 +112,4 @@ re_user_mails = re.compile(r"^(pub|uid):[^rdin].*<(.*@.*)>.*$", re.MULTILINE);
 re_user_name = re.compile(r"^pub:.*:(.*)<.*$", re.MULTILINE);
 re_re_mark = re.compile(r'^RE:')
 
-re_parse_lintian = re.compile(r"^(W|E|O): (.*?): ([^ ]*) ?(.*)$")
+re_parse_lintian = re.compile(r"^(?P<level>W|E|O): (?P<package>.*?): (?P<tag>[^ ]*) ?(?P<description>.*)$")
diff --git a/daklib/singleton.py b/daklib/singleton.py
deleted file mode 100644 (file)
index 535a25a..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-# vim:set et ts=4 sw=4:
-
-"""
-Singleton pattern code
-
-Inspiration for this very simple ABC was taken from various documents /
-tutorials / mailing lists.  This may not be thread safe but given that
-(as I write) large chunks of dak aren't even type-safe, I'll live with
-it for now
-
-@contact: Debian FTPMaster <ftpmaster@debian.org>
-@copyright: 2008  Mark Hymers <mhy@debian.org>
-@license: GNU General Public License version 2 or later
-"""
-
-################################################################################
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-################################################################################
-
-# < sgran> NCommander: in SQL, it's better to join than to repeat information
-# < tomv_w> that makes SQL the opposite to Debian mailing lists!
-
-################################################################################
-
-"""
-This class set implements objects that may need to be instantiated multiple
-times, but we don't want the overhead of actually creating and init'ing
-them more than once.  It also saves us using globals all over the place
-"""
-
-class Singleton(object):
-    """This is the ABC for other dak Singleton classes"""
-    __single = None
-    def __new__(cls, *args, **kwargs):
-        # Check to see if a __single exists already for this class
-        # Compare class types instead of just looking for None so
-        # that subclasses will create their own __single objects
-        if cls != type(cls.__single):
-            cls.__single = object.__new__(cls, *args, **kwargs)
-            cls.__single._startup(*args, **kwargs)
-        return cls.__single
-
-    def __init__(self, *args, **kwargs):
-        if type(self) == "Singleton":
-            raise NotImplementedError("Singleton is an ABC")
-
-    def _startup(self):
-        """
-        _startup is a private method used instead of __init__ due to the way
-        we instantiate this object
-        """
-        raise NotImplementedError("Singleton is an ABC")
-
old mode 100755 (executable)
new mode 100644 (file)
index 86300cc..60702c3
@@ -26,16 +26,15 @@ Simple summary class for dak
 
 ###############################################################################
 
-from singleton import Singleton
+class SummaryStats(object):
+    __shared_state = {}
 
-###############################################################################
-
-class SummaryStats(Singleton):
     def __init__(self, *args, **kwargs):
-        super(SummaryStats, self).__init__(*args, **kwargs)
+        self.__dict__ = self.__shared_state
 
-    def _startup(self):
-        self.reset_accept()
+        if not getattr(self, 'initialised', False):
+            self.initialised = True
+            self.reset_accept()
 
     def reset_accept(self):
         self.accept_count = 0
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index fb2e7fa..7d67905
@@ -29,33 +29,35 @@ Urgency Logger class for dak
 import os
 import time
 
-from singleton import Singleton
 from config import Config
 from utils import warn, open_file, move
 
 ###############################################################################
 
-class UrgencyLog(Singleton):
+class UrgencyLog(object):
     "Urgency Logger object"
+
+    __shared_state = {}
+
     def __init__(self, *args, **kwargs):
-        super(UrgencyLog, self).__init__(*args, **kwargs)
+        self.__dict__ = self.__shared_state
 
-    def _startup(self):
-        "Initialize a new Urgency Logger object"
+        if not getattr(self, 'initialised', False):
+            self.initialised = True
 
-        self.timestamp = time.strftime("%Y%m%d%H%M%S")
+            self.timestamp = time.strftime("%Y%m%d%H%M%S")
 
-        # Create the log directory if it doesn't exist
-        self.log_dir = Config()["Dir::UrgencyLog"]
+            # Create the log directory if it doesn't exist
+            self.log_dir = Config()["Dir::UrgencyLog"]
 
-        if not os.path.exists(self.log_dir) or not os.access(self.log_dir, os.W_OK):
-            warn("UrgencyLog directory %s does not exist or is not writeable, using /srv/ftp.debian.org/tmp/ instead" % (self.log_dir))
-            self.log_dir = '/srv/ftp.debian.org/tmp/'
+            if not os.path.exists(self.log_dir) or not os.access(self.log_dir, os.W_OK):
+                warn("UrgencyLog directory %s does not exist or is not writeable, using /srv/ftp.debian.org/tmp/ instead" % (self.log_dir))
+                self.log_dir = '/srv/ftp.debian.org/tmp/'
 
-        # Open the logfile
-        self.log_filename = "%s/.install-urgencies-%s.new" % (self.log_dir, self.timestamp)
-        self.log_file = open_file(self.log_filename, 'w')
-        self.writes = 0
+            # Open the logfile
+            self.log_filename = "%s/.install-urgencies-%s.new" % (self.log_dir, self.timestamp)
+            self.log_file = open_file(self.log_filename, 'w')
+            self.writes = 0
 
     def log(self, source, version, urgency):
         "Log an event"
old mode 100755 (executable)
new mode 100644 (file)
index 0528748..3cc4053
@@ -712,24 +712,23 @@ def where_am_i ():
         return res[0]
 
 def which_conf_file ():
-    if os.getenv("DAK_CONFIG"):
-        print(os.getenv("DAK_CONFIG"))
-        return os.getenv("DAK_CONFIG")
-    else:
-        res = socket.gethostbyaddr(socket.gethostname())
-        # In case we allow local config files per user, try if one exists
-        if Cnf.FindB("Config::" + res[0] + "::AllowLocalConfig"):
-            homedir = os.getenv("HOME")
-            confpath = os.path.join(homedir, "/etc/dak.conf")
-            if os.path.exists(confpath):
-                apt_pkg.ReadConfigFileISC(Cnf,default_config)
-
-        # We are still in here, so there is no local config file or we do
-        # not allow local files. Do the normal stuff.
-        if Cnf.get("Config::" + res[0] + "::DakConfig"):
-            return Cnf["Config::" + res[0] + "::DakConfig"]
-        else:
-            return default_config
+    if os.getenv('DAK_CONFIG'):
+        return os.getenv('DAK_CONFIG')
+
+    res = socket.gethostbyaddr(socket.gethostname())
+    # In case we allow local config files per user, try if one exists
+    if Cnf.FindB("Config::" + res[0] + "::AllowLocalConfig"):
+        homedir = os.getenv("HOME")
+        confpath = os.path.join(homedir, "/etc/dak.conf")
+        if os.path.exists(confpath):
+            apt_pkg.ReadConfigFileISC(Cnf,default_config)
+
+    # We are still in here, so there is no local config file or we do
+    # not allow local files. Do the normal stuff.
+    if Cnf.get("Config::" + res[0] + "::DakConfig"):
+        return Cnf["Config::" + res[0] + "::DakConfig"]
+
+    return default_config
 
 def which_apt_conf_file ():
     res = socket.gethostbyaddr(socket.gethostname())
@@ -1504,7 +1503,8 @@ def get_changes_files(from_dir):
 apt_pkg.init()
 
 Cnf = apt_pkg.newConfiguration()
-apt_pkg.ReadConfigFileISC(Cnf,default_config)
+if not os.getenv("DAK_TEST"):
+    apt_pkg.ReadConfigFileISC(Cnf,default_config)
 
 if which_conf_file() != default_config:
     apt_pkg.ReadConfigFileISC(Cnf,which_conf_file())
diff --git a/tests/base_test.py b/tests/base_test.py
new file mode 100644 (file)
index 0000000..d99ce41
--- /dev/null
@@ -0,0 +1,20 @@
+import os
+import sys
+import unittest
+
+from os.path import abspath, dirname, join
+
+DAK_ROOT_DIR = dirname(dirname(abspath(__file__)))
+
+class DakTestCase(unittest.TestCase):
+    def setUp(self):
+        pass
+
+def fixture(*dirs):
+    return join(DAK_ROOT_DIR, 'tests', 'fixtures', *dirs)
+
+os.environ['DAK_TEST'] = '1'
+os.environ['DAK_CONFIG'] = fixture('dak.conf')
+
+if DAK_ROOT_DIR not in sys.path:
+    sys.path.insert(0, DAK_ROOT_DIR)
diff --git a/tests/fixtures/changes/1.changes b/tests/fixtures/changes/1.changes
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/fixtures/changes/2.changes b/tests/fixtures/changes/2.changes
new file mode 100644 (file)
index 0000000..9d264c1
--- /dev/null
@@ -0,0 +1,54 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+Format: 1.7
+Date: Fri, 20 Apr 2001 02:47:21 -0400
+Source: krb5
+Binary: krb5-kdc krb5-doc krb5-rsh-server libkrb5-dev libkrb53 krb5-ftpd
+ krb5-clients krb5-user libkadm54 krb5-telnetd krb5-admin-server
+Architecture: m68k
+Version: 1.2.2-4
+Distribution: unstable
+Urgency: low
+Maintainer: buildd m68k user account <buildd@ax.westfalen.de>
+Changed-By: Sam Hartman <hartmans@debian.org>
+Description: 
+ krb5-admin-server - Mit Kerberos master server (kadmind)
+ krb5-clients - Secure replacements for ftp, telnet and rsh using MIT Kerberos
+ krb5-ftpd  - Secure FTP server supporting MIT Kerberos
+ krb5-kdc   - Mit Kerberos key server (KDC)
+ krb5-rsh-server - Secure replacements for rshd and rlogind  using MIT Kerberos
+ krb5-telnetd - Secure telnet server supporting MIT Kerberos
+ krb5-user  - Basic programs to authenticate using MIT Kerberos
+ libkadm54  - MIT Kerberos administration runtime libraries
+ libkrb5-dev - Headers and development libraries for MIT Kerberos
+ libkrb53   - MIT Kerberos runtime libraries
+Closes: 94407
+Changes: 
+ krb5 (1.2.2-4) unstable; urgency=low
+ .
+   * Fix shared libraries to build with gcc not ld to properly include
+     -lgcc symbols, closes: #94407
+Files: 
+ 563dac1cdd3ba922f9301fe074fbfc80 65836 non-us/main optional libkadm54_1.2.2-4_m68k.deb
+ bb620f589c17ab0ebea1aa6e10ca52ad 272198 non-us/main optional libkrb53_1.2.2-4_m68k.deb
+ 40af6e64b3030a179e0de25bd95c95e9 143264 non-us/main optional krb5-user_1.2.2-4_m68k.deb
+ ffe4e5e7b2cab162dc608d56278276cf 141870 non-us/main optional krb5-clients_1.2.2-4_m68k.deb
+ 4fe01d1acb4b82ce0b8b72652a9a15ae 54592 non-us/main optional krb5-rsh-server_1.2.2-4_m68k.deb
+ b3c8c617ea72008a33b869b75d2485bf 41292 non-us/main optional krb5-ftpd_1.2.2-4_m68k.deb
+ 5908f8f60fe536d7bfc1ef3fdd9d74cc 42090 non-us/main optional krb5-telnetd_1.2.2-4_m68k.deb
+ 650ea769009a312396e56503d0059ebc 160236 non-us/main optional krb5-kdc_1.2.2-4_m68k.deb
+ 399c9de4e9d7d0b0f5626793808a4391 160392 non-us/main optional krb5-admin-server_1.2.2-4_m68k.deb
+ 6f962fe530c3187e986268b4e4d27de9 398662 non-us/main optional libkrb5-dev_1.2.2-4_m68k.deb
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3i
+Charset: noconv
+
+iQCVAwUBOvVPPm547I3m3eHJAQHyaQP+M7RXVEqZ2/xHiPzaPcZRJ4q7o0zbMaU8
+qG/Mi6kuR1EhRNMjMH4Cp6ctbhRDHK5FR/8v7UkOd+ETDAhiw7eqJnLC60EZxZ/H
+CiOs8JklAXDERkQ3i7EYybv46Gxx91pIs2nE4xVKnG16d/wFELWMBLY6skF1B2/g
+zZju3cuFCCE=
+=Vm59
+-----END PGP SIGNATURE-----
+
+
diff --git a/tests/fixtures/changes/bogus-post.changes b/tests/fixtures/changes/bogus-post.changes
new file mode 100644 (file)
index 0000000..95e5a1f
--- /dev/null
@@ -0,0 +1,41 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.7
+Date: Tue,  9 Sep 2003 01:16:01 +0100
+Source: gawk
+Binary: gawk
+Architecture: source i386
+Version: 1:3.1.3-2
+Distribution: unstable
+Urgency: low
+Maintainer: James Troup <james@nocrew.org>
+Changed-By: James Troup <james@nocrew.org>
+Description: 
+ gawk       - GNU awk, a pattern scanning and processing language
+Closes: 204699 204701
+Changes: 
+ gawk (1:3.1.3-2) unstable; urgency=low
+ .
+   * debian/control (Standards-Version): bump to 3.6.1.0.
+ .
+   * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]].
+     Thanks to <vle@gmx.net> for reporting the bug and forwarding it
+     upstream.  Closes: #204701
+ .
+   * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix
+     [\x80-\xff].  Thanks to <vle@gmx.net> for reporting the bug and
+     forwarding it upstream.  Closes: #204699
+Files: 
+ 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc
+ 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz
+ 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+
+iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau
+fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB
+=O7Gh
+-----END PGP SIGNATURE-----
+You: have been 0wned
diff --git a/tests/fixtures/changes/bogus-pre.changes b/tests/fixtures/changes/bogus-pre.changes
new file mode 100644 (file)
index 0000000..0234d8b
--- /dev/null
@@ -0,0 +1,41 @@
+You: have been 0wned
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.7
+Date: Tue,  9 Sep 2003 01:16:01 +0100
+Source: gawk
+Binary: gawk
+Architecture: source i386
+Version: 1:3.1.3-2
+Distribution: unstable
+Urgency: low
+Maintainer: James Troup <james@nocrew.org>
+Changed-By: James Troup <james@nocrew.org>
+Description: 
+ gawk       - GNU awk, a pattern scanning and processing language
+Closes: 204699 204701
+Changes: 
+ gawk (1:3.1.3-2) unstable; urgency=low
+ .
+   * debian/control (Standards-Version): bump to 3.6.1.0.
+ .
+   * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]].
+     Thanks to <vle@gmx.net> for reporting the bug and forwarding it
+     upstream.  Closes: #204701
+ .
+   * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix
+     [\x80-\xff].  Thanks to <vle@gmx.net> for reporting the bug and
+     forwarding it upstream.  Closes: #204699
+Files: 
+ 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc
+ 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz
+ 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+
+iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau
+fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB
+=O7Gh
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/changes/valid.changes b/tests/fixtures/changes/valid.changes
new file mode 100644 (file)
index 0000000..0e77d27
--- /dev/null
@@ -0,0 +1,40 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.7
+Date: Tue,  9 Sep 2003 01:16:01 +0100
+Source: gawk
+Binary: gawk
+Architecture: source i386
+Version: 1:3.1.3-2
+Distribution: unstable
+Urgency: low
+Maintainer: James Troup <james@nocrew.org>
+Changed-By: James Troup <james@nocrew.org>
+Description: 
+ gawk       - GNU awk, a pattern scanning and processing language
+Closes: 204699 204701
+Changes: 
+ gawk (1:3.1.3-2) unstable; urgency=low
+ .
+   * debian/control (Standards-Version): bump to 3.6.1.0.
+ .
+   * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]].
+     Thanks to <vle@gmx.net> for reporting the bug and forwarding it
+     upstream.  Closes: #204701
+ .
+   * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix
+     [\x80-\xff].  Thanks to <vle@gmx.net> for reporting the bug and
+     forwarding it upstream.  Closes: #204699
+Files: 
+ 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc
+ 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz
+ 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+
+iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau
+fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB
+=O7Gh
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dak.conf b/tests/fixtures/dak.conf
new file mode 100644 (file)
index 0000000..94992fe
--- /dev/null
@@ -0,0 +1,19 @@
+# For extract_component_from_section tests
+
+Component
+{
+  main
+  {
+       Description "Main";
+  };
+
+  contrib
+  {
+       Description "Contrib";
+  };
+
+  non-free
+  {
+       Description "Software that fails to meet the DFSG";
+  };
+};
diff --git a/tests/fixtures/dsc/1.dsc b/tests/fixtures/dsc/1.dsc
new file mode 100644 (file)
index 0000000..dfdd92f
--- /dev/null
@@ -0,0 +1,22 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.0
+Source: amaya
+Version: 3.2.1-1
+Binary: amaya
+Maintainer: Steve Dunham <dunham@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files: 
+ 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
+ da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.2 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
+rhYnRmVuNMa8oYSvL4hl/Yw=
+=EFAA
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dsc/2.dsc b/tests/fixtures/dsc/2.dsc
new file mode 100644 (file)
index 0000000..a6c9d85
--- /dev/null
@@ -0,0 +1,21 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.0
+Source: amaya
+Version: 3.2.1-1
+Binary: amaya
+Maintainer: Steve Dunham <dunham@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files: 
+ 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
+ da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.2 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
+rhYnRmVuNMa8oYSvL4hl/Yw=
+=EFAA
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dsc/3.dsc b/tests/fixtures/dsc/3.dsc
new file mode 100644 (file)
index 0000000..211340e
--- /dev/null
@@ -0,0 +1,21 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+Format: 1.0
+Source: amaya
+Version: 3.2.1-1
+Binary: amaya
+Maintainer: Steve Dunham <dunham@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files: 
+ 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
+ da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.2 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
+rhYnRmVuNMa8oYSvL4hl/Yw=
+=EFAA
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dsc/4.dsc b/tests/fixtures/dsc/4.dsc
new file mode 100644 (file)
index 0000000..91e361f
--- /dev/null
@@ -0,0 +1,19 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+Format: 1.0
+Source: amaya
+Version: 3.2.1-1
+Binary: amaya
+Maintainer: Steve Dunham <dunham@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files: 
+ 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
+ da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.2 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
+rhYnRmVuNMa8oYSvL4hl/Yw=
+=EFAA
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dsc/5.dsc b/tests/fixtures/dsc/5.dsc
new file mode 100644 (file)
index 0000000..db9d8d3
--- /dev/null
@@ -0,0 +1,23 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.0
+Source: amaya
+Version: 3.2.1-1
+Binary: amaya
+Maintainer: Steve Dunham <dunham@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files: 
+ 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
+ da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
+
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.2 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
+rhYnRmVuNMa8oYSvL4hl/Yw=
+=EFAA
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dsc/6.dsc b/tests/fixtures/dsc/6.dsc
new file mode 100644 (file)
index 0000000..ae36d64
--- /dev/null
@@ -0,0 +1,23 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+
+Format: 1.0
+Source: amaya
+Version: 3.2.1-1
+Binary: amaya
+Maintainer: Steve Dunham <dunham@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files: 
+ 07f95f92b7cb0f12f7cf65ee5c5fbde2 4532418 amaya_3.2.1.orig.tar.gz
+ da06b390946745d9efaf9e7df8e05092 4817 amaya_3.2.1-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.2 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQE5j091iPgEjVqvb1kRAvFtAJ0asUAaac6ebfR3YeaH16HjL7F3GwCfV+AQ
+rhYnRmVuNMa8oYSvL4hl/Yw=
+=EFAA
+-----END PGP SIGNATURE-----
diff --git a/tests/fixtures/dsc/7.dsc b/tests/fixtures/dsc/7.dsc
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/test_extract_component_from_section.py b/tests/test_extract_component_from_section.py
new file mode 100755 (executable)
index 0000000..3493f41
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+from base_test import DakTestCase
+
+import unittest
+
+from daklib.utils import extract_component_from_section
+
+class ExtractComponentTestCase(DakTestCase):
+    """
+    prefix: non-US
+    component: main, contrib, non-free
+    section: games, admin, libs, [...]
+
+    [1] Order is as above.
+    [2] Prefix is optional for the default archive, but mandatory when
+        uploads are going anywhere else.
+    [3] Default component is main and may be omitted.
+    [4] Section is optional.
+    [5] Prefix is case insensitive
+    [6] Everything else is case sensitive.
+    """
+
+    def assertExtract(self, input, output):
+        self.assertEqual(
+            extract_component_from_section(input)[1],
+            output,
+        )
+
+    def test_1(self):
+        # Validate #3
+        self.assertExtract('utils', 'main')
+
+    def test_2(self):
+        # Err, whoops?  should probably be 'utils', 'main'...
+        self.assertExtract('main/utils', 'main')
+
+    def test_3(self):
+        self.assertExtract('non-free/libs', 'non-free')
+
+    def test_4(self):
+        self.assertExtract('contrib/net', 'contrib')
+
+    def test_5(self):
+        # Validate #4
+        self.assertExtract('main', 'main')
+
+    def test_6(self):
+        self.assertExtract('contrib', 'contrib')
+
+    def test_7(self):
+        self.assertExtract('non-free', 'non-free')
+
+    def test_8(self):
+        # Validate #6 (section)
+        self.assertExtract('utIls', 'main')
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_fix_maintainer.py b/tests/test_fix_maintainer.py
new file mode 100755 (executable)
index 0000000..203fbfc
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from base_test import DakTestCase
+
+import unittest
+
+from daklib.textutils import fix_maintainer
+from daklib.dak_exceptions import ParseMaintError
+
+class FixMaintainerTestCase(DakTestCase):
+    def assertValid(self, input, a, b, c, d):
+        a_, b_, c_, d_ = fix_maintainer(input)
+
+        self.assertEqual(a, a_)
+        self.assertEqual(b, b_)
+        self.assertEqual(c, c_)
+        self.assertEqual(d, d_)
+
+    def assertNotValid(self, input):
+        self.assertRaises(ParseMaintError, lambda: fix_maintainer(input))
+
+    def testUTF8Maintainer(self):
+        # Check Valid UTF-8 maintainer field
+        self.assertValid(
+            "Noèl Köthe <noel@debian.org>",
+            "Noèl Köthe <noel@debian.org>",
+            "=?utf-8?b?Tm/DqGwgS8O2dGhl?= <noel@debian.org>",
+            "Noèl Köthe",
+            "noel@debian.org",
+        )
+
+    def testASCII(self):
+        # Check valid ASCII maintainer field
+        self.assertValid(
+            "James Troup <james@nocrew.org>",
+            "James Troup <james@nocrew.org>",
+            "James Troup <james@nocrew.org>",
+            "James Troup",
+            "james@nocrew.org",
+        )
+
+    def testRFC822(self):
+        # Check "Debian vs RFC822" fixup of names with '.' or ',' in them
+        self.assertValid(
+            "James J. Troup <james@nocrew.org>",
+            "james@nocrew.org (James J. Troup)",
+            "james@nocrew.org (James J. Troup)",
+            "James J. Troup",
+            "james@nocrew.org",
+        )
+
+    def testSimple(self):
+        self.assertValid(
+            "James J, Troup <james@nocrew.org>",
+            "james@nocrew.org (James J, Troup)",
+            "james@nocrew.org (James J, Troup)",
+            "James J, Troup",
+            "james@nocrew.org",
+        )
+
+    def testJustEmail(self):
+        # Check just-email form
+        self.assertValid(
+            "james@nocrew.org",
+            " <james@nocrew.org>",
+            " <james@nocrew.org>",
+            "",
+            "james@nocrew.org",
+        )
+
+    def testBracketedEmail(self):
+        # Check bracketed just-email form
+        self.assertValid(
+            "<james@nocrew.org>",
+            " <james@nocrew.org>",
+            " <james@nocrew.org>",
+            "",
+            "james@nocrew.org",
+        )
+
+    def testKrazy(self):
+        # Check Krazy quoted-string local part email address
+        self.assertValid(
+            "Cris van Pelt <\"Cris van Pelt\"@tribe.eu.org>",
+            "Cris van Pelt <\"Cris van Pelt\"@tribe.eu.org>",
+            "Cris van Pelt <\"Cris van Pelt\"@tribe.eu.org>",
+            "Cris van Pelt",
+            "\"Cris van Pelt\"@tribe.eu.org",
+        )
+
+    def testEmptyString(self):
+        # Check empty string
+        self.assertValid("", "", "", "", "")
+
+    def testMissingEmailAddress(self):
+        # Check for missing email address
+        self.assertNotValid("James Troup")
+
+    def testInvalidEmail(self):
+        # Check for invalid email address
+        self.assertNotValid("James Troup <james@nocrew.org")
+
+if __name__ == '__main__':
+    unittest.main()
index 1ae6860aa60659ba890e9f00c31b1c02a9945ac9..a897eeb0b7df98a92b0c7b9acde9039363cd2fba 100755 (executable)
@@ -1,14 +1,13 @@
 #!/usr/bin/env python
 
-import unittest
+from base_test import DakTestCase
 
-import os, sys
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import unittest
 
 from daklib.formats import parse_format, validate_changes_format
 from daklib.dak_exceptions import UnknownFormatError
 
-class ParseFormatTestCase(unittest.TestCase):
+class ParseFormatTestCase(DakTestCase):
     def assertParse(self, format, expected):
         self.assertEqual(parse_format(format), expected)
 
@@ -30,7 +29,7 @@ class ParseFormatTestCase(unittest.TestCase):
         self.assertParse('1.2 (three)', (1, 2, 'three'))
         self.assertParseFail('0.0 ()')
 
-class ValidateChangesFormat(unittest.TestCase):
+class ValidateChangesFormat(DakTestCase):
     def assertValid(self, changes, field='files'):
         validate_changes_format(changes, field)
 
@@ -56,3 +55,6 @@ class ValidateChangesFormat(unittest.TestCase):
     def testFilesField(self):
         self.assertInvalid((1, 7), field='notfiles')
         self.assertValid((1, 8), field='notfiles')
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_lintian.py b/tests/test_lintian.py
new file mode 100755 (executable)
index 0000000..f4ed98e
--- /dev/null
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+from base_test import DakTestCase
+
+import unittest
+
+from daklib.lintian import parse_lintian_output, generate_reject_messages
+
+class ParseLintianTestCase(DakTestCase):
+    def assertParse(self, output, expected):
+        self.assertEqual(
+            list(parse_lintian_output(output)),
+            expected,
+        )
+
+    def testSimple(self):
+        self.assertParse(
+            'W: pkgname: some-tag path/to/file', [{
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'some-tag',
+                'description': 'path/to/file',
+            }],
+        )
+
+        self.assertParse('', [])
+        self.assertParse('\n\n', [])
+        self.assertParse('dummy error test', [])
+
+    def testBinaryNoDescription(self):
+        self.assertParse(
+            'W: pkgname: some-tag', [{
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'some-tag',
+                'description': '',
+            }],
+        )
+
+    def testSource(self):
+        self.assertParse(
+            'W: pkgname source: some-tag', [{
+                'level': 'W',
+                'package': 'pkgname source',
+                'tag': 'some-tag',
+                'description': '',
+            }]
+        )
+
+    def testSourceNoDescription(self):
+        self.assertParse(
+            'W: pkgname source: some-tag path/to/file', [{
+                'level': 'W',
+                'package': 'pkgname source',
+                'tag': 'some-tag',
+                'description': 'path/to/file',
+            }]
+        )
+
+class GenerateRejectMessages(DakTestCase):
+    def assertNumReject(self, input, defs, num):
+        msgs = list(generate_reject_messages(input, defs))
+        self.assertEqual(len(msgs), num)
+
+    def testUnknownTag(self):
+        self.assertNumReject([
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'unknown-tag',
+                'description': '',
+            }
+            ], {'fatal': ['known-tag'], 'nonfatal': []},
+            0,
+        )
+
+    def testFatalTags(self):
+        self.assertNumReject([
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'fatal-tag-1',
+                'description': '',
+            },
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'fatal-tag-2',
+                'description': '',
+            },
+            ], {'fatal': ['fatal-tag-1', 'fatal-tag-2'], 'nonfatal': []},
+            2,
+        )
+
+    def testMixture(self):
+        self.assertNumReject([
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'fatal-tag',
+                'description': '',
+            },
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'unknown-tag',
+                'description': '',
+            },
+            ], {'fatal': ['fatal-tag'], 'nonfatal': []},
+            1,
+        )
+
+    def testOverridable(self):
+        self.assertNumReject([
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'non-fatal-tag',
+                'description': '',
+            },
+            ], {'fatal': [], 'nonfatal': ['non-fatal-tag']},
+            1 + 1, # We add an extra 'reject' hint message
+        )
+
+    def testOverrideAllowed(self):
+        self.assertNumReject([
+                {'level': 'O',
+                'package': 'pkgname',
+                'tag': 'non-fatal-tag',
+                'description': ''},
+            ], {'fatal': [], 'nonfatal': ['non-fatal-tag']},
+            0,
+        )
+
+    def testOverrideNotAllowed(self):
+        self.assertNumReject([
+            {
+                'level': 'O',
+                'package': 'pkgname',
+                'tag': 'fatal-tag',
+                'description': '',
+            },
+            ], {'fatal': ['fatal-tag'], 'nonfatal': []},
+            1,
+        )
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_parse_changes.py b/tests/test_parse_changes.py
new file mode 100755 (executable)
index 0000000..2de4b8a
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+
+from base_test import DakTestCase, fixture
+
+import unittest
+
+from daklib.utils import parse_changes
+from daklib.dak_exceptions import InvalidDscError, ParseChangesError
+
+class ParseChangesTestCase(DakTestCase):
+    def assertParse(self, filename, *args):
+        return parse_changes(fixture(filename), *args)
+
+    def assertFails(self, filename, line=None, *args):
+        try:
+            self.assertParse(filename, *args)
+            self.fail('%s was not recognised as invalid' % filename)
+        except ParseChangesError:
+            pass
+        except InvalidDscError, actual_line:
+            if line is not None:
+                assertEqual(actual_line, line)
+
+class ParseDscTestCase(ParseChangesTestCase):
+    def test_1(self):
+        self.assertParse('dsc/1.dsc')
+
+    def test_1_ignoreErrors(self):
+        # Valid .dsc ; ignoring errors
+        self.assertParse('dsc/1.dsc', 0)
+
+    def test_2(self):
+        # Missing blank line before signature body
+        self.assertParse('dsc/2.dsc')
+
+    def test_2_ignoreErrors(self):
+        # Invalid .dsc ; ignoring errors
+        self.assertParse('dsc/2.dsc', 0)
+
+    def test_3(self):
+        # Missing blank line after signature header
+        self.assertParse('dsc/3.dsc')
+
+    def test_4(self):
+        # No blank lines at all
+        self.assertParse('dsc/4.dsc')
+
+    def test_5(self):
+        # Extra blank line before signature body
+        self.assertParse('dsc/5.dsc')
+
+    def test_6(self):
+        # Extra blank line after signature header
+        self.assertParse('dsc/6.dsc')
+
+class ParseChangesTestCase(ParseChangesTestCase):
+    def test_1(self):
+        # Empty changes
+        self.assertFails('changes/1.changes', line=5)
+
+    def test_2(self):
+        changes = self.assertParse('changes/2.changes', 0)
+
+        binaries = changes['binary']
+
+        self.assert_('krb5-ftpd' in binaries.split())
+
+    def test_3(self):
+        for filename in ('valid', 'bogus-pre', 'bogus-post'):
+            for strict_whitespace in (0, 1):
+                changes = self.assertParse(
+                    'changes/%s.changes' % filename,
+                    strict_whitespace,
+                )
+                self.failIf(changes.get('you'))
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_process_gpgv_output.py b/tests/test_process_gpgv_output.py
new file mode 100755 (executable)
index 0000000..ea1fb33
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+from base_test import DakTestCase
+
+import unittest
+
+from daklib.utils import process_gpgv_output
+
+class ProcessGPGVOutputTestCase(DakTestCase):
+    def assertParse(self, input, output):
+        self.assertEqual(process_gpgv_output(input)[0], output)
+
+    def assertNotParse(self, input):
+        ret = process_gpgv_output(input)
+        self.assertNotEqual(len(ret[1]), 0)
+
+    ##
+
+    def testEmpty(self):
+        self.assertParse('', {})
+
+    def testBroken(self):
+        self.assertNotParse('foo')
+        self.assertNotParse('  foo  ')
+        self.assertNotParse('[PREFIXPG:] KEY VAL1 VAL2 VAL3')
+
+    def testSimple(self):
+        self.assertParse(
+            '[GNUPG:] KEY VAL1 VAL2 VAL3',
+            {'KEY': ['VAL1', 'VAL2', 'VAL3']},
+        )
+
+    def testNoKeys(self):
+        self.assertParse('[GNUPG:] KEY', {'KEY': []})
+
+    def testDuplicate(self):
+        self.assertNotParse('[GNUPG:] TEST_KEY\n[GNUPG:] TEST_KEY')
+        self.assertNotParse('[GNUPG:] KEY VAL1\n[GNUPG:] KEY VAL2')
+
+    def testDuplicateSpecial(self):
+        # NODATA and friends are special
+        for special in ('NODATA', 'SIGEXPIRED', 'KEYEXPIRED'):
+            self.assertParse(
+                '[GNUPG:] %s\n[GNUPG:] %s' % (special, special),
+                {special: []},
+            )
+
+if __name__ == '__main__':
+    unittest.main()
index 766e73e49070a86fe798498aee38d9d9d29669dd..bde17275acd2c2509a3107254cbfc977880abaad 100755 (executable)
@@ -1,13 +1,10 @@
 #!/usr/bin/env python
 
-import unittest
-
-import os, sys
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+from base_test import DakTestCase
 
 from daklib import regexes
 
-class re_single_line_field(unittest.TestCase):
+class re_single_line_field(DakTestCase):
     MATCH = regexes.re_single_line_field.match
 
     def testSimple(self):
@@ -32,31 +29,51 @@ class re_single_line_field(unittest.TestCase):
         self.assertEqual(self.MATCH('Foo::bar').groups(), ('Foo', ':bar'))
         self.assertEqual(self.MATCH('Foo: :bar').groups(), ('Foo', ':bar'))
 
-class re_parse_lintian(unittest.TestCase):
+class re_parse_lintian(DakTestCase):
     MATCH = regexes.re_parse_lintian.match
 
     def testBinary(self):
         self.assertEqual(
-            self.MATCH('W: pkgname: some-tag path/to/file').groups(),
-            ('W', 'pkgname', 'some-tag', 'path/to/file')
+            self.MATCH('W: pkgname: some-tag path/to/file').groupdict(),
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'some-tag',
+                'description': 'path/to/file',
+            }
         )
 
     def testBinaryNoDescription(self):
         self.assertEqual(
-            self.MATCH('W: pkgname: some-tag').groups(),
-            ('W', 'pkgname', 'some-tag', '')
+            self.MATCH('W: pkgname: some-tag').groupdict(),
+            {
+                'level': 'W',
+                'package': 'pkgname',
+                'tag': 'some-tag',
+                'description': '',
+            }
         )
 
     def testSource(self):
         self.assertEqual(
-            self.MATCH('W: pkgname source: some-tag').groups(),
-            ('W', 'pkgname source', 'some-tag', '')
+            self.MATCH('W: pkgname source: some-tag').groupdict(),
+            {
+                'level': 'W',
+                'package': 'pkgname source',
+                'tag': 'some-tag',
+                'description': '',
+            }
         )
 
     def testSourceNoDescription(self):
         self.assertEqual(
-            self.MATCH('W: pkgname source: some-tag path/to/file').groups(),
-            ('W', 'pkgname source', 'some-tag', 'path/to/file')
+            self.MATCH('W: pkgname source: some-tag path/to/file').groupdict(),
+            {
+                'level': 'W',
+                'package': 'pkgname source',
+                'tag': 'some-tag',
+                'description': 'path/to/file',
+            }
         )
 
 if __name__ == '__main__':
index 4ecaf8b7fcc83925238f2473ed7961714158eee2..fa6f3b386c34aa3706d62b359f2755dc31ca70c1 100755 (executable)
@@ -1,17 +1,13 @@
 #!/usr/bin/env python
 
-import unittest
-
-import os, sys
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-from collections import defaultdict
+from base_test import DakTestCase
 
 from daklib import srcformats
+from collections import defaultdict
 from daklib.formats import parse_format
 from daklib.dak_exceptions import UnknownFormatError
 
-class SourceFormatTestCase(unittest.TestCase):
+class SourceFormatTestCase(DakTestCase):
     def get_rejects(self, has_vars):
         has = defaultdict(lambda: 0)
         has.update(has_vars)
@@ -104,7 +100,7 @@ class FormatTreeQuiltTestCase(SourceFormatTestCase):
             'native_tar': 1,
         })
 
-class FormatFromStringTestCase(unittest.TestCase):
+class FormatFromStringTestCase(DakTestCase):
     def assertFormat(self, txt, klass):
         self.assertEqual(srcformats.get_format_from_string(txt), klass)