Localsearch module

Localsearch is a desktop search engine developed as part of the GNOME project. It’s available on most Linux desktop OSes.

On a machine where Localsearch is configured to index music files, you can use the Calliope integration to search and query the user’s music library.

With some extra configuration, you can also make Localsearch work as a general-purpose media library scanner.

Note that Localsearch was named LocalSearch until 2024 and the old name still appears in some places.

User notes

See the API Reference for features.

How the integration works

The Localsearch indexer provides an endpoint, available over D-Bus message bus, implemented using the TinySPARQL database library. Calliope uses TinySPARQL to connect to the Localsearch indexer daemon and query its database.

As a GNOME platform library, TinySPARQL is written in C with GObject, and has Python bindings available via PyGObject.

As these are not pure-Python dependency, you can’t rely on Python packaging tools to install them. Linux distributions should have packages available for Localsearch, PyGObject and the TinySPARQL “GIR” introspection data. Use those.

Developer notes

Developing queries

Querying the Localsearch index is done using the SPARQL query language. Each query used by Calliope is in a standalone file, and parametrized using the TinySPARQL-specific ~arg syntax to allow passing in arguments from Python code.

When working on the queries themselves, it’s handy to run them directly from the commandline. Using the tinysparql query command, with the --dbus-service= option to point it at the Localsearch indexer (the systemwide indexer lives at org.freedesktop.LocalSearch3). And use --arg to set parameter values. Full documentation in the TinySPARQL manual, see: man tinysparql query.

How the tests work

Automated tests involving localsearch have several moving pieces. Here’s a summary to help you debug when things go wrong.

There is a special Tox environment for localsearch defined in pyproject.toml. It uses the localsearch test-sandbox command, which does the following:

  • Starts a new D-Bus message bus.

  • Creates a temporary directory to hold the localsearch database (also known as the “store”).

  • Creates another temporary directory for files that will be indexed

  • Sets several environment variables that child processes will see, including:
    • DBUS_SESSION_BUS_ADDRESS: the address of the new message bus.

    • PYTHONPATH: updated to include a Python package named ‘trackertestutils’.

    • TRACKER_INDEXED_TMPDIR: the directory for files that will be indexed.

    • TRACKER_SANDBOX: set to "1"

The Pytest command and all the tests are run inside localsearch test-sandbox.

Tests for the Calliope localsearch integration use the following pattern to create test scenarios:

  1. Create files inside the TRACKER_INDEXED_TMPDIR directory.

  2. Use trackertestutils.storehelper.StoreHelper.ensure_resource() to block until the file has been indexed by localsearch and the expected metadata is available in the store.

  3. Use the calliope module to run queries against the search index.

The localsearch indexer process (/usr/libexec/localsearch-3) is started on-demand by the D-Bus daemon when the test first tries to connect to it. See the localsearch docs for details about how indexing works.

When the tests are complete, localsearch test-sandbox terminates the D-Bus daemon and all its child processes, and deletes the temporary directories before exiting.

Debugging test failures

Start with the general debugging guide in the :ref:developer-nodes` page.

If metadata is missing in the Localsearch index, you can enable logging from Localsearch in the Tox environment as follows:

  • Set the LOCALSEARCH_DEBUG = all environment variable to get verbose logs from localsearch.

  • Pass the –debug-sandbox argument to localsearch test-sandbox so logs from the localsearch services are written to stderr.

This should surface any errors in the logs.

Good luck!