> On 19-02-12 14:39:32, Georg Faerber wrote: >> That is: option one of the second proposal ("quickly patch together a >> Python 2 Nautilus extension that wraps mat2's CLI"). > > Unfortunately, and sorry again for my delay working on this, there was > no feedback. I've poked Jonas today on IRC privately, asking if he had a > comment, he said "sounds good, go ahead", and so I did. Ouch, this is unexpected and sounds like a hack, but I guess this is the only way to get a useable Mat2 into Buster before the hard freeze.
I took a look at your patch, and improved it a bit. Improved as in tried to reduce the number of modifications, and made it more Pythonic. I'm not super-duper-confident that this approach won't result in some weird issues, but again, I guess it's better than nothing. Thank you for taking the time to write this patch and taking care of mat2 in Debian ♥
--- a/nautilus/mat2.py +++ b/nautilus/mat2.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python3 - +#!/usr/bin/env python +# -*- coding: utf-8 -*- """ Because writing GUI is non-trivial (cf. https://0xacab.org/jvoisin/mat2/issues/3), we decided to write a Nautilus extensions instead @@ -12,34 +12,39 @@ # pylint: disable=no-name-in-module,unused-argument,no-self-use,import-error -import queue +import Queue as queue import threading -from typing import Tuple, Optional, List -from urllib.parse import unquote +from urlparse import unquote import gi gi.require_version('Nautilus', '3.0') gi.require_version('Gtk', '3.0') gi.require_version('GdkPixbuf', '2.0') from gi.repository import Nautilus, GObject, Gtk, Gio, GLib, GdkPixbuf +import subprocess +import mimetypes -from libmat2 import parser_factory +def _remove_metadata(fpath): + """ This is a simple wrapper around the mat2 cli. """ + try: + return subprocess.check_output(['mat2', fpath]) + except subprocess.CalledProcessError, e: + return e.output + + +def _guess_mtype(fpath): + """ Function to guess the mtype of a given file. """ + mtype, _ = mimetypes.guess_type(fpath) + return mtype -def _remove_metadata(fpath) -> Tuple[bool, Optional[str]]: - """ This is a simple wrapper around libmat2, because it's - easier and cleaner this way. - """ - parser, mtype = parser_factory.get_parser(fpath) - if parser is None: - return False, mtype - return parser.remove_all(), mtype class Mat2Extension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationWidgetProvider): """ This class adds an item to the right-clic menu in Nautilus. """ def __init__(self): - super().__init__() + super(Mat2Extension, self).__init__() self.infobar_hbox = None self.infobar = None self.failed_items = list() @@ -61,7 +66,7 @@ self.infobar.get_content_area().pack_start(self.infobar_hbox, True, True, 0) self.infobar.show_all() - def get_widget(self, uri, window) -> Gtk.Widget: + def get_widget(self, uri, window): """ This is the method that we have to implement (because we're a LocationWidgetProvider) in order to show our infobar. """ @@ -103,7 +108,7 @@ window.show_all() @staticmethod - def __validate(fileinfo) -> Tuple[bool, str]: + def __validate(fileinfo): """ Validate if a given file FileInfo `fileinfo` can be processed. Returns a boolean, and a textreason why""" if fileinfo.get_uri_scheme() != "file" or fileinfo.is_directory(): @@ -112,7 +117,7 @@ return False, "Not writeable" return True, "" - def __create_treeview(self) -> Gtk.TreeView: + def __create_treeview(self): liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str) treeview = Gtk.TreeView(model=liststore) @@ -144,7 +149,7 @@ treeview.show_all() return treeview - def __create_progressbar(self) -> Gtk.ProgressBar: + def __create_progressbar(self): """ Create the progressbar used to notify that files are currently being processed. """ @@ -161,11 +166,11 @@ return progressbar - def __update_progressbar(self, processing_queue, progressbar) -> bool: + def __update_progressbar(self, processing_queue, progressbar): """ This method is run via `Glib.add_idle` to update the progressbar.""" try: fname = processing_queue.get(block=False) except queue.Empty: return True # `None` is the marker put in the queue to signal that every selected @@ -186,7 +191,7 @@ self.infobar.show_all() return True - def __clean_files(self, files: list, processing_queue: queue.Queue) -> bool: + def __clean_files(self, files, processing_queue): """ This method is threaded in order to avoid blocking the GUI while cleaning up the files. """ @@ -200,8 +205,9 @@ continue fpath = unquote(fileinfo.get_uri()[7:]) # `len('file://') = 7` - success, mtype = _remove_metadata(fpath) - if not success: + if _remove_metadata(fpath): + mtype = _guess_mtype(fpath) self.failed_items.append((fname, mtype, 'Unsupported/invalid')) processing_queue.put(None) # signal that we processed all the files return True @@ -215,7 +221,7 @@ progressbar.set_pulse_step = 1.0 / len(files) self.infobar.show_all() processing_queue = queue.Queue() GLib.idle_add(self.__update_progressbar, processing_queue, progressbar) thread = threading.Thread(target=self.__clean_files, args=(files, processing_queue)) @@ -226,7 +232,7 @@ """ https://bugzilla.gnome.org/show_bug.cgi?id=784278 """ return None - def get_file_items(self, window, files) -> Optional[List[Nautilus.MenuItem]]: + def get_file_items(self, window, files): """ This method is the one allowing us to create a menu item. """ # Do not show the menu item if not a single file has a chance to be