importwarningswarnings.filterwarnings("ignore",".*could not open display.*",Warning)warnings.filterwarnings("ignore",".*g_object_unref.*",Warning)importloggingimportoptparseimportosimportdbusimportgobjectimportgioimportpynotifytry:fromxdg.BaseDirectoryimportxdg_config_homeexceptImportError:xdg_config_home=os.path.expanduser('~/.config')importudiskie.deviceimportudiskie.matchclassDeviceState:def__init__(self,mounted,has_media):self.mounted=mountedself.has_media=has_mediaclassAutoMounter:CONFIG_PATH='udiskie/filters.conf'def__init__(self,bus=None,filter_file=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=busifnotfilter_file:filter_file=os.path.join(xdg_config_home,self.CONFIG_PATH)self.filters=udiskie.match.FilterMatcher((filter_file,))self.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():fstype=str(device.id_type())options=self.filters.get_mount_options(device)S='attempting to mount device %s (%s:%s)'self.log.info(S%(device,fstype,options))try:device.mount(fstype,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())try:pynotify.Notification('Device mounted','%s mounted on %s'%(device.device_file(),mount_paths),'drive-removable-media').show()exceptgio.Error:passfinally: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')parser.add_option('-f','--filters',action='store',dest='filters',default=None,metavar='FILE',help='filter FILE')(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(bus=None,filter_file=options.filters)mounter.mount_present_devices()returngobject.MainLoop().run()