[PREVIEW] python-xdg: shared-mimeinfo/trash/mime-actions/desktop-entry specs in python. Compatible with intents.

Jerome Leclanche adys.wh at gmail.com
Thu Jan 16 06:09:45 PST 2014


Hi list

I mentioned python-xdg before:
https://github.com/Adys/python-xdg

Lately I've been updating it and using it as a reference
implementation for the various improvements highlighted in my intents
email from the other day.

The xdg.mime module implements an interface for interacting with mime
types (whether they exist or not). The BaseMimeType class implements
the common mime type functionality, and the MimeType class implements
the xdg-specific functionality.

The tests display most of what's possible when dealing directly with
the mime types:
https://github.com/Adys/python-xdg/blob/master/tests/mime.py

The MimeType class implements the following useful class methods:
MimeType.fromName("path/to/file") -> returns a MimeType based on globs
matching the name. eg "foo.png" will match image/png's *.png
MimeType.fromContent("path/to/file") -> returns a MimeType based on
the contents of the file (currently not fully implemented). Returns
application/x-zerosize for zero-byte apps.
MimeType.fromInode("path/to/inode") -> returns an inode/* mime type
(inode/directory, inode/symlink, etc)
MimeType.fromScheme("http://...") -> returns the scheme MimeType class
of a URI (eg. x-scheme-handler/http)

Once you have a mime type, you can get the applications associated
with it. It's all implemented in the xdg.actions module, however you
do not actually have to deal with that module directly, convenience
functions are implemented in the MimeType class.

To get every app associated with a MimeType, everything is implemented
in MimeType.applications():
>>> list(MimeType("text/plain").applications())
['kde4-kate.desktop']

MimeType.applications() returns a generator, hence the list(). The
elements are ordered from most to least fitting to open the MIME type.
It is first unaliased, then the default app is checked, then added
associations are checked, then cached associations; the process is
then repeated for every parent of the MIME type, recursively.
 MimeType.bestApplication() will immediately return the first
application in that list.

Their cousins availableApplications() and bestAvailableApplications()
will return the same generators, filtered to only applications that
actually exist (this is useful if you have lingering .desktop files
from old installations, especially in ~/.local/share).


The xdg.actions module is written in a generic way, so that the
proposed extensions to it can easily be implemented.

It is divided into two file classes: ActionsListFile and
ActionsCacheFile. The global instances ACTIONS_LIST and ACTIONS_CACHE
read applications/mimeapps.list and applications/mimeinfo.cache from
all xdg directories and merges them (all that is implemented into
xdg.inifile, which is a minor extension of python's builtin
configparser.RawConfigParser).

The module defines three types of actions: ACTION_OPEN, ACTION_VIEW
and ACTION_EDIT. They are flag and can be combined, an ACTION_ALL is
present for convenience.
The only action currently defined in the spec is ACTION_OPEN. Every
function that takes an action defaults to ACTION_ALL in order to
remain backwards-compatible with the current implementations.

The ActionsCacheFile is very easy to extend. Adding a cache to
categories and intents is then immediately available. For example...

Getting every application that implements the Camera intent (uses
Intents Cache section):
>>> ACTIONS_CACHE.applicationsForIntent("org.freedesktop.intents.Camera")
['kde4-kamoso.desktop']

Getting every application in a specific category (uses Category Cache section):
>>> ACTIONS_CACHE.applicationsForCategory("Graphics")
['gimp.desktop', 'easypaint.desktop', 'lximage-qt.desktop',
'feh.desktop', 'inkscape.desktop']

Great for listing eg. every screen capture app, or every window manager, etc.


The xdg.desktopfile module implements a DesktopFile class (subclassed
from IniFile). In addition to supporting the format itself, it
implements a few methods to directly access (potentially-translated)
values.
The classmethod DesktopFile.lookup() takes a desktop file name and
returns a DesktopFile instance of the most readily available desktop
file matching it in the xdg directories.

DesktopFile.formattedExec() formats the Exec line according to the
spec and the given list of arguments (defaults to an empty list).
If you don't want to bother with starting the application yourself,
the convenience function DesktopFile.exec_() implements it (using
subprocess.Popen()).

In short, to reimplement xdg-open, you just need the following:
>>> from xdg.mime import MimeType
>>> from xdg.desktopfile import DesktopFile
>>> app = MimeType.fromName("foo.png").bestAvailableApplication()
>>> DesktopFile.lookup(app).exec_()

Ta-dah.

J. Leclanche


More information about the xdg mailing list