diff options
author | Kurt Jaeger <pi@FreeBSD.org> | 2019-09-21 18:45:22 +0000 |
---|---|---|
committer | Kurt Jaeger <pi@FreeBSD.org> | 2019-09-21 18:45:22 +0000 |
commit | afc03086202ce696e54c801d26c215310f4e2e31 (patch) | |
tree | 499d2ee3d97c9fc488cdeeaf3faf719b839a252f /graphics/rapid-photo-downloader/files/patch-raphodo_storage.py | |
parent | New port: sysutils/p5-File-Rename (diff) |
New port: graphics/rapid-photo-downloader
Rapid Photo Downloader imports photos and videos from cameras, phones,
memory cards and other devices at high speed. It can be configured to
rename photos and videos with meaningful filenames you specify. It can
also back up photos and videos as they are downloaded. It downloads
from and backs up to multiple devices simultaneously.
WWW: http://www.damonlynch.net/rapid/
PR: 240601
Submitted by: m.ne@gmx.net
Reviewed by: koobs
Notes
Notes:
svn path=/head/; revision=512533
Diffstat (limited to 'graphics/rapid-photo-downloader/files/patch-raphodo_storage.py')
-rw-r--r-- | graphics/rapid-photo-downloader/files/patch-raphodo_storage.py | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py b/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py new file mode 100644 index 000000000000..095d0263348c --- /dev/null +++ b/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py @@ -0,0 +1,319 @@ +--- raphodo/storage.py.orig 2019-07-09 21:12:19 UTC ++++ raphodo/storage.py +@@ -68,10 +68,9 @@ import xdg + import gi + + gi.require_version('GUdev', '1.0') +-gi.require_version('UDisks', '2.0') + gi.require_version('GExiv2', '0.10') + gi.require_version('GLib', '2.0') +-from gi.repository import GUdev, UDisks, GLib ++from gi.repository import GUdev, GLib + + from gettext import gettext as _ + +@@ -170,7 +169,7 @@ def get_media_dir() -> str: + + """ + +- if sys.platform.startswith('linux'): ++ if sys.platform.startswith('linux') or sys.platform.startswith('freebsd'): + media_dir = '/media/{}'.format(get_user_name()) + run_media_dir = '/run{}'.format(media_dir) + distro = get_distro() +@@ -278,7 +277,7 @@ class ValidMounts(): + self.validMountFolders, e.g. /media/<USER>, etc. + """ + +- if not sys.platform.startswith('linux'): ++ if not sys.platform.startswith('linux') and not sys.platform.startswith('freebsd'): + raise ("Mounts.setValidMountPoints() not implemented on %s", sys.platform()) + else: + try: +@@ -646,7 +645,7 @@ def get_default_file_manager() -> Tuple[Optional[str], + + _default_file_manager_probed = True + +- assert sys.platform.startswith('linux') ++ assert sys.platform.startswith('linux') or sys.platform.startswith('freebsd') + cmd = shlex.split('xdg-mime query default inode/directory') + try: + desktop_file = subprocess.check_output(cmd, universal_newlines=True) # type: str +@@ -791,7 +790,7 @@ def validate_download_folder(path: Optional[str], + + :param path: path to analyze + :param write_on_waccesss_failure: if os.access reports path is not writable, test +- nonetheless to see if it's writable by writing and deleting a test file ++ nonetheless to see if it's writable by writing and deleting a test file + :return: Tuple indicating validity and path made absolute + + >>> validate_download_folder('/some/bogus/and/ridiculous/path') +@@ -1008,259 +1007,6 @@ class CameraHotplug(QObject): + self.cameraRemoved.emit() + + +-class UDisks2Monitor(QObject): +- # Most of this class is Copyright 2008-2015 Canonical +- +- partitionMounted = pyqtSignal(str, list, bool) +- partitionUnmounted = pyqtSignal(str) +- +- loop_prefix = '/org/freedesktop/UDisks2/block_devices/loop' +- not_interesting = ( +- '/org/freedesktop/UDisks2/block_devices/dm_', +- '/org/freedesktop/UDisks2/block_devices/ram', +- '/org/freedesktop/UDisks2/block_devices/zram', +- ) +- +- def __init__(self, validMounts: ValidMounts) -> None: +- super().__init__() +- self.validMounts = validMounts +- +- @pyqtSlot() +- def startMonitor(self) -> None: +- self.udisks = UDisks.Client.new_sync(None) +- self.manager = self.udisks.get_object_manager() +- self.manager.connect('object-added', +- lambda man, obj: self._udisks_obj_added(obj)) +- self.manager.connect('object-removed', +- lambda man, obj: self._device_removed(obj)) +- +- # Track the paths of the mount points, which is useful when unmounting +- # objects. +- self.known_mounts = {} # type: Dict[str, str] +- for obj in self.manager.get_objects(): +- path = obj.get_object_path() +- fs = obj.get_filesystem() +- if fs: +- mount_points = fs.get_cached_property('MountPoints').get_bytestring_array() +- if mount_points: +- self.known_mounts[path] = mount_points[0] +- logging.debug("... UDisks2 monitor started") +- +- def _udisks_obj_added(self, obj) -> None: +- path = obj.get_object_path() +- for boring in self.not_interesting: +- if path.startswith(boring): +- return +- block = obj.get_block() +- if not block: +- return +- +- drive = self._get_drive(block) +- +- part = obj.get_partition() +- is_system = block.get_cached_property('HintSystem').get_boolean() +- is_loop = path.startswith(self.loop_prefix) and not \ +- block.get_cached_property('ReadOnly').get_boolean() +- if not is_system or is_loop: +- if part: +- self._udisks_partition_added(obj, block, drive, path) +- +- def _get_drive(self, block) -> Optional[UDisks.Drive]: +- drive_name = block.get_cached_property('Drive').get_string() +- if drive_name != '/': +- return self.udisks.get_object(drive_name).get_drive() +- else: +- return None +- +- def _udisks_partition_added(self, obj, block, drive, path) -> None: +- logging.debug('UDisks: partition added: %s' % path) +- fstype = block.get_cached_property('IdType').get_string() +- logging.debug('Udisks: id-type: %s' % fstype) +- +- fs = obj.get_filesystem() +- +- if fs: +- icon_names = self.get_icon_names(obj) +- +- if drive is not None: +- ejectable = drive.get_property('ejectable') +- else: +- ejectable = False +- mount_point = '' +- mount_points = fs.get_cached_property('MountPoints').get_bytestring_array() +- if len(mount_points) == 0: +- try: +- logging.debug("UDisks: attempting to mount %s", path) +- mount_point = self.retry_mount(fs, fstype) +- if not mount_point: +- raise Exception +- else: +- logging.debug("UDisks: successfully mounted at %s", mount_point) +- except Exception: +- logging.error('UDisks: could not mount the device: %s', path) +- return +- else: +- mount_point = mount_points[0] +- logging.debug("UDisks: already mounted at %s", mount_point) +- +- self.known_mounts[path] = mount_point +- if self.validMounts.pathIsValidMountPoint(mount_point): +- self.partitionMounted.emit(mount_point, icon_names, ejectable) +- +- else: +- logging.debug("Udisks: partition has no file system %s", path) +- +- def retry_mount(self, fs, fstype) -> str: +- # Variant parameter construction Copyright Bernard Baeyens, and is +- # licensed under GNU General Public License Version 2 or higher. +- # https://github.com/berbae/udisksvm +- list_options = '' +- if fstype == 'vfat': +- list_options = 'flush' +- elif fstype == 'ext2': +- list_options = 'sync' +- G_VARIANT_TYPE_VARDICT = GLib.VariantType.new('a{sv}') +- param_builder = GLib.VariantBuilder.new(G_VARIANT_TYPE_VARDICT) +- optname = GLib.Variant.new_string('fstype') # s +- value = GLib.Variant.new_string(fstype) +- vvalue = GLib.Variant.new_variant(value) # v +- newsv = GLib.Variant.new_dict_entry(optname, vvalue) # {sv} +- param_builder.add_value(newsv) +- optname = GLib.Variant.new_string('options') +- value = GLib.Variant.new_string(list_options) +- vvalue = GLib.Variant.new_variant(value) +- newsv = GLib.Variant.new_dict_entry(optname, vvalue) +- param_builder.add_value(newsv) +- vparam = param_builder.end() # a{sv} +- +- # Try to mount until it does not fail with "Busy" +- timeout = 10 +- while timeout >= 0: +- try: +- return fs.call_mount_sync(vparam, None) +- except GLib.GError as e: +- if not 'UDisks2.Error.DeviceBusy' in e.message: +- raise +- logging.debug('Udisks: Device busy.') +- time.sleep(0.3) +- timeout -= 1 +- return '' +- +- def get_icon_names(self, obj: UDisks.Object) -> List[str]: +- # Get icon information, if possible +- icon_names = [] +- if have_gio: +- info = self.udisks.get_object_info(obj) +- icon = info.get_icon() +- if isinstance(icon, Gio.ThemedIcon): +- icon_names = icon.get_names() +- return icon_names +- +- # Next four class member functions from Damon Lynch, not Canonical +- def _device_removed(self, obj: UDisks.Object) -> None: +- # path here refers to the udev / udisks path, not the mount point +- path = obj.get_object_path() +- if path in self.known_mounts: +- mount_point = self.known_mounts[path] +- del self.known_mounts[path] +- self.partitionUnmounted.emit(mount_point) +- +- def get_can_eject(self, obj: UDisks.Object) -> bool: +- block = obj.get_block() +- drive = self._get_drive(block) +- if drive is not None: +- return drive.get_property('ejectable') +- return False +- +- def get_device_props(self, device_path: str) -> Tuple[List[str], bool]: +- """ +- Given a device, get the icon names suggested by udev, and +- determine whether the mount is ejectable or not. +- :param device_path: system path of the device to check, +- e.g. /dev/sdc1 +- :return: icon names and eject boolean +- """ +- +- object_path = '/org/freedesktop/UDisks2/block_devices/{}'.format( +- os.path.split(device_path)[1]) +- obj = self.udisks.get_object(object_path) +- icon_names = self.get_icon_names(obj) +- can_eject = self.get_can_eject(obj) +- return (icon_names, can_eject) +- +- @pyqtSlot(str) +- def unmount_volume(self, mount_point: str) -> None: +- +- G_VARIANT_TYPE_VARDICT = GLib.VariantType.new('a{sv}') +- param_builder = GLib.VariantBuilder.new(G_VARIANT_TYPE_VARDICT) +- +- # Variant parameter construction Copyright Bernard Baeyens, and is +- # licensed under GNU General Public License Version 2 or higher. +- # https://github.com/berbae/udisksvm +- +- optname = GLib.Variant.new_string('force') +- value = GLib.Variant.new_boolean(False) +- vvalue = GLib.Variant.new_variant(value) +- newsv = GLib.Variant.new_dict_entry(optname, vvalue) +- param_builder.add_value(newsv) +- +- vparam = param_builder.end() # a{sv} +- +- path = None +- # Get the path from the dict we keep of known mounts +- for key, value in self.known_mounts.items(): +- if value == mount_point: +- path = key +- break +- if path is None: +- logging.error("Could not find UDisks2 path used to be able to unmount %s", mount_point) +- +- fs = None +- for obj in self.manager.get_objects(): +- opath = obj.get_object_path() +- if path == opath: +- fs = obj.get_filesystem() +- if fs is None: +- logging.error("Could not find UDisks2 filesystem used to be able to unmount %s", +- mount_point) +- +- logging.debug("Unmounting %s...", mount_point) +- try: +- fs.call_unmount(vparam, None, self.umount_volume_callback, (mount_point, fs)) +- except GLib.GError: +- value = sys.exc_info()[1] +- logging.error('Unmounting failed with error:') +- logging.error("%s", value) +- +- def umount_volume_callback(self, source_object: UDisks.FilesystemProxy, +- result: Gio.AsyncResult, +- user_data: Tuple[str, UDisks.Filesystem]) -> None: +- """ +- Callback for asynchronous unmount operation. +- +- :param source_object: the FilesystemProxy object +- :param result: result of the unmount +- :param user_data: mount_point and the file system +- """ +- +- mount_point, fs = user_data +- +- try: +- if fs.call_unmount_finish(result): +- logging.debug("...successfully unmounted %s", mount_point) +- else: +- # this is the result even when the unmount was unsuccessful +- logging.debug("...possibly failed to unmount %s", mount_point) +- except GLib.GError as e: +- logging.error('Exception occurred unmounting %s', mount_point) +- logging.exception('Traceback:') +- except: +- logging.error('Exception occurred unmounting %s', mount_point) +- logging.exception('Traceback:') +- +- self.partitionUnmounted.emit(mount_point) +- +- + if have_gio: + class GVolumeMonitor(QObject): + r""" +@@ -1577,7 +1323,7 @@ def get_mount_size(mount: QStorageInfo) -> Tuple[int, + """ + Uses GIO to get bytes total and bytes free (available) for the mount that a + path is in. +- ++ + :param path: path located anywhere in the mount + :return: bytes_total, bytes_free + """ |