Category Archives: GNOME

Posts about GNOME and programming for it.

Coding style checks in CI

For a few weeks now, we’ve had coding style and thinko checks running in CI for GLib, long enough to see that it’s working OK (check out this pipeline!) and is perhaps time to share with others.

There are two jobs in the checks, both of which run in a new style-check stage of our CI pipeline, which runs before anything else. One job checks the coding style of a merge request, using clang-format. The other job checks for any lines which introduce TODO comments (or similar). These jobs are intended to be fast, but also to not fail the pipeline if they produce warnings. Coding style is subjective, and nobody has yet come up with a mechanical style description which doesn’t have ugly corner cases. So the intention of these jobs is to help remind people of the coding style, to avoid reviewers having to check coding style manually, and hence to only end up thinking about it or discussing it when the CI says the style is wrong.

The first job, style-check-diff, uses a script to work out the diff from the merge request’s branch point, and then passes that to clang-format-diff.py, a script from LLVM which uses clang-format to reformat only the changed lines in a diff. If any reformatting occurs, that means the merge request differs from the GLib coding style (as described by .clang-format) and should be warned about.

There are some limitations to clang-format: it can’t completely describe how the GLib coding style aligns function arguments. That’s unfortunate, because GNOME Builder aligns function arguments by default (and it’s nice behaviour). Hopefully somebody will implement support in clang-format for this sometime, so that it can accurately describe the coding style which is used by a large number of GNOME projects.

These coding style checks are work by Pavlo Solntsev and Emmanuel Fleury. Thanks!

The second job, check-todos, also uses a script to work out the diff from the merge request’s branch point. It passes that to a little Python program which checks for banned words in the commit message and added lines in the diff. The aim is to prevent any comments containing TODO or WIP from accidentally getting merged, as these strings are often used by developers to indicate something they need to come back to before they’re finished — and it’s easy to miss them!

I’ve been using the convention that comments containing FIXME are OK to be merged, as they indicate something that will need updating in future, but can be merged as-is for now (such as a workaround).

Feedback, improvements, and copying welcome. These scripts should run on any CI image which has git, clang and Python.

Interested in a GUADEC remote attendance party in the UK, July 2020?

tl;dr: Fill out this 5 minute survey if you want to meet up in the UK to attend GUADEC remotely.

GUADEC is in Mexico this year, which is great! This means that, for once, the tables are turned and people in Europe will get to experience what everyone in the rest of the world normally experiences for GUADEC: long travel times. That’s no bad thing, but I suspect it means there’ll be more people from Europe who are taking a break from GUADEC this year.

I don’t want to travel to GUADEC, but do want to keep up with the conference and see people. So I’m looking at organising a UK remote attendance party for GUADEC, where anyone who isn’t going to Mexico is welcome to come along for a few days, follow the conference remotely, hack together, and socialise together.

This would be open to the same audience as GUADEC itself, but limited to people in the UK. It would be great if people in other countries who can’t make it to Mexico also got together to follow the conference, but I don’t want to encourage travel from Europe to the UK to attend this party. This is not (currently) an official GNOME event.

So, to get the ball rolling, here’s a 5 minute survey. Please fill it in if you’re at all interested in any of this. Thanks!

Testing D-Bus clients with libglib-testing

I’ve always found it a bit of a pain to write unit tests for D-Bus client libraries, where you’re testing that your code calls methods on a D-Bus service appropriately and, in particular, correctly handles a variety of return values and errors. Writing unit tests like this traditionally involves writing a mock D-Bus service for them to talk to, which validates the input it receives and provides appropriate responses. That often goes most of the way towards reimplementing the entirety of the real D-Bus service.

Part of the difficulty of testing D-Bus clients like this is synchronising the state of the mock D-Bus service with the test code, and part of the difficulty is the fact that you have to write mock service code for each D-Bus method before you can test it — which is a lot of investment in writing code before you can even start writing your unit tests themselves.

As an experiment in finding a better way of doing this kind of testing, I’ve written GtDBusQueue in libglib-testing, and I think it might be ready for some wider use. Thanks a lot to Endless for allowing me to work on such projects! I’ve used it in a couple of projects now, particularly in libmalcontent (which handles implementing parental controls policy on the desktop, and needs to talk to the accountsservice D-Bus service).

GtDBusQueue basically implements a queue for D-Bus messages received from your D-Bus client code. Each D-Bus message is typically a method call: your unit test can inspect the queue, and will typically pop messages off the front of the queue to assert they match a certain method call, and then send a reply to that call.

A key feature of GtDBusQueue is that it operates as a queue of D-Bus messages, rather than as a collection of D-Bus object proxies (typically GDBusObjectProxy), which means that it can be used to handle method calls to arbitrary D-Bus object paths without having to implement a new proxy class for each of them.

Message matching is typically implemented using gt_dbus_queue_assert_pop_message() (though other methods are available which give you finer-grained control over message matching and removal from the queue). It blocks until the queue is not empty, pops the first message off the front, asserts that its D-Bus object path, interface name and method name are as expected, and then returns the method call parameters to your unit test code using the same syntax as g_variant_get(). Your unit test code can then check the values of those parameters how it pleases.

If your D-Bus client code is asynchronous, GtDBusQueue can be used inline in your unit test. Your client code will start a method call asynchronously, then the test code will pop the method call off the GtDBusQueue, check it and reply, and then your client code will asynchronously finish its method call and handle the results. You can see an example of this in the test_app_filter_bus_get_error_disabled() test in libmalcontent which, in a single function, tests that the mct_manager_get_app_filter_async() API can correctly handle a D-Bus InvalidArgs error returned by the second D-Bus call it makes.

If your D-Bus client code is synchronous, GtDBusQueue needs to run in a thread using gt_dbus_queue_set_server_func(), since otherwise it would block your D-Bus client code. The unit test and the server thread take turns at blocking on pushing messages onto the queue or popping them off. You can see an example of this (which also works for asynchronous client code, testing both the synchronous and asynchronous code paths in a single test) in the GtDBusQueue usage example in its documentation.

That’s a brief introduction to GtDBusQueue; hopefully it’s given you a bit of an idea about where it’s appropriate and how it can be used. There’s documentation in the source code (including some usage examples), and a load of usage examples in libmalcontent. Feedback, questions and improvements are always welcome!

g_get_os_info() and GLib 2.63.1

GLib 2.63.1 has been released. The final new API to mention in this mini-series of blog posts about what’s in 2.63.1 is g_get_os_info().

g_get_os_info() is a way to get identifying information about the OS. On Linux, this is gathered from /etc/os-release. On other OSs, it’s gathered using platform-specific APIs (on other Unixes, this means falling back to uname()).

It was written by Robert Ancell, with contributions from Ruslan Izhbulatov, Ting-Wei Lan and Simon McVittie; and it came out of proposals from Robert at GUADEC.

To use it, pass it a key, like G_OS_INFO_KEY_PRETTY_NAME, and it’ll return a newly-allocated string with the corresponding value for the current OS, or NULL if there was none. Different OSs support different sets of keys, and the amount of support and set of keys may change over time.

An example:

g_autofree gchar *os_name = g_get_os_info (G_OS_INFO_KEY_PRETTY_NAME);
g_print ("OS: %s\n", os_name);
/* Prints “OS: Fedora 30 (Workstation Edition)” for me */

g_array_steal() and g_ptr_array_steal() in GLib 2.63.1

Another set of new APIs in the upcoming GLib 2.63.1 release allow you to steal all the contents of a GArray, GPtrArray or GByteArray, and continue using the array container to add more contents to in future.

This is work by Paolo Bonzini and Emmanuel Fleury, and will be available in the soon-to-be-released 2.63.1 release.

Here’s a quick example using GPtrArray — usage is similar in GArray and GByteArray:

g_autoptr(GPtrArray) chunk_buffer = g_ptr_array_new_with_free_func (g_bytes_unref);

/* Some part of your application appends a number of chunks to the pointer array. */
g_ptr_array_add (chunk_buffer, g_bytes_new_static ("hello", 5));
g_ptr_array_add (chunk_buffer, g_bytes_new_static ("world", 5));

…

/* Periodically, the chunks need to be sent as an array-and-length to some other part of the program. */
GBytes **chunks;
gsize n_chunks;

chunks = g_ptr_array_steal (chunk_buffer, &n_chunks);
for (gsize i = 0; i < n_chunks; i++)
  {
    /* Do something with each chunk here, and then free them, since g_ptr_array_steal() transfers ownership of all the elements and the array to the caller. */
    …

    g_bytes_unref (chunks[i]);
  }

g_free (chunks);

/* After calling g_ptr_array_steal(), the pointer array can be reused for the next set of chunks. */
g_assert (chunk_buffer->len == 0);

A diary program for GNOME: Almanah Diary

tl;dr: I’m giving up maintaining Almanah as it no longer scratches my itch — it’s yours if you want it, but maybe it should die in favour of more modern apps like Lifeograph or Red Notebook.

Almanah Diary is a project I started many years ago for maintaining a personal diary, with encryption and tracking of the events you did that day (from your calendar). It’s been neglected for a long time — given that I no longer use it, I have no incentive to maintain it and improve it, and have only held on to maintainership for so long out of a feeling of duty.

However, having me listed as a maintainer might have been giving people the false impression that it was actually maintained. So I’m removing myself as maintainer, having just made the 0.12.0 release. Álvaro Peña is also listed as a maintainer, but hasn’t been active for over a year. The project is technically now his, but if someone else turns up wanting to work on it, I am happy to add them as a co-maintainer, especially if they are going to revitalise things.

Other diary programs exist, and while I haven’t tried them, Lifeograph and Red Notebook look like they could be much more featureful and maintained than Almanah. Perhaps it’s time for them to be blessed as GNOME apps?

That said, if you want to take over maintenance of Almanah, please be my guest. It’s been ported to Meson, but needs some UI updates and needs flatpacking and putting on flathub.

If you’re interested, please get in touch, or send a merge request through.

Maintainer wanted: gnome-directory-thumbnailer

tl;dr: I’m giving up maintaining gnome-directory-thumbnailer as it no longer scratches my itch — it’s yours if you want it.

gnome-directory-thumbnailer is a little project I started a while ago for creating thumbnails for directories (rather than showing a plain directory icon for them in the file manager). Times change, I no longer have the itch that it was developed to scratch, and so I’m giving up maintenance of it after making the 0.1.11 release.

If you use it, or think you should use it, please care about it and take over maintenance. It needs porting to Meson, and some changes to handle working in the brave new world of sandboxed thumbnailers. It’s not a complicated code base to maintain.

If you’re interested, please get in touch, or send a merge request through.

GTimeVal deprecation in GLib 2.61.2

tl;dr: GTimeVal and g_get_current_time() are not year-2038-safe and have been deprecated; use GDateTime and g_get_real_time() instead.

One of the latest changes in GLib (released in 2.61.2) is the deprecation of GTimeVal, g_get_current_time(), and a number of other time functions. This is because we can’t guarantee they’re wide enough on all platforms to be year-2038-safe.

Instead, you should use GDateTime or, if you just need to store epoch time, guint64. They are year-2038-safe — and with that, GLib should be entirely year-2038-safe.

GTimeVal is used in a number of places, and widespread (but simple) changes will need to be made to stop using it. You will likely have already seen some deprecation warnings popping up to inform you of this, if you use any C-based and GLib-based libraries.

If you can’t allocate time to fixing these deprecation warnings yet, you can silence them by explicitly stating your minimum and maximum supported versions of GLib. If your minimum supported version of GLib is older than 2.62, you won’t see deprecation warnings for GTimeVal (since it was deprecated in 2.62, and your code is claiming to need to support older GLib versions than that).

You can do that by setting the following in meson.build:

common_c_args = [
  '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_44',
  '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_60',
]

and then using common_c_args in the c_args field of every executable and library you define in Meson. Your minimum required GLib version should match the version you list in your dependency('glib-2.0').

So,

GTimeVal tv;
g_get_current_time (&amp;tv);
g_message ("Current time: %lu", tv.tv_sec);

becomes

gint64 tv;
tv = g_get_real_time ();
g_message ("Current time: %" G_GINT64_FORMAT, tv / G_USEC_PER_SEC);

And

GTimeVal tv;
if (!g_time_val_from_iso8601 ("2019-08-24T10:47:05Z", &amp;tv))
  g_error ("Conversion failed");

becomes

g_autoptr(GDateTime) dt = g_date_time_new_from_iso8601 ("2019-08-24T10:47:05Z", NULL);
if (dt == NULL)
  {
    g_error ("Conversion failed");
    return;
  }

gint64 time_val = g_date_time_to_unix (dt);
/* or (simpler) use the #GDateTime directly */

Finally

GTimeVal tv = some timeval;
g_autofree gchar *tv_in_iso8601 = g_time_val_to_iso8601 (&amp;tv);
g_message ("In ISO 8601 format: %s", tv_in_iso8601);

becomes the following, using the new g_date_time_format_iso8601() function:

g_autoptr(GDateTime) dt = some GDateTime;
g_autofree gchar *dt_in_iso8601 = g_date_time_format_iso8601 (dt);
g_message ("In ISO 8601 format: %s", dt_in_iso8601);

g_assert_finalize_object() in GLib 2.61.2

One more API in this mini-series! g_assert_finalize_object(), which is available in GLib 2.61.2, which was released today.

This one’s useful when writing tests (and only when writing tests). It’s been put together by Simon McVittie to implement the common pattern needed in tests, where you want to unref a GObject and assert that you just dropped the final reference to the object — i.e., check that no references to the object have been leaked in the test.

Use it in place of g_object_unref(). If G_DISABLE_ASSERT is defined, it will actually just be a call to g_object_unref().

Here’s an example usage of it, straight out of the GLib unit test for it:

static void
test_assert_finalize_object (void)
{
  GObject *obj = g_object_new (G_TYPE_OBJECT, NULL);

  /* do some things with the obj here */

  g_assert_finalize_object (obj);
}