
import dbus
import subprocess


def get_call_long(call):
    def call_long(*args, **kwargs):
        """Do an async call with a very long timeout (unless specified otherwise)"""
        if 'timeout' not in kwargs:
            kwargs['timeout'] = 100  # seconds
        return call(*args, **kwargs)

    return call_long







class Base():
    iface_prefix = None
    path_prefix = None
    bus = None

    def __init__(self,):
        self.iface_prefix = 'org.freedesktop.UDisks2'
        self.path_prefix = '/org/freedesktop/UDisks2'
        self.dbus = dbus.SystemBus()
        self.no_options = dbus.Dictionary(signature="sv")

        self._orig_call_async = self.dbus.call_async
        self._orig_call_blocking = self.dbus.call_blocking

        # overwrite bus call_async
        self.dbus.call_async = get_call_long(self._orig_call_async)

        # overwrite bus call_blocking
        self.dbus.call_blocking = get_call_long(self._orig_call_blocking)

    def get_object(self, path_suffix):
        # if given full path, just use it, otherwise prepend the prefix
        if path_suffix.startswith(self.path_prefix):
            path = path_suffix
        else:
            path = self.path_prefix + path_suffix
        try:
            # self.iface_prefix is the same as the DBus name we acquire
            obj = self.dbus.get_object(self.iface_prefix, path)
        except:
            obj = None
        return obj



    def get_interface(self, obj, iface_suffix):
        """Get interface for the given object either specified by an object path suffix
        (appended to the common UDisks2 prefix) or given as the object
        itself.
        :param obj: object to get the interface for
        :type obj: str or dbus.proxies.ProxyObject
        :param iface_suffix: suffix appended to the common UDisks2 interface prefix
        :type iface_suffix: str
        """
        if isinstance(obj, str):
            obj = self.get_object(obj)
        return dbus.Interface(obj, self.iface_prefix + iface_suffix)


    def run(self, command, out=False, version=True):
        res = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)

        out, err = res.communicate()
        if res.returncode != 0:
            output = out.decode().strip() + "\n\n" + err.decode().strip()
        else:
            output = out.decode().strip()
        if version :
            print("INFO: %s ..." % command)
            print(output)
        if out :
            return (res.returncode, output)
        return res.returncode





class Manage(Base):
    def __init__(self,):
        super(Manage, self).__init__()
        self.manager_obj = self.get_object('/Manager')
        self.manager_interface = self.get_interface(self.manager_obj, '.Manager')
        self.manager_interface.EnableModules(dbus.Boolean(True))

    def get_manager_raw_property(self, property_name):
        return self.get_property_raw(self.manager_obj, '.Manager', property_name)

    def get_manager_property(self, property_name):
        return self.get_property(self.manager_obj, '.Manager', property_name)


    def enable_module(self, module=None):
        if not module :
            self.manager_interface.EnableModules(dbus.Boolean(True))
            return True
        self.manager_interface.EnableModule(module, dbus.Boolean(True))
        return True



if __name__ == '__main__':

    o=Manage()

    o.run("systemctl  restart  udisks2")
    o.run("systemctl  status  udisks2")

    print(o.enable_module())
