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!