From 00eb2233b7791333ac286bc93e25ca8d1f36b42e Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Fri, 9 Mar 2007 11:23:18 +0000 Subject: [PATCH] Merged from trunk 6185:6199 For bug #169620, in --tree display always show the dowload size on the node that is "ordered" rather than one of it's "nomerge" counterparts. Fix 2 more types.InstanceType comparisons that are broken by the transition of dbapi to new-style classes. Take marien's advice, turn Skips into Todos for clarity sake Part of my attempt now involves cleaning up config; this means for me; removing the file-based stuff from it (config_path) and encapsulating that into classes. This is the first one, a simple PackageKeywords class that does file-based stuff, no recursion yet but soon. Trying to do TDD here as well,so tests first then code. Change load() to have no default arguments, makes caller specifiy explicitly...I think assuming a default arg is bad here. Also add PackageUse and PackageUseFile, change up the comments a bit. I've started to notice code re-use here; these are basically the same code. I think I will write up the rest of the package* classes and then perform code merges to save LOC and memory and whatnot add PackageMask{File} classes, change unit tests to use try/finally, makes sure the tempfile gets destroyed even if something weird happens whoopse, s/;/:/ (WarnerBro) Remove legacy "masked by: profile" support as per bug #149508. Profiles should use package.mask to mask unwanted versions of system packages. Use the full atoms from the system set, since profile masking does not automatically constrain the matches anymore. Remove the "masked by: profile" support from getmaskingstatus(). Remove profile masking of system packages from the docs. Display message about --buildpkgonly restriction in pretend mode as well svn path=/main/branches/prefix/; revision=6200 --- NEWS | 2 + man/portage.5 | 15 +- pym/emerge/__init__.py | 16 +- pym/portage/__init__.py | 16 +- pym/portage/dbapi/porttree.py | 17 -- pym/portage/env/__init__.py | 4 + pym/portage/env/config.py | 169 ++++++++++++++++++ pym/portage/tests/__init__.py | 43 ++--- pym/portage/tests/dep/test_isvalidatom.py | 4 +- pym/portage/tests/env/__init__.py | 5 + pym/portage/tests/env/config/__init__.py | 5 + .../env/config/test_PackageKeywordsFile.py | 37 ++++ .../tests/env/config/test_PackageMaskFile.py | 30 ++++ .../tests/env/config/test_PackageUseFile.py | 35 ++++ 14 files changed, 324 insertions(+), 74 deletions(-) create mode 100644 pym/portage/env/__init__.py create mode 100644 pym/portage/env/config.py create mode 100644 pym/portage/tests/env/__init__.py create mode 100644 pym/portage/tests/env/config/__init__.py create mode 100644 pym/portage/tests/env/config/test_PackageKeywordsFile.py create mode 100644 pym/portage/tests/env/config/test_PackageMaskFile.py create mode 100644 pym/portage/tests/env/config/test_PackageUseFile.py diff --git a/NEWS b/NEWS index d0d6886ae..52fc11b48 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ News (mainly features/major bug fixes) portage-2.1.3 ------------- +* Legacy "masked by: profile" support has been removed. Profiles should use + package.mask to mask unwanted versions of system packages. * Allow per-module setting of PORTAGE_ELOG_CLASSES * Add ** as new token for package.keywords to bypass the keyword visibility layer * Namespace sanitizing: move all portage related code into portage.* namespace, diff --git a/man/portage.5 b/man/portage.5 index b59eb0a0e..9c3ae32cf 100644 --- a/man/portage.5 +++ b/man/portage.5 @@ -165,14 +165,12 @@ Special USE flags used by catalyst for building a stage3 and GRP sets. .PD 1 .TP .BR packages -This file serves two purposes. The first is to mask out specific -packages/versions on a per\-profile basis. The second is to provide the -list of packages that compose the special \fIsystem\fR set. +Provides the list of packages that compose the special \fIsystem\fR set. .I Format: .nf \- comments begin with # -\- one DEPEND atom per line of what to mask OUT +\- one DEPEND atom per line \- packages to be added to the system set begin with a * .fi .I Note: @@ -183,12 +181,11 @@ a '\-'. .I Example: .nf # i am a comment ! -# only allow versions of glibc less than 2.3 ->> cpv [-~]keyword1 [-~]keyword2 keyword3 + >>> Exceptions include -*, ~*, and ** for keywords. + """ + + if os.path.exists( self.fname ): + f = open(self.fname, 'rb') + for line in f: + if line.startswith('#'): + continue + split = line.split() + if len(split): + # Surprisingly this works for iterables of length 1 + # fex ['sys-apps/portage','x86','amd64'] becomes {'sys-apps/portage':['x86','amd64']} + key, items = split[0],split[1:] + # if they specify the same cpv twice; stack the values (append) instead of overwriting. + if key in self.data: + self.data[key].append(items) + else: + self.data[key] = items + +class PackageUse(UserDict): + """ + A base class stub for things to inherit from; some people may want a database based package.keywords or something + + Internally dict has pairs of the form + {'cpv':['flag1','flag22','flag3'...] + """ + + data = {} + + def iteritems(self): + return self.data.iteritems() + + def __hash__(self): + return hash(self.data) + + def __contains__(self, other): + return other in self.data + + def keys(self): + return self.data.keys() + +class PackageUseFile(PackageUse): + """ + Inherits from PackageUse; implements a file-based backend. Doesn't handle recursion yet. + """ + def __init__(self, filename): + self.fname = filename + + def load(self, recursive): + """ + Package.keywords files have comments that begin with #. + The entries are of the form: + >>> atom useflag1 useflag2 useflag3.. + useflags may optionally be negative with a minus sign (-) + >>> atom useflag1 -useflag2 useflag3 + """ + + if os.path.exists( self.fname ): + f = open(self.fname, 'rb') + for line in f: + if line.startswith('#'): + continue + split = line.split() + if len(split): + # Surprisingly this works for iterables of length 1 + # fex ['sys-apps/portage','foo','bar'] becomes {'sys-apps/portage':['foo','bar']} + key, items = split[0],split[1:] + # if they specify the same cpv twice; stack the values (append) instead of overwriting. + if key in self.data: + self.data[key].append(items) + else: + self.data[key] = items + +class PackageMask(UserDIct): + """ + A base class for Package.mask functionality + """ + data = {} + + def iteritems(self): + return self.data.iteritems() + + def __hash__(self): + return hash(self.data) + + def __contains__(self, other): + return other in self.data + + def keys(self): + return self.data.keys() + + def iterkeys(self): + return self.data.iterkeys() + +class PackageMaskFile(PackageMask): + """ + A class that implements a file-based package.mask + + Entires in package.mask are of the form: + atom1 + atom2 + or optionally + -atom3 + to revert a previous mask; this only works when masking files are stacked + """ + + def __init__(self, filename): + self.fname = filename + + def load(self, recursive): + """ + Package.keywords files have comments that begin with #. + The entries are of the form: + >>> atom useflag1 useflag2 useflag3.. + useflags may optionally be negative with a minus sign (-) + >>> atom useflag1 -useflag2 useflag3 + """ + + if os.path.exists( self.fname ): + f = open(self.fname, 'rb') + for line in f: + if line.startswith('#'): + continue + split = line.split() + if len(split): + atom = split[0] # This is an extra assignment, but I think it makes the code more explicit in what goes into the dict + self.data[atom] = None # we only care about keys in the dict, basically abusing it as a list diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index 56fc869c2..7d13af1e6 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -7,7 +7,7 @@ import os, unittest, time import portage.tests def main(): - testDirs = ["util","versions", "dep", "xpak"] + testDirs = ["util","versions", "dep", "xpak", "env/config"] suite = unittest.TestSuite() basedir = os.path.dirname(__file__) for mydir in testDirs: @@ -37,36 +37,29 @@ def getTests( path, base_path ): parent_module = parent_module.replace('/','.') result = [] for mymodule in files: - try: - # Make the trailing / a . for module importing - modname = ".".join((parent_module, mymodule)) - mod = my_import(modname) - result.append( unittest.TestLoader().loadTestsFromModule(mod) ) - except ImportError: - raise + # Make the trailing / a . for module importing + modname = ".".join((parent_module, mymodule)) + mod = my_import(modname) + result.append( unittest.TestLoader().loadTestsFromModule(mod) ) return result -class SkipException(Exception): - pass - class TextTestResult(unittest._TextTestResult): """ - We need a subclass of unittest._TextTestResult to handle skipped - tests. + We need a subclass of unittest._TextTestResult to handle tests with TODO - This just adds an addSkip method that can be used to add - skipped tests to the result; these can be displayed later + This just adds an addTodo method that can be used to add tests + that are marked TODO; these can be displayed later by the test runner. """ def __init__( self, stream, descriptions, verbosity ): unittest._TextTestResult.__init__( self, stream, descriptions, verbosity ) - self.skipped = [] + self.todoed = [] - def addSkip( self, test, info ): - self.skipped.append((test,info)) + def addTodo( self, test, info ): + self.todoed.append((test,info)) if self.showAll: - self.stream.writeln("FAIL AND SKIP") + self.stream.writeln("TODO") elif self.dots: self.stream.write(".") @@ -75,7 +68,7 @@ class TextTestResult(unittest._TextTestResult): self.stream.writeln() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) - self.printErrorList('SKIP', self.skipped) + self.printErrorList('TODO', self.todoed) class TestCase(unittest.TestCase): """ @@ -85,14 +78,13 @@ class TestCase(unittest.TestCase): (broken code!!??!11oneone) but it does happen at times. """ - SkipException = SkipException - def __init__(self, methodName='runTest'): # This method exists because unittest.py in python 2.4 stores # the methodName as __testMethodName while 2.5 uses # _testMethodName. self._testMethodName = methodName unittest.TestCase.__init__(self, methodName) + self.todo = False def defaultTestResult(self): return TextTestResult() @@ -114,9 +106,10 @@ class TestCase(unittest.TestCase): testMethod() ok = True except self.failureException: - result.addFailure(self, self._exc_info()) - except self.SkipException: - result.addSkip(self,"%s: Failed but Skippable" % testMethod) + if self.todo: + result.addTodo(self,"%s: TODO" % testMethod) + else: + result.addFailure(self, self._exc_info()) except KeyboardInterrupt: raise except: diff --git a/pym/portage/tests/dep/test_isvalidatom.py b/pym/portage/tests/dep/test_isvalidatom.py index 5f0149120..512d9b465 100644 --- a/pym/portage/tests/dep/test_isvalidatom.py +++ b/pym/portage/tests/dep/test_isvalidatom.py @@ -13,7 +13,8 @@ class IsValidAtom(TestCase): """ def testIsValidAtom(self): - + + self.todo = True tests = [ ( "sys-apps/portage", True ), ( "=sys-apps/portage-2.1", True ), ( "=sys-apps/portage-2.1*", True ), @@ -33,7 +34,6 @@ class IsValidAtom(TestCase): ( "portage", False ) ] for test in tests: - raise self.SkipException() if test[1]: atom_type = "valid" else: diff --git a/pym/portage/tests/env/__init__.py b/pym/portage/tests/env/__init__.py new file mode 100644 index 000000000..50e38af99 --- /dev/null +++ b/pym/portage/tests/env/__init__.py @@ -0,0 +1,5 @@ +# tests/portage/env/__init__.py -- Portage Unit Test functionality +# Copyright 2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + diff --git a/pym/portage/tests/env/config/__init__.py b/pym/portage/tests/env/config/__init__.py new file mode 100644 index 000000000..7fc0d0e96 --- /dev/null +++ b/pym/portage/tests/env/config/__init__.py @@ -0,0 +1,5 @@ +# tests/portage/env/config/__init__.py -- Portage Unit Test functionality +# Copyright 2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + diff --git a/pym/portage/tests/env/config/test_PackageKeywordsFile.py b/pym/portage/tests/env/config/test_PackageKeywordsFile.py new file mode 100644 index 000000000..32e9c30c5 --- /dev/null +++ b/pym/portage/tests/env/config/test_PackageKeywordsFile.py @@ -0,0 +1,37 @@ +# test_PackageKeywordsFile.py -- Portage Unit Testing Functionality +# Copyright 2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id: test_PackageKeywordsFile.py 6182 2007-03-06 07:35:22Z antarus $ + +from portage.tests import TestCase +from portage.env.config import PackageKeywordsFile + +class PackageKeywordsFileTestCase(TestCase): + + fname = 'package.keywords' + cpv = 'sys-apps/portage' + keywords = ['~x86', 'amd64', '-mips'] + + def testPackageKeywordsLoad(self): + """ + A simple test to ensure the load works properly + """ + + self.BuildFile() + try: + f = PackageKeywordsFile(self.fname) + f.load(recursive=False) + for cpv, keyword in f.iteritems(): + self.assertEqual( cpv, self.cpv ) + [k for k in keyword if self.assertTrue(k in self.keywords)] + finally: + self.NukeFile() + + def BuildFile(self): + f = open(self.fname, 'wb') + f.write('%s %s\n' % (self.cpv, ' '.join(self.keywords))) + f.close() + + def NukeFile(self): + import os + os.unlink(self.fname) diff --git a/pym/portage/tests/env/config/test_PackageMaskFile.py b/pym/portage/tests/env/config/test_PackageMaskFile.py new file mode 100644 index 000000000..f17eaf021 --- /dev/null +++ b/pym/portage/tests/env/config/test_PackageMaskFile.py @@ -0,0 +1,30 @@ +# test_PackageMaskFile.py -- Portage Unit Testing Functionality +# Copyright 2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id: test_PackageMaskFile.py 6182 2007-03-06 07:35:22Z antarus $ + +from portage.env.config import PackageMaskFile +from portage.tests import TestCase + +class PackageMaskFileTestCase(TestCase): + + fname = 'package.mask' + atoms = ['sys-apps/portage','dev-util/diffball','not@va1id@t0m'] + + def testPackageMaskLoad(self): + self.BuildFile() + try: + f = PackageMaskFile(self.fname) + f.load(recursive=False) + [atom for atom in f.iterkeys() if self.assertTrue(atom in self.atoms)] + finally: + self.NukeFile() + + def BuildFile(self): + f = open(self.fname, 'wb') + f.write("\n".join(atoms)) + f.close() + + def NukeFile(self): + import os + os.unlink(self.fname) diff --git a/pym/portage/tests/env/config/test_PackageUseFile.py b/pym/portage/tests/env/config/test_PackageUseFile.py new file mode 100644 index 000000000..4638923df --- /dev/null +++ b/pym/portage/tests/env/config/test_PackageUseFile.py @@ -0,0 +1,35 @@ +# test_PackageUseFile.py -- Portage Unit Testing Functionality +# Copyright 2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id: test_PackageUseFile.py 6182 2007-03-06 07:35:22Z antarus $ + +from portage.tests import TestCase +from portage.env.config import PackageUseFile + +class PackageUseFileTestCase(TestCase): + + fname = 'package.use' + cpv = 'sys-apps/portage' + useflags = ['cdrom', 'far', 'boo', 'flag', 'blat'] + + def testPackageUseLoad(self): + """ + A simple test to ensure the load works properly + """ + self.BuildFile() + try: + f = PackageUseFile(self.fname) + f.load(recursive=False) + for cpv, use in f.iteritems(): + self.assertEqual( cpv, self.cpv ) + [flag for flag in use if self.assertTrue(flag in self.useflags)] + finally: + self.NukeFile() + + def BuildFile(self): + f = open(self.fname, 'wb') + f.write("%s %s" % (self.cpv, ' '.join(self.useflags))) + + def NukeFile(self): + import os + os.unlink(self.fname) -- 2.26.2