From: Alec Warner Date: Fri, 7 Sep 2007 10:14:12 +0000 (-0000) Subject: dbapi currently depends on being subclassed and having the subclasses impelement... X-Git-Tag: v2.2_pre1~824 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f77868a5f27b87d053e000667992ecb4cb78d335;p=portage.git dbapi currently depends on being subclassed and having the subclasses impelement certain functions (that aren't even implemented IN dbapi, so a particular child has no idea what functions are actually required). Try to make this cleared by adding stubs in dbapi. There should be no behavior change here because these cases would be Attribute errors in the current scheme. Also add a horribly bad testdbapi with stub funcs to use in testing code. Remove regexes with possibly faster string comparisons. svn path=/main/trunk/; revision=7752 --- diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py index f76878ebb..329271ee6 100644 --- a/pym/portage/dbapi/__init__.py +++ b/pym/portage/dbapi/__init__.py @@ -2,15 +2,15 @@ # Distributed under the terms of the GNU General Public License v2 # $Id$ - +import os +import re from portage.dep import dep_getslot, dep_getkey, match_from_list from portage.locks import unlockfile from portage.output import red from portage.util import writemsg - from portage import dep_expand +from portage.versions import catsplit -import os, re class dbapi(object): def __init__(self): @@ -23,18 +23,61 @@ class dbapi(object): return def cpv_all(self): + """Return all CPVs in the db + Args: + None + Returns: + A list of Strings, 1 per CPV + + This function relies on a subclass implementing cp_all, this is why the hasattr is there + """ + + if not hasattr(self, "cp_all"): + raise NotImplementedError cpv_list = [] for cp in self.cp_all(): cpv_list.extend(self.cp_list(cp)) return cpv_list + def cp_all(self): + """ Implement this in a child class + Args + None + Returns: + A list of strings 1 per CP in the datastore + """ + return NotImplementedError + def aux_get(self, mycpv, mylist): - "stub code for returning auxiliary db information, such as SLOT, DEPEND, etc." - 'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]' - 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or [] if mycpv not found' + """Return the metadata keys in mylist for mycpv + Args: + mycpv - "sys-apps/foo-1.0" + mylist - ["SLOT","DEPEND","HOMEPAGE"] + Returns: + a list of results, in order of keys in mylist, such as: + ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or [] if mycpv not found' + """ + raise NotImplementedError + + def aux_update(self, cpv, metadata_updates): + """ + Args: + cpv - "sys-apps/foo-1.0" + metadata_updates = { key : newvalue } + Returns: + None + """ raise NotImplementedError def match(self, origdep, use_cache=1): + """Given a dependency, try to find packages that match + Args: + origdep - Depend atom + use_cache - Boolean indicating if we should use the cache or not + NOTE: Do we ever not want the cache? + Returns: + a list of packages that match origdep + """ mydep = dep_expand(origdep, mydb=self, settings=self.settings) mykey = dep_getkey(mydep) mylist = match_from_list(mydep, self.cp_list(mykey, use_cache=use_cache)) @@ -45,14 +88,14 @@ class dbapi(object): return mylist def invalidentry(self, mypath): - if re.search("portage_lockfile$", mypath): + if mypath.endswith('portage_lockfile'): if not os.environ.has_key("PORTAGE_MASTER_PID"): writemsg("Lockfile removed: %s\n" % mypath, 1) unlockfile((mypath, None, None)) else: # Nothing we can do about it. We're probably sandboxed. pass - elif re.search(".*/-MERGING-(.*)", mypath): + elif '/-MERGING-' in mypath: if os.path.exists(mypath): writemsg(red("INCOMPLETE MERGE:")+" "+mypath+"\n", noiselevel=-1) else: @@ -60,7 +103,7 @@ class dbapi(object): def update_ents(self, updates, onProgress=None): """ - Update metadata of all packages for packages moves. + Update metadata of all packages for package moves. @param updates: A list of move commands @type updates: List @param onProgress: A progress callback function @@ -85,6 +128,12 @@ class dbapi(object): onProgress(maxval, i+1) def move_slot_ent(self, mylist): + """This function takes a sequence: + Args: + mylist: a sequence of (package, originalslot, newslot) + Returns: + The number of slotmoves this function did + """ pkg = mylist[1] origslot = mylist[2] newslot = mylist[3] @@ -92,7 +141,6 @@ class dbapi(object): moves = 0 if not origmatches: return moves - from portage.versions import catsplit for mycpv in origmatches: slot = self.aux_get(mycpv, ["SLOT"])[0] if slot != origslot: diff --git a/pym/portage/dbapi/virtual.py b/pym/portage/dbapi/virtual.py index 467eb032c..30f51ceaf 100644 --- a/pym/portage/dbapi/virtual.py +++ b/pym/portage/dbapi/virtual.py @@ -4,11 +4,12 @@ from portage.dbapi import dbapi - from portage import cpv_getkey class fakedbapi(dbapi): - "This is a dbapi to use for the emptytree function. It's empty, but things can be added to it." + """A fake dbapi that allows consumers to inject/remove packages to/from it + portage.settings is required to maintain the dbAPI. + """ def __init__(self, settings=None): self.cpvdict = {} self.cpdict = {} @@ -90,3 +91,19 @@ class fakedbapi(dbapi): def aux_update(self, cpv, values): self._clear_cache() self.cpvdict[cpv].update(values) + +class testdbapi(object): + """A dbapi instance with completely fake functions to get by hitting disk + TODO(antarus): + This class really needs to be rewritten to have better stubs; but these work for now. + The dbapi classes themselves need unit tests...and that will be a lot of work. + """ + + def __init__(self): + self.cpvs = {} + def f(*args, **kwargs): + return True + fake_api = dir(dbapi) + for call in fake_api: + if not hasattr(self, call): + setattr(self, call, f) \ No newline at end of file