Updated docstrings
authorworch <[email protected]>
Mon, 18 Aug 2008 04:33:23 +0000 (17 23:33 -0500)
committerworch <[email protected]>
Mon, 18 Aug 2008 04:33:23 +0000 (17 23:33 -0500)
libs.py.2.2_rc8.patch
pym/portage/dbapi/vartree.py
pym/portage/sets/libs.py
vartree.py.2.2_rc8.patch

index 947aab6..eb17089 100644 (file)
@@ -1,5 +1,5 @@
---- libs.py.2.2_rc8    2008-08-14 15:45:30.000000000 -0500
-+++ pym/portage/sets/libs.py   2008-08-17 20:59:09.000000000 -0500
+--- libs.py.2.2_rc8    2008-08-17 21:11:38.000000000 -0500
++++ pym/portage/sets/libs.py   2008-08-17 23:33:23.000000000 -0500
 @@ -2,10 +2,18 @@
  # Distributed under the terms of the GNU General Public License v2
  # $Id: libs.py 10759 2008-06-22 04:04:50Z zmedico $
@@ -19,7 +19,7 @@
  class LibraryConsumerSet(PackageSet):
        _operations = ["merge", "unmerge"]
  
-@@ -45,3 +53,338 @@
+@@ -45,3 +53,318 @@
                debug = get_boolean(options, "debug", False)
                return PreservedLibraryConsumerSet(trees["vartree"].dbapi, debug)
        singleBuilder = classmethod(singleBuilder)
 +                                      print x
 +                      return
 +
-+              if self.debug:
-+                      timeStart = time.time()
 +              self.linkmap.rebuild()
-+              if self.debug:
-+                      timeRebuild = time.time() - timeStart
-+
-+              if self.debug:
-+                      timeStart = time.time()
-+              self.linkmap.listConsumers()
-+              if self.debug:
-+                      timeConsumers = time.time() - timeStart
-+
-+              if self.debug:
-+                      timeStart = time.time()
-+              self.linkmap.listProviders()
-+              if self.debug:
-+                      timeProviders = time.time() - timeStart
 +
 +              # Get the list of broken dependencies from LinkageMap.
 +              if self.debug:
 +                      timeStart = time.time()
-+              brokenDependencies = self.linkmap.listBrokenBinaries()
++              brokenDependencies = self.linkmap.listBrokenBinaries(False)
 +              if self.debug:
 +                      timeListBrokenBinaries = time.time() - timeStart
 +
 +                      for x in sorted(atoms):
 +                              print x
 +                      print
-+                      print "Rebuild time:", timeRebuild
-+                      print "Providers time:", timeProviders
-+                      print "Consumers time:", timeConsumers
 +                      print "Broken binaries time:", timeListBrokenBinaries
 +                      print "Broken libtool time:", timeLibtool
 +                      print "Remove mask time:", timeMask
 +              atoms = set()
 +              consumers = set()
 +              matchedLibraries = set()
-+              libraryObjects = []
++              libraryObjects = self.linkmap.listLibraryObjects()
 +              _librarySearch_re = re.compile(searchString)
 +
 +              # Find libraries matching searchString.
-+              libraryObjects = self.linkmap.listLibraryObjects()
 +              for library in libraryObjects:
 +                      m = _librarySearch_re.search(library)
 +                      if m:
index ee7fff1..0ea2fbd 100644 (file)
@@ -212,9 +212,10 @@ class LinkageMap(object):
 
                @param obj: path to an existing file
                @type obj: string (example: '/usr/bin/bar')
-               @rtype: 2-tuple of longs or string
-               @return: If obj exists, a 2-tuple of obj's inode and device from a stat
-                       call is returned.  Otherwise, the obj is returned.
+               @rtype: 2-tuple of longs if obj exists. string if obj does not exist.
+               @return:
+                       1. 2-tuple of obj's inode and device from a stat call, if obj exists.
+                       2. string if obj does not exist.
 
                """
                try:
@@ -225,12 +226,15 @@ class LinkageMap(object):
 #                      from portage.output import teal
 #                      writemsg(bold(red("Error in ")) + \
 #                                      bold(teal("_generateObjKey. Stat failed on %s" % obj)) + '\n')
+                       # XXX do we need realpath?
                        return obj
 
        def listBrokenBinaries(self, debug=False):
                """
                Find binaries and their needed sonames, which have no providers.
 
+               @param debug: Boolean to enable debug output
+               @type debug: Boolean
                @rtype: dict (example: {'/usr/bin/foo': set(['libbar.so'])})
                @return: The return value is an object -> set-of-sonames mapping, where
                        object is a broken binary and the set consists of sonames needed by
@@ -240,7 +244,7 @@ class LinkageMap(object):
                class LibraryCache(object):
 
                        """
-                       Caches sonames and realpaths associated with paths.
+                       Caches properties associated with paths.
 
                        The purpose of this class is to prevent multiple calls of
                        os.path.realpath and os.path.isfile on the same paths.
@@ -318,9 +322,12 @@ class LinkageMap(object):
                                                validLibraries.add(cachedKey)
                                                if debug and cachedKey not in \
                                                                set(map(self._obj_key_cache.get, libraries)):
+                                                       # XXX This is most often due to soname symlinks not in
+                                                       # a library's directory.  We could catalog symlinks in
+                                                       # LinkageMap to avoid checking for this edge case here.
                                                        print "Found provider outside of findProviders:", \
                                                                        os.path.join(directory, soname), "->", \
-                                                                       self._obj_properties[cachedKey][4]
+                                                                       self._obj_properties[cachedKey][4], libraries
                                                # A valid library has been found, so there is no need to
                                                # continue.
                                                break
@@ -338,27 +345,11 @@ class LinkageMap(object):
                                        # If no valid libraries have been found by this point, then
                                        # there are no files named with the soname within obj's runpath,
                                        # but if there are libraries (from the providers mapping), it is
-                                       # likely that symlinks or the actual libraries are missing.
-                                       # Thus possible symlinks and missing libraries are added to
-                                       # rValue in order to emerge corrupt library packages.
+                                       # likely that soname symlinks or the actual libraries are
+                                       # missing or broken.  Thus those libraries are added to rValue
+                                       # in order to emerge corrupt library packages.
                                        for lib in libraries:
-                                               cachedArch, cachedSoname, cachedKey, cachedExists = \
-                                                               cache.get(lib)
-                                               if not cachedExists:
-                                                       # The library's package needs to be emerged to repair the
-                                                       # missing library.
-                                                       rValue.setdefault(lib, set()).add(soname)
-                                               else:
-                                                       # A library providing the soname exists in the obj's
-                                                       # runpath, but no file named as the soname exists, so add
-                                                       # the path constructed from the lib's directory and the
-                                                       # soname to rValue to fix cases of vanishing (or modified)
-                                                       # symlinks.  This path is not guaranteed to exist, but it
-                                                       # follows the symlink convention found in the majority of
-                                                       # packages.
-                                                       # XXX merge this into block above
-                                                       rValue.setdefault(os.path.join(os.path.dirname(lib), \
-                                                                       soname), set()).add(soname)
+                                               rValue.setdefault(lib, set()).add(soname)
                                                if debug:
                                                        if not os.path.isfile(lib):
                                                                print "Missing library:", lib
@@ -367,18 +358,9 @@ class LinkageMap(object):
                                                                                os.path.join(os.path.dirname(lib), soname)
                return rValue
 
-       def listConsumers(self):
-               rValue = {}
-               if not self._libs:
-                       self.rebuild()
-               # Iterate over all objects within LinkageMap.
-               for obj_key in self._obj_properties:
-                       rValue.setdefault(obj_key, self.findConsumers(obj_key=obj_key))
-               return rValue
-
        def listProviders(self):
                """
-               Find the providers for all objects in LinkageMap.
+               Find the providers for all object keys in LinkageMap.
 
                @rtype: dict (example:
                        {(123L, 456L): {'libbar.so': set(['/lib/libbar.so.1.5'])}})
@@ -399,6 +381,17 @@ class LinkageMap(object):
                return rValue
 
        def isMasterLink(self, obj):
+               """
+               Determine whether an object is a master link.
+
+               @param obj: absolute path to an object
+               @type obj: string (example: '/usr/bin/foo')
+               @rtype: Boolean
+               @return:
+                       1. True if obj is a master link
+                       2. False if obj is not a master link
+
+               """
                basename = os.path.basename(obj)
                obj_key = self._generateObjKey(obj)
                if obj_key not in self._obj_properties:
@@ -407,6 +400,15 @@ class LinkageMap(object):
                return (len(basename) < len(soname))
 
        def listLibraryObjects(self):
+               """
+               Return a list of library objects.
+
+               Known limitation: library objects lacking an soname are not included.
+
+               @rtype: list of strings
+               @return: list of paths to all providers
+
+               """
                rValue = []
                if not self._libs:
                        self.rebuild()
@@ -417,6 +419,15 @@ class LinkageMap(object):
                return rValue
 
        def getSoname(self, obj):
+               """
+               Return the soname associated with an object.
+
+               @param obj: absolute path to an object
+               @type obj: string (example: '/usr/bin/bar')
+               @rtype: string
+               @return: soname
+
+               """
                if not self._libs:
                        self.rebuild()
                if obj not in self._obj_key_cache:
@@ -431,12 +442,17 @@ class LinkageMap(object):
                with both, the obj_key is ignored.  If called with neither, KeyError is
                raised as if an invalid obj was passed.
 
-               @param obj:
-               @type obj:
-               @param obj_key:
-               @type obj_key:
-               @rtype:
-               @return:
+               In some cases, not all valid libraries are returned.  This may occur when
+               an soname symlink referencing a library is in and object's runpath while
+               the actual library is not.
+
+               @param obj: absolute path to an object
+               @type obj: string (example: '/usr/bin/bar')
+               @param obj_key: key from LinkageMap._generateObjKey
+               @type obj_key: 2-tuple of longs or string
+               @rtype: dict (example: {'libbar.so': set(['/lib/libbar.so.1.5'])})
+               @return: The return value is a soname -> set-of-library-paths, where
+               set-of-library-paths satisfy soname.
 
                """
                rValue = {}
@@ -455,17 +471,12 @@ class LinkageMap(object):
 
                arch, needed, path, soname, objs = self._obj_properties[obj_key]
                path = path.union(self._defpath)
-               # XXX test this
-               # path = set(realpath(x) for x in path)
                for x in needed:
                        rValue[x] = set()
                        if x not in self._libs or arch not in self._libs[x]:
                                continue
                        for y in self._libs[x][arch]["providers"]:
                                objs = self._obj_properties[y][4]
-                               # XXX x is an soname, so it should never start with os.sep, right?
-                               #if x[0] == os.sep and realpath(x) == realpath(y):
-                               #       rValue[x].add(y)
                                for o in objs:
                                        if os.path.dirname(o) in path:
                                                rValue[x].add(o)
@@ -480,12 +491,17 @@ class LinkageMap(object):
                with both, the obj_key is ignored.  If called with neither, KeyError is
                raised as if an invalid obj was passed.
 
-               @param obj:
-               @type obj:
-               @param obj_key:
-               @type obj_key:
-               @rtype:
-               @return:
+               In some cases, not all consumers are returned.  This may occur when
+               an soname symlink referencing a library is in and object's runpath while
+               the actual library is not.
+
+               @param obj: absolute path to an object
+               @type obj: string (example: '/usr/bin/bar')
+               @param obj_key: key from LinkageMap._generateObjKey
+               @type obj_key: 2-tuple of longs or string
+               @rtype: set of strings (example: )
+               @return: The return value is a soname -> set-of-library-paths, where
+               set-of-library-paths satisfy soname.
 
                """
                rValue = set()
@@ -532,19 +548,12 @@ class LinkageMap(object):
                        for consumer_key in self._libs[soname][arch]["consumers"]:
                                _, _, path, _, consumer_objs = \
                                                self._obj_properties[consumer_key]
-                               # XXX test this
-                               #path = [realpath(y) for y in path+self._defpath]
                                path = path.union(self._defpath)
-                               # XXX x is an soname, so it should never start with os.sep,
-                               # right?
-                               #if soname[0] == os.sep and realpath(soname) == realpath(obj):
-                               #       rValue.add(x)
-                               #if realpath(obj_dir) in path:
-                               #       rValue.add(x)
                                for consumer_obj in consumer_objs:
                                        for directory in objs_dirs:
                                                if directory in path:
                                                        rValue.add(consumer_obj)
+
                return rValue
 
 class vardbapi(dbapi):
index 0d44022..8259d33 100644 (file)
@@ -105,28 +105,12 @@ class MissingLibraryConsumerSet(LibraryConsumerSet):
                                        print x
                        return
 
-               if self.debug:
-                       timeStart = time.time()
                self.linkmap.rebuild()
-               if self.debug:
-                       timeRebuild = time.time() - timeStart
-
-               if self.debug:
-                       timeStart = time.time()
-               self.linkmap.listConsumers()
-               if self.debug:
-                       timeConsumers = time.time() - timeStart
-
-               if self.debug:
-                       timeStart = time.time()
-               self.linkmap.listProviders()
-               if self.debug:
-                       timeProviders = time.time() - timeStart
 
                # Get the list of broken dependencies from LinkageMap.
                if self.debug:
                        timeStart = time.time()
-               brokenDependencies = self.linkmap.listBrokenBinaries()
+               brokenDependencies = self.linkmap.listBrokenBinaries(False)
                if self.debug:
                        timeListBrokenBinaries = time.time() - timeStart
 
@@ -178,9 +162,6 @@ class MissingLibraryConsumerSet(LibraryConsumerSet):
                        for x in sorted(atoms):
                                print x
                        print
-                       print "Rebuild time:", timeRebuild
-                       print "Providers time:", timeProviders
-                       print "Consumers time:", timeConsumers
                        print "Broken binaries time:", timeListBrokenBinaries
                        print "Broken libtool time:", timeLibtool
                        print "Remove mask time:", timeMask
@@ -304,11 +285,10 @@ class MissingLibraryConsumerSet(LibraryConsumerSet):
                atoms = set()
                consumers = set()
                matchedLibraries = set()
-               libraryObjects = []
+               libraryObjects = self.linkmap.listLibraryObjects()
                _librarySearch_re = re.compile(searchString)
 
                # Find libraries matching searchString.
-               libraryObjects = self.linkmap.listLibraryObjects()
                for library in libraryObjects:
                        m = _librarySearch_re.search(library)
                        if m:
index 462576c..3065b96 100644 (file)
@@ -1,5 +1,5 @@
 --- vartree.py.2.2_rc8 2008-08-17 21:11:41.000000000 -0500
-+++ pym/portage/dbapi/vartree.py       2008-08-17 21:39:11.000000000 -0500
++++ pym/portage/dbapi/vartree.py       2008-08-17 23:33:23.000000000 -0500
 @@ -143,10 +143,12 @@
                self._dbapi = vardbapi
                self._libs = {}
@@ -15,7 +15,7 @@
                obj_properties = {}
                lines = []
                for cpv in self._dbapi.cpv_all():
-@@ -176,26 +178,56 @@
+@@ -176,29 +178,63 @@
                                # insufficient field length
                                continue
                        arch = fields[0]
 +      def _generateObjKey(self, obj):
 +              """
 +              Generate obj key for a given object.
--      def listBrokenBinaries(self):
++
 +              @param obj: path to an existing file
 +              @type obj: string (example: '/usr/bin/bar')
-+              @rtype: 2-tuple of longs or string
-+              @return: If obj exists, a 2-tuple of obj's inode and device from a stat
-+                      call is returned.  Otherwise, the obj is returned.
-+
++              @rtype: 2-tuple of longs if obj exists. string if obj does not exist.
++              @return:
++                      1. 2-tuple of obj's inode and device from a stat call, if obj exists.
++                      2. string if obj does not exist.
+-      def listBrokenBinaries(self):
 +              """
 +              try:
 +                      return os.stat(obj)[1:3]
 +#                     from portage.output import teal
 +#                     writemsg(bold(red("Error in ")) + \
 +#                                     bold(teal("_generateObjKey. Stat failed on %s" % obj)) + '\n')
++                      # XXX do we need realpath?
 +                      return obj
 +
 +      def listBrokenBinaries(self, debug=False):
                """
                Find binaries and their needed sonames, which have no providers.
  
-@@ -218,55 +250,56 @@
++              @param debug: Boolean to enable debug output
++              @type debug: Boolean
+               @rtype: dict (example: {'/usr/bin/foo': set(['libbar.so'])})
+               @return: The return value is an object -> set-of-sonames mapping, where
+                       object is a broken binary and the set consists of sonames needed by
+@@ -208,7 +244,7 @@
+               class LibraryCache(object):
+                       """
+-                      Caches sonames and realpaths associated with paths.
++                      Caches properties associated with paths.
+                       The purpose of this class is to prevent multiple calls of
+                       os.path.realpath and os.path.isfile on the same paths.
+@@ -218,55 +254,56 @@
                        def __init__(cache_self):
                                cache_self.cache = {}
  
                                validLibraries = set()
                                # It could be the case that the library to satisfy the soname is
                                # not in the obj's runpath, but a symlink to the library is (eg
-@@ -274,29 +307,34 @@
+@@ -274,67 +311,60 @@
                                # does not catalog symlinks, broken or missing symlinks may go
                                # unnoticed.  As a result of these cases, check that a file with
                                # the same name as the soname exists in obj's runpath.
 +                                              validLibraries.add(cachedKey)
 +                                              if debug and cachedKey not in \
 +                                                              set(map(self._obj_key_cache.get, libraries)):
++                                                      # XXX This is most often due to soname symlinks not in
++                                                      # a library's directory.  We could catalog symlinks in
++                                                      # LinkageMap to avoid checking for this edge case here.
                                                        print "Found provider outside of findProviders:", \
 -                                                                      os.path.join(d, soname), "->", cachedRealpath
 +                                                                      os.path.join(directory, soname), "->", \
-+                                                                      self._obj_properties[cachedKey][4]
++                                                                      self._obj_properties[cachedKey][4], libraries
                                                # A valid library has been found, so there is no need to
                                                # continue.
                                                break
                                        # If no valid libraries have been found by this point, then
                                        # there are no files named with the soname within obj's runpath,
                                        # but if there are libraries (from the providers mapping), it is
-@@ -304,7 +342,8 @@
-                                       # Thus possible symlinks and missing libraries are added to
-                                       # rValue in order to emerge corrupt library packages.
+-                                      # likely that symlinks or the actual libraries are missing.
+-                                      # Thus possible symlinks and missing libraries are added to
+-                                      # rValue in order to emerge corrupt library packages.
++                                      # likely that soname symlinks or the actual libraries are
++                                      # missing or broken.  Thus those libraries are added to rValue
++                                      # in order to emerge corrupt library packages.
                                        for lib in libraries:
 -                                              cachedSoname, cachedRealpath, cachedExists = cache.get(lib)
-+                                              cachedArch, cachedSoname, cachedKey, cachedExists = \
-+                                                              cache.get(lib)
-                                               if not cachedExists:
-                                                       # The library's package needs to be emerged to repair the
-                                                       # missing library.
-@@ -317,24 +356,33 @@
-                                                       # symlinks.  This path is not guaranteed to exist, but it
-                                                       # follows the symlink convention found in the majority of
-                                                       # packages.
-+                                                      # XXX merge this into block above
-                                                       rValue.setdefault(os.path.join(os.path.dirname(lib), \
-                                                                       soname), set()).add(soname)
+-                                              if not cachedExists:
+-                                                      # The library's package needs to be emerged to repair the
+-                                                      # missing library.
+-                                                      rValue.setdefault(lib, set()).add(soname)
+-                                              else:
+-                                                      # A library providing the soname exists in the obj's
+-                                                      # runpath, but no file named as the soname exists, so add
+-                                                      # the path constructed from the lib's directory and the
+-                                                      # soname to rValue to fix cases of vanishing (or modified)
+-                                                      # symlinks.  This path is not guaranteed to exist, but it
+-                                                      # follows the symlink convention found in the majority of
+-                                                      # packages.
+-                                                      rValue.setdefault(os.path.join(os.path.dirname(lib), \
+-                                                                      soname), set()).add(soname)
++                                              rValue.setdefault(lib, set()).add(soname)
                                                if debug:
 -                                                      if not cachedExists:
 +                                                      if not os.path.isfile(lib):
                                                        else:
                                                                print "Possibly missing symlink:", \
                                                                                os.path.join(os.path.dirname(lib), soname)
-+              return rValue
-+      def listConsumers(self):
-+              rValue = {}
-+              if not self._libs:
-+                      self.rebuild()
-+              # Iterate over all objects within LinkageMap.
-+              for obj_key in self._obj_properties:
-+                      rValue.setdefault(obj_key, self.findConsumers(obj_key=obj_key))
+-
                return rValue
  
        def listProviders(self):
                """
 -              Find the providers for all binaries.
-+              Find the providers for all objects in LinkageMap.
++              Find the providers for all object keys in LinkageMap.
  
                @rtype: dict (example:
 -                      {'/usr/bin/foo': {'libbar.so': set(['/lib/libbar.so.1.5'])}})
                        providers is a mapping of soname -> set-of-library-paths returned
                        from the findProviders method.
  
-@@ -342,118 +390,163 @@
+@@ -342,118 +372,190 @@
                rValue = {}
                if not self._libs:
                        self.rebuild()
                return rValue
  
        def isMasterLink(self, obj):
++              """
++              Determine whether an object is a master link.
++
++              @param obj: absolute path to an object
++              @type obj: string (example: '/usr/bin/foo')
++              @rtype: Boolean
++              @return:
++                      1. True if obj is a master link
++                      2. False if obj is not a master link
++
++              """
                basename = os.path.basename(obj)
 -              if obj not in self._obj_properties:
 -                      obj = os.path.realpath(obj)
 -              
 +
        def listLibraryObjects(self):
++              """
++              Return a list of library objects.
++
++              Known limitation: library objects lacking an soname are not included.
++
++              @rtype: list of strings
++              @return: list of paths to all providers
++
++              """
                rValue = []
                if not self._libs:
                        self.rebuild()
                return rValue
  
        def getSoname(self, obj):
++              """
++              Return the soname associated with an object.
++
++              @param obj: absolute path to an object
++              @type obj: string (example: '/usr/bin/bar')
++              @rtype: string
++              @return: soname
++
++              """
                if not self._libs:
                        self.rebuild()
 -              if obj not in self._obj_properties:
 +              with both, the obj_key is ignored.  If called with neither, KeyError is
 +              raised as if an invalid obj was passed.
 +
-+              @param obj:
-+              @type obj:
-+              @param obj_key:
-+              @type obj_key:
-+              @rtype:
-+              @return:
++              In some cases, not all valid libraries are returned.  This may occur when
++              an soname symlink referencing a library is in and object's runpath while
++              the actual library is not.
++
++              @param obj: absolute path to an object
++              @type obj: string (example: '/usr/bin/bar')
++              @param obj_key: key from LinkageMap._generateObjKey
++              @type obj_key: 2-tuple of longs or string
++              @rtype: dict (example: {'libbar.so': set(['/lib/libbar.so.1.5'])})
++              @return: The return value is a soname -> set-of-library-paths, where
++              set-of-library-paths satisfy soname.
 +
 +              """
 +              rValue = {}
 -                              real_path = os.path.realpath(p)
 -                              realpath_cache[p] = real_path
 -                      return real_path
--
++              if obj is not None:
++                      obj_key = self._obj_key_cache.get(obj)
++                      if obj_key not in self._obj_properties:
++                              obj_key = self._generateObjKey(obj)
++                              if obj_key not in self._obj_properties:
++                                      raise KeyError("%s (%s) not in object list" % (obj_key, obj))
++              elif obj_key not in self._obj_properties:
++                      raise KeyError("%s not in object list" % obj_key)
 -              rValue = {}
 -              if obj not in self._obj_properties:
 -                      obj = realpath(obj)
 -              path = path[:]
 -              path.extend(self._defpath)
 -              path = set(realpath(x) for x in path)
-+              if obj is not None:
-+                      obj_key = self._obj_key_cache.get(obj)
-+                      if obj_key not in self._obj_properties:
-+                              obj_key = self._generateObjKey(obj)
-+                              if obj_key not in self._obj_properties:
-+                                      raise KeyError("%s (%s) not in object list" % (obj_key, obj))
-+              elif obj_key not in self._obj_properties:
-+                      raise KeyError("%s not in object list" % obj_key)
-+
 +              arch, needed, path, soname, objs = self._obj_properties[obj_key]
 +              path = path.union(self._defpath)
-+              # XXX test this
-+              # path = set(realpath(x) for x in path)
                for x in needed:
                        rValue[x] = set()
                        if x not in self._libs or arch not in self._libs[x]:
 -                              elif realpath(os.path.dirname(y)) in path:
 -                                      rValue[x].add(y)
 +                              objs = self._obj_properties[y][4]
-+                              # XXX x is an soname, so it should never start with os.sep, right?
-+                              #if x[0] == os.sep and realpath(x) == realpath(y):
-+                              #       rValue[x].add(y)
 +                              for o in objs:
 +                                      if os.path.dirname(o) in path:
 +                                              rValue[x].add(o)
 +              with both, the obj_key is ignored.  If called with neither, KeyError is
 +              raised as if an invalid obj was passed.
 +
-+              @param obj:
-+              @type obj:
-+              @param obj_key:
-+              @type obj_key:
-+              @rtype:
-+              @return:
++              In some cases, not all consumers are returned.  This may occur when
++              an soname symlink referencing a library is in and object's runpath while
++              the actual library is not.
++
++              @param obj: absolute path to an object
++              @type obj: string (example: '/usr/bin/bar')
++              @param obj_key: key from LinkageMap._generateObjKey
++              @type obj_key: 2-tuple of longs or string
++              @rtype: set of strings (example: )
++              @return: The return value is a soname -> set-of-library-paths, where
++              set-of-library-paths satisfy soname.
 +
 +              """
 +              rValue = set()
 -                      if (obj_st.st_dev, obj_st.st_ino) != \
 -                              (master_st.st_dev, master_st.st_ino):
 -                              return set()
--
--              rValue = set()
--              for soname in self._libs:
--                      for arch in self._libs[soname]:
--                              if obj in self._libs[soname][arch]["providers"]:
--                                      for x in self._libs[soname][arch]["consumers"]:
--                                              path = self._obj_properties[x][2]
--                                              path = [realpath(y) for y in path+self._defpath]
--                                              if soname[0] == os.sep and realpath(soname) == realpath(obj):
--                                                      rValue.add(x)
--                                              elif realpath(obj_dir) in path:
--                                                      rValue.add(x)
 +              if obj is not None:
 +                      soname = self._obj_properties[obj_key][3]
 +                      obj_dir = os.path.dirname(obj)
 +                      for consumer_key in self._libs[soname][arch]["consumers"]:
 +                              _, _, path, _, consumer_objs = \
 +                                              self._obj_properties[consumer_key]
-+                              # XXX test this
-+                              #path = [realpath(y) for y in path+self._defpath]
 +                              path = path.union(self._defpath)
-+                              # XXX x is an soname, so it should never start with os.sep,
-+                              # right?
-+                              #if soname[0] == os.sep and realpath(soname) == realpath(obj):
-+                              #       rValue.add(x)
-+                              #if realpath(obj_dir) in path:
-+                              #       rValue.add(x)
 +                              for consumer_obj in consumer_objs:
 +                                      for directory in objs_dirs:
 +                                              if directory in path:
 +                                                      rValue.add(consumer_obj)
+-              rValue = set()
+-              for soname in self._libs:
+-                      for arch in self._libs[soname]:
+-                              if obj in self._libs[soname][arch]["providers"]:
+-                                      for x in self._libs[soname][arch]["consumers"]:
+-                                              path = self._obj_properties[x][2]
+-                                              path = [realpath(y) for y in path+self._defpath]
+-                                              if soname[0] == os.sep and realpath(soname) == realpath(obj):
+-                                                      rValue.add(x)
+-                                              elif realpath(obj_dir) in path:
+-                                                      rValue.add(x)
                return rValue
 -                                      
 +