2
\$\begingroup\$

It works pretty well, but I suspect there's too many variables, and I wonder what else.

I'm using this library: Python APT.

#!/usr/bin/env python3

import argparse
import apt

def getdeps(deptype, pkg, otherpkg):
    deps = list()
    name = otherpkg.shortname
    otherpkg = otherpkg.candidate
    for deplist in otherpkg.get_dependencies(deptype):
        for dep in deplist.or_dependencies:
            if dep.name == pkg.shortname:
                deps.append(name)
    return deps


def reverse_dependencies(pkg):
    """Which packages have some kind of dependency on the given package"""

    cache = apt.cache.Cache()
    try:
        pkg = cache[pkg]
    except KeyError as e:
        print(str(e).strip('"'))
        return 1

    dependents = dict()
    recommends = list()
    suggests = list()
    replaces = list()
    enhances = list()
    depends = list()

    for key in cache.keys():
        otherpkg = cache[key]
        depends.append(getdeps("Depends", pkg, otherpkg))
        recommends.append(getdeps("Recommends", pkg, otherpkg))
        suggests.append(getdeps("Suggests", pkg, otherpkg))
        replaces.append(getdeps("Replaces", pkg, otherpkg))
        enhances.append(getdeps("Enhances", pkg, otherpkg))

    dependents["Depends"] = depends
    dependents["Recommends"] = recommends
    dependents["Suggests"] = suggests
    dependents["Replaces"] = replaces
    dependents["Enhances"] = enhances

    for deptype, deps in dependents.items():
        deps_output = list()
        for match in deps:
            if match:
                for item in match:
                    deps_output.append(item)
        if deps_output:
            print(deptype.upper(), end=": ")
            print(" ".join(deps_output))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("pkg", help="pkg to describe")
    args = parser.parse_args()
    reverse_dependencies(args.pkg)

Example terminal session:

$ ./rdeps.py python3-apt
DEPENDS: python3-apt-dbg wajig
ENHANCES: python-apt-common
\$\endgroup\$
3
\$\begingroup\$
#!/usr/bin/env python3

import argparse
import apt

def getdeps(deptype, pkg, otherpkg):

I recommend not using abbrivates like dep or pkg.

    deps = list()

We usually create lists with [] not list()

    name = otherpkg.shortname
    otherpkg = otherpkg.candidate

I wouldn't do this. You only use it once, so its actually best to just otherpkg.candidate.get_dependencies Generally, I recommend against replacing one variable with another because often it increases confusion.

    for deplist in otherpkg.get_dependencies(deptype):
        for dep in deplist.or_dependencies:
            if dep.name == pkg.shortname:
                deps.append(name)

    return deps

Why does this function return a list? It seems to me that you are checking whether otherpkg depends on pkg. If so, this function really ought to return True or False.

def reverse_dependencies(pkg):
    """Which packages have some kind of dependency on the given package"""

    cache = apt.cache.Cache()
    try:
        pkg = cache[pkg]
    except KeyError as e:
        print(str(e).strip('"'))
        return 1

You don't do anything with this return value. you should pass it to sys.exit()

    dependents = dict()

We usually create dicts with {}

    recommends = list()
    suggests = list()
    replaces = list()
    enhances = list()
    depends = list()

These are all basically the same thing which means they shouldn't be seperate variables.

    for key in cache.keys():
        otherpkg = cache[key]
        depends.append(getdeps("Depends", pkg, otherpkg))
        recommends.append(getdeps("Recommends", pkg, otherpkg))
        suggests.append(getdeps("Suggests", pkg, otherpkg))
        replaces.append(getdeps("Replaces", pkg, otherpkg))
        enhances.append(getdeps("Enhances", pkg, otherpkg))

This would be better as iteration over a list of the dependency types. Also you are putting lists into lists. It'd be cleaner if you just had lists.

    dependents["Depends"] = depends
    dependents["Recommends"] = recommends
    dependents["Suggests"] = suggests
    dependents["Replaces"] = replaces
    dependents["Enhances"] = enhances

    for deptype, deps in dependents.items():
        deps_output = list()
        for match in deps:
            if match:

There's no point in doing this, because the loop will be executed 0 times if match is empty

                for item in match:
                    deps_output.append(item)

Use dep_output.extend(match) it has the same effect as this loop

        if deps_output:
            print(deptype.upper(), end=": ")
            print(" ".join(deps_output))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("pkg", help="pkg to describe")
    args = parser.parse_args()
    reverse_dependencies(args.pkg)

My reworking of your code:

#!/usr/bin/env python3

import argparse
import apt
import sys

DEPENDENCY_TYPES = [
    "Depends",
    "Recommends",
    "Suggests",
    "Replaces",
    "Enhances",
]

def extract_dependencies(package, dependency_type):
    """
    Generator that produce all the dependencies of a particular type
    """
    for dependency_list in package.candidate.get_dependencies(dependency_type):
        for dependency in dependency_list.or_dependencies:
            yield dependency.name

def reverse_dependencies(pkg):
    """Which packages have some kind of dependency on the given package"""

    cache = apt.cache.Cache()
    try:
        pkg = cache[pkg]
    except KeyError as error:
        print(error.args[0])
        sys.exit(1)

    dependents = { name : [] for name in DEPENDENCY_TYPES }

    for key in cache.keys():
        other_package = cache[key]
        for dependency_type, specific_dependents in dependents.items():
            if pkg.shortname in extract_dependencies(other_package, dependency_type):
                specific_dependents.append(other_package.shortname)

    for dependency_type, specific_dependents in dependents.items():
        if specific_dependents:
            print(dependency_type.upper(), ": ", " ".join(specific_dependents))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("pkg", help="pkg to describe")
    args = parser.parse_args()
    reverse_dependencies(args.pkg)
\$\endgroup\$
  • \$\begingroup\$ I really like your new names, stuff like extract_dependencies and extract_dependencies. You also exposed me to the fact I didn't fully understand my code. Thanks also for writing a fully-working version of your own alternative, especially since I didn't quite get some of your suggestions. \$\endgroup\$ – Tshepang Feb 15 '12 at 20:34
  • 1
    \$\begingroup\$ "We usually create lists with [] not list()" but Alex Martelli does not like that (I cannot find the link though). \$\endgroup\$ – Leonid Feb 15 '12 at 20:35
  • \$\begingroup\$ @Leonid stackoverflow.com/a/2745292 \$\endgroup\$ – Tshepang Feb 15 '12 at 20:47
  • \$\begingroup\$ @Tshepang, some exceptions exist, but [] is generally more common then list(). But its an issue of style, and you can go either way. \$\endgroup\$ – Winston Ewert Feb 15 '12 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.