Access GnomeKeyring with Python GIR

Since GTK+ 3.0 and the broad introduction of GObject Introspection (GIR) one now can switch from using the existing GnomeKeyring Python module to direct GIR-based access. This allows reducing the Python runtime dependency.

Below you find a simple keyring access script unlocking a keyring named "test" adding a new entry and dumping all entries in the keyring. This code uses the generic secret keyring type and was originally written for a Liferea plugin that allows Liferea to store feed passwords into GnomeKeyring:

from gi.repository import GObject
from gi.repository import GnomeKeyring

keyringName = 'test'

def unlock(): print 'Unlocking keyring %s...' % keyringName GnomeKeyring.unlock_sync(keyringName, None)

def dump_all(): print "Dump all keyring entries..." (result, ids) = GnomeKeyring.list_item_ids_sync(keyringName) for id in ids: (result, item) = GnomeKeyring.item_get_info_sync(keyringName, id) if result != GnomeKeyring.Result.OK: print '%s is locked!' % (id) else: print ' => %s = %s' % (item.get_display_name(), item.get_secret())

def do_query(id): print 'Fetch secret for id %s' % id attrs = GnomeKeyring.Attribute.list_new() GnomeKeyring.Attribute.list_append_string(attrs, 'id', id) result, value = GnomeKeyring.find_items_sync(GnomeKeyring.ItemType.GENERIC_SECRET, attrs) if result != GnomeKeyring.Result.OK: return

print ' => password %s = %s' % (id, value[0].secret) print ' keyring id = %s' % value[0].item_id

def do_store(id, username, password): print 'Adding keyring entry for id %s' % id GnomeKeyring.create_sync(keyringName, None) attrs = GnomeKeyring.Attribute.list_new() GnomeKeyring.Attribute.list_append_string(attrs, 'id', id) GnomeKeyring.item_create_sync(keyringName, GnomeKeyring.ItemType.GENERIC_SECRET, repr(id), attrs, '@@@'.join([username, password]), True) print ' => Stored.'

# Our test code... unlock() dump_all() do_store('id1', 'User1', 'Password1') do_query('id1') dump_all()
For simplicity the username and password are stored together as the secret token separated by "@@@". According to the documentation it should be possible to store them separately, but given my limited Python knowledge and the missing GIR documentation made me use this simple method. If I find a better way I'll update this post. If you know how to improve the code please post a comment!

The code should raise a keyring password dialog when run for the first time in the session and give an output similar to this:
Unlocking keyring test...
Dump all keyring entries...
  => 'id1' = TestA@@@PassA
Adding keyring entry for id id1
  => Stored.
Fetch secret for id id1
  => password id1 = TestA@@@PassA
     keyring id  = 1
Dump all keyring entries...
  => 'id1' = TestA@@@PassA
You can also check the keyring contents using the seahorse GUI where you should see the "test" keyring with an entry with id "1" as in the screenshot below.