| | Writing your own apt-cdrom |
| | ========================== |
| | :Author: Julian Andres Klode <jak@debian.org> |
| | :Release: |release| |
| | :Date: |today| |
| |
|
| | This article explains how to utilise python-apt to build your own clone of the |
| | :command:`apt-cdrom` command. To do this, we will take a look at the |
| | :mod:`apt.cdrom` and :mod:`apt.progress.text` modules, and we will learn how |
| | to use apt_pkg.parse_commandline to parse commandline arguments. The code shown |
| | here works on Python 2 and Python 3. |
| |
|
| | Basics |
| | ------ |
| | The first step in building your own :command:`apt-cdrom` clone is to import the |
| | :mod:`apt` package, which will import :mod:`apt.cdrom` and |
| | :mod:`apt.progress.text`:: |
| |
|
| | import apt |
| |
|
| | Now we have to create a new :class:`apt.cdrom.Cdrom` object and pass to it an |
| | :class:`apt.progress.text.CdromProgress` object, which is responsible for |
| | displaying the progress and asking questions:: |
| | |
| | cdrom = apt.Cdrom(apt.progress.text.CdromProgress()) |
| |
|
| | Now we have to choose the action, depending on the given options on the |
| | command line. For now, we simply use the value of ``sys.argv[1]``:: |
| | |
| | import sys |
| | if sys.argv[1] == 'add': |
| | cdrom.add() |
| | elif sys.argv[1] == 'ident': |
| | cdrom.ident() |
| |
|
| | Now we have a basic :command:`apt-cdrom` clone which can add and identify |
| | CD-ROMs:: |
| | |
| | import sys |
| |
|
| | import apt |
| |
|
| | cdrom = apt.Cdrom(apt.progress.text.CdromProgress()) |
| | if sys.argv[1] == 'add': |
| | cdrom.add() |
| | elif sys.argv[1] == 'ident': |
| | cdrom.ident() |
| |
|
| | Advanced example with command-line parsing |
| | ------------------------------------------- |
| | Our example clearly misses a way to parse the commandline in a correct |
| | manner. Luckily, :mod:`apt_pkg` provides us with a function to do this: |
| | :func:`apt_pkg.parse_commandline`. To use it, we add ``import apt_pkg`` right |
| | after import apt:: |
| | |
| | import sys |
| |
|
| | import apt_pkg |
| | import apt |
| |
|
| |
|
| | :func:`apt_pkg.parse_commandline` is similar to :mod:`getopt` functions, it |
| | takes a list of recognized options and the arguments and returns all unknown |
| | arguments. If it encounters an unknown argument which starts with a leading |
| | '-', the function raises an error indicating that the option is unknown. The |
| | major difference is that this function manipulates the apt configuration space. |
| |
|
| | The function takes 3 arguments. The first argument is an |
| | :class:`apt_pkg.Configuration` object. The second argument is a list of tuples |
| | of the form ``(shortopt, longopt, config, type)``, whereas *shortopt* is a |
| | character indicating the short option name, *longopt* a string indicating the |
| | corresponding long option (e.g. ``"--help"``), *config* the name of the |
| | configuration item which should be set and *type* the type of the argument. |
| |
|
| | For apt-cdrom, we can use the following statement:: |
| | |
| | arguments = apt_pkg.parse_commandline(apt_pkg.config, |
| | [('h', "help", "help"), |
| | ('v', "version", "version"), |
| | ('d', "cdrom", "Acquire::cdrom::mount", "HasArg"), |
| | ('r', "rename", "APT::CDROM::Rename"), |
| | ('m', "no-mount", "APT::CDROM::NoMount"), |
| | ('f', "fast", "APT::CDROM::Fast"), |
| | ('n', "just-print", "APT::CDROM::NoAct"), |
| | ('n', "recon", "APT::CDROM::NoAct"), |
| | ('n', "no-act", "APT::CDROM::NoAct"), |
| | ('a', "thorough", "APT::CDROM::Thorough"), |
| | ('c', "config-file", "", "ConfigFile"), |
| | ('o', "option", "", "ArbItem")], args) |
| |
|
| |
|
| | This allows us to support all options supported by apt-cdrom. The first option |
| | is --help. As you can see, it omits the fourth field of the tuple; which means |
| | it is a boolean argument. Afterwards you could use |
| | ``apt_pkg.config.find_b("help")`` to see whether ``--help`` was specified. In |
| | ``('d',"cdrom","Acquire::cdrom::mount","HasArg")`` the fourth field is |
| | ``"HasArg"``. This means that the option has an argument, in this case the |
| | location of the mount point. ``('c',"config-file","","ConfigFile")`` shows how |
| | to include configuration files. This option takes a parameter which points to |
| | a configuration file which will be added to the configuration space. |
| | ``('o',"option","","ArbItem")`` is yet another type of option, which allows users |
| | to set configuration options on the commandline. |
| | |
| | Now we have to check whether help or version is specified, and print a message |
| | and exit afterwards. To do this, we use :meth:`apt_pkg.Configuration.find_b` |
| | which returns ``True`` if the configuration option exists and evaluates to |
| | ``True``:: |
| | |
| | if apt_pkg.config.find_b("help"): |
| | print("This should be a help message") |
| | sys.exit(0) |
| | elif apt_pkg.config.find_b("version"): |
| | print("Version blah.") |
| | sys.exit(0) |
| |
|
| |
|
| | Now we are ready to create our progress object and our cdrom object. Instead |
| | of using :class:`apt.Cdrom` like in the first example, we will use |
| | :class:`apt_pkg.Cdrom` which provides a very similar interface. We could also |
| | use :class:`apt.Cdrom`, but `apt.Cdrom` provides options like *nomount* which |
| | conflict with our commandline parsing:: |
| | |
| | progress = apt.progress.text.CdromProgress() |
| | cdrom = apt_pkg.Cdrom() |
| |
|
| |
|
| | Now we have to do the action requested by the user on the commandline. To see |
| | which option was requested, we check the list ``arguments`` which was returned |
| | by ``apt_pkg.parse_commandline`` above, and afterwards call ``cdrom.add`` or |
| | ``cdrom.ident``:: |
| | |
| | if apt_pkg.config.find_b("help"): |
| | print("This should be a help message") |
| | sys.exit(0) |
| | elif apt_pkg.config.find_b("version"): |
| | print("Version blah.") |
| | sys.exit(0) |
| |
|
| | if not arguments: |
| | sys.stderr.write('E: No operation specified\n') |
| | sys.exit(1) |
| | elif arguments[0] == 'add': |
| | cdrom.add(progress) |
| | elif arguments[0] == 'ident': |
| | cdrom.ident(progress) |
| | else: |
| | sys.stderr.write('E: Invalid operation %s\n' % arguments[0]) |
| | sys.exit(1) |
| |
|
| |
|
| | After putting all our actions into a main() function, we get a completely |
| | working apt-cdrom clone, which just misses useful ``--help`` and ``--version`` |
| | options. If we add a function show_help(), we get an even more complete |
| | apt-cdrom clone: |
| |
|
| | .. literalinclude:: ../examples/apt-cdrom.py |
| |
|