Exemple #1
0
    def cacheIsUpToDate(self, flavor, cacheDir=None):
        """
        return True if there is a cache file on disk with product information
        for a given flavor which is newer than the information in the
        product database.  False is returned if the file does not exist
        or otherwise appears out-of-date.

        Note that this is different from cacheIsInSync()
        """
        if not cacheDir:
            cacheDir = self.dbpath
        cache = self._persistPath(flavor, cacheDir)
        if not os.path.exists(cache):
            return False

        # get the modification time of the cache file
        cache_mtime = os.stat(cache).st_mtime

        # check for user tag updates
        if cacheDir != self.dbpath and \
           Database(cacheDir).isNewerThan(cache_mtime):
            return False

        # this is slightly inaccurate: if data for any flavor in the database
        # is newer than this time, this isNewerThan() returns True
        return not Database(self.dbpath).isNewerThan(cache_mtime)
Exemple #2
0
    def _tryCache(self, dbpath, cacheDir, flavors, verbose=0):
        if not cacheDir or not os.path.exists(cacheDir):
            return False

        cacheOkay = True
        for flav in flavors:
            if not self.cacheIsUpToDate(flav, cacheDir):
                cacheOkay = False
                if verbose > 1:
                    print >>sys.stderr, "Regenerating missing or out-of-date cache for %s in %s" % (flav, dbpath)
                break

        if cacheOkay:
            self.reload(flavors, cacheDir, verbose=verbose)

            # do a final consistency check; do we have the same products
            dbnames = Database(dbpath).findProductNames()
            dbnames.sort()
            dbnames = " ".join(dbnames)

            cachenames = self.getProductNames()
            cachenames.sort()
            cachenames = " ".join(cachenames)

            if dbnames != cachenames:
                cacheOkay = False
                self.lookup = {}  # forget loaded data
                if verbose:
                    print >>sys.stderr, "Regenerating out-of-date cache for %s in\n   %s" % (flav, dbpath)

        return cacheOkay
Exemple #3
0
    def _tryCache(self, dbpath, cacheDir, flavors, verbose=0):
        if not cacheDir or not os.path.exists(cacheDir):
            return False

        cacheOkay = True
        for flav in flavors:
            if not self.cacheIsUpToDate(flav, cacheDir):
                cacheOkay = False
                if verbose > 1:
                    print >> sys.stderr, \
                          "Regenerating missing or out-of-date cache for %s in %s" % (flav, dbpath)
                break

        if cacheOkay:
            self.reload(flavors, cacheDir, verbose=verbose)

            # do a final consistency check; do we have the same products
            dbnames = Database(dbpath).findProductNames()
            dbnames.sort()
            dbnames = " ".join(dbnames)

            cachenames = self.getProductNames()
            cachenames.sort()
            cachenames = " ".join(cachenames)

            if dbnames != cachenames:
                cacheOkay = False
                self.lookup = {}  # forget loaded data
                if verbose:
                    print >> sys.stderr, \
                     "Regenerating out-of-date cache for %s in %s" % (flav, dbpath)

        return cacheOkay
Exemple #4
0
    def setUp(self):
        self.dbpath = os.path.join(testEupsStack, "ups_db")
        self.userdb = os.path.join(testEupsStack, "user_ups_db")
        if not os.path.exists(self.userdb):
            os.makedirs(self.userdb)

        self.db = Database(self.dbpath, self.userdb)

        self.pycur = os.path.join(self.dbpath, "python", "current.chain")
        if os.path.isfile(self.pycur + ".bak"):
            os.rename(self.pycur + ".bak", self.pycur)
Exemple #5
0
    def _loadUserTags(self, userTagDir=None):
        if not userTagDir:
            userTagDir = self.persistDir
        if not userTagDir or not os.path.exists(userTagDir):
            return

        db = Database(self.dbpath, userTagDir)
        prodnames = db.findProductNames()
        for pname in prodnames:
            for tag, version, flavor in db.getTagAssignments(pname, glob=False):
                self.assignTag(tag, pname, version, flavor)
Exemple #6
0
    def _loadUserTags(self, userTagDir=None):
        if not userTagDir:
            userTagDir = self.persistDir
        if not userTagDir or not os.path.exists(userTagDir):
            return

        db = Database(self.dbpath, userTagDir)
        prodnames = db.findProductNames()
        for pname in prodnames:
            for tag, version, flavor in db.getTagAssignments(pname,
                                                             glob=False):
                self.assignTag(tag, pname, version, flavor)
Exemple #7
0
    def refreshFromDatabase(self, userTagDir=None):
        """
        load product information directly from the database files on disk,
        overwriting any previous information.  If userTagDir is provided,
        user tag assignments will be explicitly loaded into the stack 
        (otherwise, the stack may not have user tags in it).
        """
        db = Database(self.dbpath, userTagDir)

        # forget!
        self.lookup = {}

        for prodname in db.findProductNames():
            for product in db.findProducts(prodname):
                self.addProduct(product)
Exemple #8
0
    def refreshFromDatabase(self, userTagDir=None):
        """
        load product information directly from the database files on disk,
        overwriting any previous information.  If userTagDir is provided,
        user tag assignments will be explicitly loaded into the stack
        (otherwise, the stack may not have user tags in it).
        """
        db = Database(self.dbpath, userTagDir)

        # forget!
        self.lookup = {}

        for prodname in db.findProductNames():
            for product in db.findProducts(prodname):
                self.addProduct(product)
Exemple #9
0
    def setUp(self):
        self.dbpath = os.path.join(testEupsStack, "ups_db")
        self.userdb = os.path.join(testEupsStack, "user_ups_db")
        if not os.path.exists(self.userdb):
            os.makedirs(self.userdb)

        self.db = Database(self.dbpath, self.userdb)

        self.pycur = os.path.join(self.dbpath,"python","current.chain")
        if os.path.isfile(self.pycur+".bak"):
            os.rename(self.pycur+".bak", self.pycur)
Exemple #10
0
class DatabaseTestCase(unittest.TestCase):
    def setUp(self):
        self.dbpath = os.path.join(testEupsStack, "ups_db")
        self.userdb = os.path.join(testEupsStack, "user_ups_db")
        if not os.path.exists(self.userdb):
            os.makedirs(self.userdb)

        self.db = Database(self.dbpath, self.userdb)

        self.pycur = os.path.join(self.dbpath, "python", "current.chain")
        if os.path.isfile(self.pycur + ".bak"):
            os.rename(self.pycur + ".bak", self.pycur)

    def tearDown(self):
        if os.path.isfile(self.pycur + ".bak"):
            os.rename(self.pycur + ".bak", self.pycur)

        if os.path.exists(self.userdb) and self.userdb.endswith("user_ups_db"):

            os.system("rm -rf " + self.userdb)

    def testFindProductNames(self):
        prods = self.db.findProductNames()
        self.assertEquals(len(prods), 6)
        expected = "cfitsio tcltk eigen mpich2 python doxygen".split()
        for p in expected:
            self.assert_(p in prods)

    def testFindVersions(self):
        vers = self.db.findVersions("goober")
        self.assertEquals(len(vers), 0)

        vers = self.db.findVersions("doxygen")
        self.assertEquals(len(vers), 2)
        expected = "1.5.7.1 1.5.9".split()
        for v in expected:
            self.assert_(v in vers)

    def testFindFlavors(self):
        flavs = self.db.findFlavors("doxygen")
        self.assertEquals(len(flavs), 2)
        expected = "Linux Linux64".split()
        for f in expected:
            self.assert_(f in flavs)

        flavs = self.db.findFlavors("doxygen", "1.5.9")
        self.assertEquals(len(flavs), 1)
        expected = "Linux64".split()
        for f in expected:
            self.assert_(f in flavs)

        flavs = self.db.findFlavors("doxygen", "1.5.10")
        self.assertEquals(len(flavs), 0)

    def testFindTags(self):
        self.assertRaises(ProductNotFound, self.db.findTags, "goober", "1.5.9",
                          "Linux64")

        tags = self.db.findTags("doxygen", "1.5.10", "Linux64")
        self.assertEquals(len(tags), 0)

        tags = self.db.findTags("doxygen", "1.5.9", "Linux64")
        self.assertEquals(len(tags), 0)

        tags = self.db.findTags("doxygen", "1.5.7.1", "Linux")
        self.assertEquals(len(tags), 1)
        self.assertEquals(tags[0], "current")

    def testFindProduct(self):
        prod = self.db.findProduct("doxygen", "1.5.9", "Linux")
        self.assert_(prod is None)

        prod = self.db.findProduct("doxygen", "1.5.10", "Linux")
        self.assert_(prod is None)

        prod = self.db.findProduct("goober", "1.5.10", "Linux")
        self.assert_(prod is None)

        prod = self.db.findProduct("doxygen", "1.5.9", "Linux64")
        self.assert_(prod is not None)
        self.assertEquals(prod.name, "doxygen")
        self.assertEquals(prod.version, "1.5.9")
        self.assertEquals(prod.flavor, "Linux64")
        self.assertEquals(prod.db, os.path.join(testEupsStack, "ups_db"))
        self.assertEquals(
            prod.dir,
            "/lsst/DC3/stacks/gcc433/04jun/Linux64/external/doxygen/1.5.9")
        self.assertEquals(
            prod.tablefile,
            "/lsst/DC3/stacks/gcc433/04jun/Linux64/external/doxygen/1.5.9/ups/doxygen.table"
        )
        self.assertEquals(len(prod.tags), 0)

        prod = self.db.findProduct("doxygen", "1.5.7.1", "Linux")
        self.assert_(prod is not None)
        self.assertEquals(prod.name, "doxygen")
        self.assertEquals(prod.version, "1.5.7.1")
        self.assertEquals(prod.flavor, "Linux")
        self.assertEquals(prod.db, os.path.join(testEupsStack, "ups_db"))
        self.assertEquals(
            prod.dir,
            "/home/rplante/wrk/NCSA/LSST/devlp/stacks/21mar/Linux/external/doxygen/1.5.7.1"
        )
        self.assertEquals(prod.tablefile, "none")
        self.assertEquals(len(prod.tags), 1)
        self.assertEquals(prod.tags[0], "current")

        # test correct formation of table file path
        prod = self.db.findProduct("python", "2.5.2", "Linux")
        self.assertEquals(prod.name, "python")
        self.assertEquals(prod.version, "2.5.2")
        self.assertEquals(prod.flavor, "Linux")
        self.assertEquals(prod.db, os.path.join(testEupsStack, "ups_db"))
        self.assert_(
            prod.tablefile.endswith("Linux/python/2.5.2/ups/python.table"))
        self.assert_(os.path.exists(prod.tablefile))

        # test autonormalization of product install directories.
        # The install directory (PROD_DIR) for this python is given
        # as a relative directory
        prod = self.db.findProduct("python", "2.5.2", "Linux")
        self.assert_(prod is not None)
        self.assertEquals(prod.name, "python")
        self.assertEquals(prod.version, "2.5.2")
        self.assertEquals(prod.flavor, "Linux")
        self.assertEquals(prod.db, os.path.join(testEupsStack, "ups_db"))
        expect_pdir = os.path.join(testEupsStack, "Linux/python/2.5.2")
        self.assertEquals(prod.dir, expect_pdir)
        expect_tfile = os.path.join(expect_pdir, "ups", "python.table")
        self.assertEquals(prod.tablefile, expect_tfile)

    def testFindProducts(self):
        prods = self.db.findProducts("doxygen")
        self.assertEquals(len(prods), 2)
        prod = filter(lambda d: d.version == "1.5.7.1", prods)[0]
        self.assertEquals(len(prod.tags), 1)
        self.assertEquals(prod.tags[0], "current")

        prods = self.db.findProducts("cfitsio")
        self.assertEquals(len(prods), 1)

        prods = self.db.findProducts("doxygen", flavors="Linux64")
        self.assertEquals(len(prods), 1)
        self.assertEquals(prods[0].version, "1.5.9")

        prods = self.db.findProducts("doxygen", "1.5.7.1")
        self.assertEquals(len(prods), 1)

    def testIsDeclared(self):
        self.assert_(self.db.isDeclared("doxygen"))
        self.assert_(self.db.isDeclared("doxygen", "1.5.9"))
        self.assert_(self.db.isDeclared("doxygen", "1.5.7.1"))
        self.assert_(self.db.isDeclared("doxygen", "1.5.9", "Linux64"))
        self.assert_(self.db.isDeclared("doxygen", flavor="Linux64"))
        self.assert_(self.db.isDeclared("doxygen", flavor="Linux"))
        self.assert_(not self.db.isDeclared("goober"))
        self.assert_(not self.db.isDeclared("goober", "1.0"))
        self.assert_(not self.db.isDeclared("doxygen", "1.5.10"))
        self.assert_(not self.db.isDeclared("doxygen", "1.5.9", "Linux"))

    def testUserTag(self):
        vers = self.db.getTaggedVersion("user:my", "python", "Linux")
        self.assert_(vers is None)

        self.db.assignTag("user:my", "python", "2.5.2")
        vers = self.db.getTaggedVersion("user:my", "python", "Linux")
        self.assertEquals(vers, "2.5.2")
        self.assert_(
            os.path.exists(os.path.join(self.userdb, "python", "my.chain")))

        tags = self.db.findTags("python", "2.5.2", "Linux")
        ntag = 2
        self.assertEquals(len(tags), ntag)
        self.assertEquals(tags.count("current"), 1)
        self.assertEquals(tags.count("user:my"), 1)

        prods = self.db.findProducts("python", "2.5.2")
        self.assertEquals(len(prods), 1)
        self.assertEquals(len(prods[0].tags), 2)
        self.assertEquals(tags[0], "current")
        self.assertEquals(tags[1], "user:my")

        self.db.unassignTag("user:my", "python")
        vers = self.db.getTaggedVersion("user:my", "python", "Linux")
        self.assert_(vers is None)
        self.assert_(not os.path.exists(
            os.path.join(self.userdb, "python", "my.chain")))

    def testAssignTag(self):
        if not os.path.exists(self.pycur + ".bak"):
            shutil.copyfile(self.pycur, self.pycur + ".bak")

        vers = self.db.getTaggedVersion("current", "python", "Linux")
        self.assertEquals(vers, "2.5.2")
        self.assertRaises(ProductNotFound, self.db.assignTag, "current",
                          "python", "2.7")

        self.db.assignTag("current", "python", "2.6")
        self.assertEquals(
            self.db.getTaggedVersion("current", "python", "Linux"), "2.6")
        self.db.assignTag("current", "python", "2.5.2")
        self.assertEquals(
            self.db.getTaggedVersion("current", "python", "Linux"), "2.5.2")

        tfile = self.db._tagFile("python", "stable")
        if os.path.exists(tfile): os.remove(tfile)
        try:
            self.db.assignTag("stable", "python", "2.6")
            self.assertEquals(
                self.db.getTaggedVersion("stable", "python", "Linux"), "2.6")
            self.db.unassignTag("stable", "python", "Linux")
            self.assert_(not os.path.exists(tfile))
        except:
            if os.path.exists(tfile): os.remove(file)
            raise

        tfile = self.db._tagFile("doxygen", "beta")
        if os.path.exists(tfile): os.remove(tfile)
        try:
            self.db.assignTag("beta", "doxygen", "1.5.9")
            self.db.assignTag("beta", "doxygen", "1.5.7.1")
            self.assertEquals(
                self.db.getTaggedVersion("beta", "doxygen", "Linux64"),
                "1.5.9")
            self.assertEquals(
                self.db.getTaggedVersion("beta", "doxygen", "Linux"),
                "1.5.7.1")
            self.db.unassignTag("beta", "doxygen", "Linux64")
            self.assertEquals(
                self.db.getTaggedVersion("beta", "doxygen", "Linux"),
                "1.5.7.1")
            self.assertEquals(
                self.db.getTaggedVersion("beta", "doxygen", "Linux64"), None)
            self.db.assignTag("beta", "doxygen", "1.5.9")
            self.db.unassignTag("beta", "doxygen", "Linux")
            self.assertEquals(
                self.db.getTaggedVersion("beta", "doxygen", "Linux64"),
                "1.5.9")
            self.assertEquals(
                self.db.getTaggedVersion("beta", "doxygen", "Linux"), None)
            self.db.assignTag("beta", "doxygen", "1.5.7.1")
            self.db.unassignTag("beta", "doxygen")
            self.assert_(not os.path.exists(tfile))
        except:
            if os.path.exists(tfile): os.remove(tfile)
            raise

        os.rename(self.pycur + ".bak", self.pycur)

    def testDeclare(self):
        pdir = self.db._productDir("base")
        if os.path.isdir(pdir):
            map(
                lambda r: os.remove(r),
                filter(lambda f: os.path.isfile(f),
                       map(lambda p: os.path.join(pdir, p), os.listdir(pdir))))
            os.removedirs(pdir)
        try:
            self.assert_(not os.path.exists(pdir))
            baseidir = os.path.join(testEupsStack, "Linux/base/1.0")
            base = Product("base",
                           "1.0",
                           "Linux",
                           baseidir,
                           os.path.join(baseidir, "ups/base.table"),
                           tags=["current"])
            self.db.declare(base)
            self.assert_(os.path.isdir(pdir))
            self.assert_(os.path.isfile(os.path.join(pdir, "1.0.version")))
            self.assert_(os.path.isfile(os.path.join(pdir, "current.chain")))
            prods = self.db.findProducts("base")
            self.assertEquals(len(prods), 1)
            self.assertEquals(prods[0].name, "base")
            self.assertEquals(prods[0].version, "1.0")
            self.assertEquals(prods[0].flavor, "Linux")
            self.assertEquals(prods[0].dir, baseidir)
            self.assertEquals(prods[0].tablefile,
                              os.path.join(baseidir, "ups/base.table"))
            self.assertEquals(len(prods[0].tags), 1)
            self.assertEquals(prods[0].tags[0], "current")

            base2 = prods[0].clone()
            base2.version = "2.0"
            base2.tags = []
            self.db.declare(base2)
            self.assertEquals(
                self.db.getTaggedVersion("current", "base", "Linux"), "1.0")
            base3 = prods[0].clone()
            base3.version = "3.0"
            self.db.declare(base3)
            self.assertEquals(
                self.db.getTaggedVersion("current", "base", "Linux"), "3.0")

            self.assertEquals(len(self.db.findProducts("base")), 3)

            self.db.undeclare(base)
            self.assertEquals(self.db.findProduct("base", "1.0", "Linux"),
                              None)
            self.assertEquals(len(self.db.findProducts("base")), 2)
            self.assert_(not os.path.exists(os.path.join(pdir, "1.0.version")))

            self.db.undeclare(base3)
            self.assertEquals(self.db.findProduct("base", "3.0", "Linux"),
                              None)
            self.assertEquals(len(self.db.findProducts("base")), 1)
            self.assert_(not os.path.exists(os.path.join(pdir, "3.0.version")))
            self.assertEquals(
                self.db.getTaggedVersion("current", "base", "Linux"), None)
            self.assert_(
                not os.path.exists(os.path.join(pdir, "current.chain")))
            self.db.undeclare(base2)
            self.assertEquals(len(self.db.findProducts("base")), 0)
            self.assert_(not os.path.exists(pdir))

        except:
            if False:
                if os.path.isdir(pdir):
                    map(
                        lambda r: os.remove(r),
                        filter(
                            lambda f: os.path.isfile(f),
                            map(lambda p: os.path.join(pdir, p),
                                os.listdir(pdir))))
                    os.removedirs(pdir)
            raise
Exemple #11
0
class DatabaseTestCase(unittest.TestCase):

    def setUp(self):
        self.dbpath = os.path.join(testEupsStack, "ups_db")
        self.userdb = os.path.join(testEupsStack, "user_ups_db")
        if not os.path.exists(self.userdb):
            os.makedirs(self.userdb)

        self.db = Database(self.dbpath, self.userdb)

        self.pycur = os.path.join(self.dbpath,"python","current.chain")
        if os.path.isfile(self.pycur+".bak"):
            os.rename(self.pycur+".bak", self.pycur)

    def tearDown(self):
        if os.path.isfile(self.pycur+".bak"):
            os.rename(self.pycur+".bak", self.pycur)

        if os.path.exists(self.userdb) and self.userdb.endswith("user_ups_db"):

            os.system("rm -rf " + self.userdb)

    def testFindProductNames(self):
        prods = self.db.findProductNames()
        self.assertEqual(len(prods), 6)
        expected = "cfitsio tcltk eigen mpich2 python doxygen".split()
        for p in expected:
            self.assertIn(p, prods)

    def testFindVersions(self):
        vers = self.db.findVersions("goober")
        self.assertEqual(len(vers), 0)

        vers = self.db.findVersions("doxygen")
        self.assertEqual(len(vers), 2)
        expected = "1.5.7.1 1.5.9".split()
        for v in expected:
            self.assertIn(v, vers)

    def testFindFlavors(self):
        flavs = self.db.findFlavors("doxygen")
        self.assertEqual(len(flavs), 2)
        expected = "Linux Linux64".split()
        for f in expected:
            self.assertIn(f, flavs)

        flavs = self.db.findFlavors("doxygen", "1.5.9")
        self.assertEqual(len(flavs), 1)
        expected = "Linux64".split()
        for f in expected:
            self.assertIn(f, flavs)

        flavs = self.db.findFlavors("doxygen", "1.5.10")
        self.assertEqual(len(flavs), 0)

    def testFindTags(self):
        self.assertRaises(ProductNotFound, self.db.findTags,
                          "goober", "1.5.9", "Linux64")

        tags = self.db.findTags("doxygen", "1.5.10", "Linux64")
        self.assertEqual(len(tags), 0)

        tags = self.db.findTags("doxygen", "1.5.9", "Linux64")
        self.assertEqual(len(tags), 0)

        tags = self.db.findTags("doxygen", "1.5.7.1", "Linux")
        self.assertEqual(len(tags), 1)
        self.assertEqual(tags[0], "current")

    def testFindProduct(self):
        prod = self.db.findProduct("doxygen", "1.5.9", "Linux")
        self.assert_(prod is None)

        prod = self.db.findProduct("doxygen", "1.5.10", "Linux")
        self.assert_(prod is None)

        prod = self.db.findProduct("goober", "1.5.10", "Linux")
        self.assert_(prod is None)

        prod = self.db.findProduct("doxygen", "1.5.9", "Linux64")
        self.assert_(prod is not None)
        self.assertEqual(prod.name, "doxygen")
        self.assertEqual(prod.version, "1.5.9")
        self.assertEqual(prod.flavor, "Linux64")
        self.assertEqual(prod.db, os.path.join(testEupsStack, "ups_db"))
        self.assertEqual(prod.dir,
                "/lsst/DC3/stacks/gcc433/04jun/Linux64/external/doxygen/1.5.9")
        self.assertEqual(prod.tablefile, "/lsst/DC3/stacks/gcc433/04jun/Linux64/external/doxygen/1.5.9/ups/doxygen.table")
        self.assertEqual(len(prod.tags), 0)

        prod = self.db.findProduct("doxygen", "1.5.7.1", "Linux")
        self.assert_(prod is not None)
        self.assertEqual(prod.name, "doxygen")
        self.assertEqual(prod.version, "1.5.7.1")
        self.assertEqual(prod.flavor, "Linux")
        self.assertEqual(prod.db, os.path.join(testEupsStack, "ups_db"))
        self.assertEqual(prod.dir,
                "/home/rplante/wrk/NCSA/LSST/devlp/stacks/21mar/Linux/external/doxygen/1.5.7.1")
        self.assertEqual(prod.tablefile, "none")
        self.assertEqual(len(prod.tags), 1)
        self.assertEqual(prod.tags[0], "current")

        # test correct formation of table file path
        prod = self.db.findProduct("python", "2.5.2", "Linux")
        self.assertEqual(prod.name, "python")
        self.assertEqual(prod.version, "2.5.2")
        self.assertEqual(prod.flavor, "Linux")
        self.assertEqual(prod.db, os.path.join(testEupsStack, "ups_db"))
        self.assert_(prod.tablefile.endswith("Linux/python/2.5.2/ups/python.table"))
        self.assert_(os.path.exists(prod.tablefile))

        # test autonormalization of product install directories.
        # The install directory (PROD_DIR) for this python is given
        # as a relative directory
        prod = self.db.findProduct("python", "2.5.2", "Linux")
        self.assert_(prod is not None)
        self.assertEqual(prod.name, "python")
        self.assertEqual(prod.version, "2.5.2")
        self.assertEqual(prod.flavor, "Linux")
        self.assertEqual(prod.db, os.path.join(testEupsStack, "ups_db"))
        expect_pdir = os.path.join(testEupsStack, "Linux/python/2.5.2")
        self.assertEqual(prod.dir, expect_pdir)
        expect_tfile = os.path.join(expect_pdir, "ups", "python.table")
        self.assertEqual(prod.tablefile, expect_tfile)

    def testFindProducts(self):
        prods = self.db.findProducts("doxygen")
        self.assertEqual(len(prods), 2)
        prod = next(d for d in prods if d.version == "1.5.7.1") # this idiom efficiently returns the first element in a sequence
        self.assertEqual(len(prod.tags), 1)
        self.assertEqual(prod.tags[0], "current")

        prods = self.db.findProducts("cfitsio")
        self.assertEqual(len(prods), 1)

        prods = self.db.findProducts("doxygen", flavors="Linux64")
        self.assertEqual(len(prods), 1)
        self.assertEqual(prods[0].version, "1.5.9")

        prods = self.db.findProducts("doxygen", "1.5.7.1")
        self.assertEqual(len(prods), 1)

    def testIsDeclared(self):
        self.assert_(self.db.isDeclared("doxygen"))
        self.assert_(self.db.isDeclared("doxygen", "1.5.9"))
        self.assert_(self.db.isDeclared("doxygen", "1.5.7.1"))
        self.assert_(self.db.isDeclared("doxygen", "1.5.9", "Linux64"))
        self.assert_(self.db.isDeclared("doxygen", flavor="Linux64"))
        self.assert_(self.db.isDeclared("doxygen", flavor="Linux"))
        self.assert_(not self.db.isDeclared("goober"))
        self.assert_(not self.db.isDeclared("goober", "1.0"))
        self.assert_(not self.db.isDeclared("doxygen", "1.5.10"))
        self.assert_(not self.db.isDeclared("doxygen", "1.5.9", "Linux"))

    def testUserTag(self):
        vers = self.db.getTaggedVersion("user:my", "python", "Linux")[1]
        self.assert_(vers is None)

        self.db.assignTag("user:my", "python", "2.5.2")
        vers = self.db.getTaggedVersion("user:my", "python", "Linux")[1]
        self.assertEqual(vers, "2.5.2")
        self.assert_(os.path.exists(os.path.join(self.userdb,
                                                 "python","my.chain")))

        tags = self.db.findTags("python", "2.5.2", "Linux")
        ntag = 2
        self.assertEqual(len(tags), ntag)
        self.assertEqual(tags.count("current"), 1)
        self.assertEqual(tags.count("user:my"), 1)

        prods = self.db.findProducts("python", "2.5.2")
        self.assertEqual(len(prods), 1)
        self.assertEqual(len(prods[0].tags), 2)
        self.assertEqual(tags[0], "current")
        self.assertEqual(tags[1], "user:my")

        self.db.unassignTag("user:my", "python")
        vers = self.db.getTaggedVersion("user:my", "python", "Linux")[1]
        self.assert_(vers is None)
        self.assert_(not os.path.exists(os.path.join(self.userdb,
                                                     "python","my.chain")))

    def testAssignTag(self):
        if not os.path.exists(self.pycur+".bak"):
            shutil.copyfile(self.pycur, self.pycur+".bak")

        vers = self.db.getTaggedVersion("current", "python", "Linux")[1]
        self.assertEqual(vers, "2.5.2")
        self.assertRaises(ProductNotFound,
                          self.db.assignTag, "current", "python", "2.7")

        self.db.assignTag("current", "python", "2.6")
        self.assertEqual(self.db.getTaggedVersion("current","python","Linux"),
                          ("python", "2.6"))
        self.db.assignTag("current", "python", "2.5.2")
        self.assertEqual(self.db.getTaggedVersion("current","python","Linux"),
                          ("python", "2.5.2"))

        tfile = self.db._tagFile("python", "stable")
        if os.path.exists(tfile):  os.remove(tfile)
        try:
            self.db.assignTag("stable", "python", "2.6")
            self.assertEqual(self.db.getTaggedVersion("stable","python",
                                                       "Linux"),
                              ("python", "2.6"))
            self.db.unassignTag("stable", "python", "Linux")
            self.assert_(not os.path.exists(tfile))
        except:
            if os.path.exists(tfile): os.remove(file)
            raise

        tfile = self.db._tagFile("doxygen", "beta")
        if os.path.exists(tfile):  os.remove(tfile)
        try:
            self.db.assignTag("beta", "doxygen", "1.5.9")
            self.db.assignTag("beta", "doxygen", "1.5.7.1")
            self.assertEqual(self.db.getTaggedVersion("beta","doxygen",
                                                       "Linux64")[1],
                              "1.5.9")
            self.assertEqual(self.db.getTaggedVersion("beta","doxygen",
                                                       "Linux")[1],
                              "1.5.7.1")
            self.db.unassignTag("beta", "doxygen", "Linux64")
            self.assertEqual(self.db.getTaggedVersion("beta","doxygen",
                                                       "Linux")[1],
                              "1.5.7.1")
            self.assertEqual(self.db.getTaggedVersion("beta","doxygen",
                                                       "Linux64")[1],
                              None)
            self.db.assignTag("beta", "doxygen", "1.5.9")
            self.db.unassignTag("beta", "doxygen", "Linux")
            self.assertEqual(self.db.getTaggedVersion("beta","doxygen",
                                                       "Linux64")[1],
                              "1.5.9")
            self.assertEqual(self.db.getTaggedVersion("beta","doxygen",
                                                       "Linux")[1],
                              None)
            self.db.assignTag("beta", "doxygen", "1.5.7.1")
            self.db.unassignTag("beta", "doxygen")
            self.assert_(not os.path.exists(tfile))
        except:
            if os.path.exists(tfile):  os.remove(tfile)
            raise

        os.rename(self.pycur+".bak", self.pycur)

    def testDeclare(self):
        pdir = self.db._productDir("base")
        if os.path.isdir(pdir):
            for p in os.listdir(pdir):
                f = os.path.join(pdir, p)
                if os.path.isfile(f):
                    os.remove(f)
            os.removedirs(pdir)
        try:
            self.assert_(not os.path.exists(pdir))
            baseidir = os.path.join(testEupsStack,"Linux/base/1.0")
            base = Product("base", "1.0", "Linux", baseidir,
                           os.path.join(baseidir, "ups/base.table"),
                           tags=["current"])
            self.db.declare(base)
            self.assert_(os.path.isdir(pdir))
            self.assert_(os.path.isfile(os.path.join(pdir,"1.0.version")))
            self.assert_(os.path.isfile(os.path.join(pdir,"current.chain")))
            prods = self.db.findProducts("base")
            self.assertEqual(len(prods), 1)
            self.assertEqual(prods[0].name, "base")
            self.assertEqual(prods[0].version, "1.0")
            self.assertEqual(prods[0].flavor, "Linux")
            self.assertEqual(prods[0].dir, baseidir)
            self.assertEqual(prods[0].tablefile,
                              os.path.join(baseidir, "ups/base.table"))
            self.assertEqual(len(prods[0].tags), 1)
            self.assertEqual(prods[0].tags[0], "current")

            base2 = prods[0].clone()
            base2.version = "2.0"
            base2.tags = []
            self.db.declare(base2)
            self.assertEqual(self.db.getTaggedVersion("current", "base",
                                                       "Linux"),
                              ("base", "1.0"))
            base3 = prods[0].clone()
            base3.version = "3.0"
            self.db.declare(base3)
            self.assertEqual(self.db.getTaggedVersion("current", "base",
                                                       "Linux"),
                              ("base", "3.0"))

            self.assertEqual(len(self.db.findProducts("base")), 3)

            self.db.undeclare(base)
            self.assertEqual(self.db.findProduct("base","1.0","Linux"), None)
            self.assertEqual(len(self.db.findProducts("base")), 2)
            self.assert_(not os.path.exists(os.path.join(pdir,"1.0.version")))

            self.db.undeclare(base3)
            self.assertEqual(self.db.findProduct("base","3.0","Linux"), None)
            self.assertEqual(len(self.db.findProducts("base")), 1)
            self.assert_(not os.path.exists(os.path.join(pdir,"3.0.version")))
            self.assertEqual(self.db.getTaggedVersion("current", "base",
                                                       "Linux")[1],
                              None)
            self.assert_(not os.path.exists(os.path.join(pdir,"current.chain")))
            self.db.undeclare(base2)
            self.assertEqual(len(self.db.findProducts("base")), 0)
            self.assert_(not os.path.exists(pdir))

        except:
            if False:
              if os.path.isdir(pdir):
                  for p in os.listdir(pdir):
                      f = os.path.join(pdir, p)
                      if os.path.isfile(f):
                          os.remove(f)
                  os.removedirs(pdir)
            raise