importloggingimportoptparseimportdbusimportgobjectimportpynotifyimportudiskie.deviceclassDeviceState:def__init__(self,mounted,has_media):self.mounted=mountedself.has_media=has_mediaclassAutoMounter:def__init__(self,bus=None):self.log=logging.getLogger('udiskie.mount.AutoMounter')self.last_device_state={}ifnotbus:fromdbus.mainloop.glibimportDBusGMainLoopDBusGMainLoop(set_as_default=True)self.bus=dbus.SystemBus()else:self.bus=busself.bus.add_signal_receiver(self.device_added,signal_name='DeviceAdded',bus_name='org.freedesktop.UDisks')self.bus.add_signal_receiver(self.device_removed,signal_name='DeviceRemoved',bus_name='org.freedesktop.UDisks')self.bus.add_signal_receiver(self.device_changed,signal_name='DeviceChanged',bus_name='org.freedesktop.UDisks')def_mount_device(self,device):ifdevice.is_handleable():try:ifnotdevice.is_mounted():filesystem=str(device.id_type())options=[]try:device.mount(filesystem,options)self.log.info('mounted device %s'%(device,))exceptdbus.exceptions.DBusException,dbus_err:self.log.error('failed to mount device %s: %s'%(device,dbus_err))returnmount_paths=', '.join(device.mount_paths())pynotify.Notification('Device mounted','%s mounted on %s'%(device.device_file(),mount_paths),'drive-removable-media').show()finally:self._store_device_state(device)def_store_device_state(self,device):state=DeviceState(device.is_mounted(),device.has_media())self.last_device_state[device.device_path]=statedef_remove_device_state(self,device):ifdevice.device_pathinself.last_device_state:delself.last_device_state[device.device_path]def_get_device_state(self,device):returnself.last_device_state.get(device.device_path)defmount_present_devices(self):"""Mount handleable devices that are already present."""fordeviceinudiskie.device.get_all(self.bus):self._mount_device(device)defdevice_added(self,device):self.log.debug('device added: %s'%(device,))udiskie_device=udiskie.device.Device(self.bus,device)# Since the device just appeared we don't want the old state.self._remove_device_state(udiskie_device)self._mount_device(udiskie_device)defdevice_removed(self,device):self.log.debug('device removed: %s'%(device,))self._remove_device_state(udiskie.device.Device(self.bus,device))defdevice_changed(self,device):self.log.debug('device changed: %s'%(device,))udiskie_device=udiskie.device.Device(self.bus,device)last_state=self._get_device_state(udiskie_device)ifnotlast_state:# First time we saw the device, try to mount it.self._mount_device(udiskie_device)else:media_added=Falseifudiskie_device.has_media()andnotlast_state.has_media:media_added=Trueifmedia_addedandnotlast_state.mounted:# Wasn't mounted before, but it has new media now.self._mount_device(udiskie_device)self._store_device_state(udiskie_device)defcli(args):parser=optparse.OptionParser()parser.add_option('-v','--verbose',action='store_true',dest='verbose',default=False,help='verbose output')(options,args)=parser.parse_args(args)log_level=logging.INFOifoptions.verbose:log_level=logging.DEBUGlogging.basicConfig(level=log_level,format='%(message)s')pynotify.init('udiskie.mount')mounter=AutoMounter()mounter.mount_present_devices()returngobject.MainLoop().run()