astra / doc /source /tutorials /apt-cdrom.rst
Lorenzob's picture
Upload folder using huggingface_hub
859a779 verified
raw
history blame
6.22 kB
Writing your own apt-cdrom
==========================
:Author: Julian Andres Klode <[email protected]>
: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