Index: head/graphics/rapid-photo-downloader/Makefile =================================================================== --- head/graphics/rapid-photo-downloader/Makefile (revision 533751) +++ head/graphics/rapid-photo-downloader/Makefile (revision 533752) @@ -1,54 +1,58 @@ # $FreeBSD$ PORTNAME= rapid-photo-downloader -DISTVERSION= 0.9.17 -PORTREVISION= 2 +DISTVERSION= 0.9.23 CATEGORIES= graphics MASTER_SITES= https://launchpad.net/rapid/pyqt/${PORTVERSION}/+download/ MAINTAINER= m.ne@gmx.net COMMENT= Import photos and videos efficiently and reliably LICENSE= GPLv3 BUILD_DEPENDS= intltool-update:textproc/intltool LIB_DEPENDS= libgexiv2.so:graphics/gexiv2 \ libgudev-1.0.so:devel/libgudev RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}arrow>0:devel/py-arrow@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}Babel>0:devel/py-babel@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}colour>0:graphics/py-colour@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}dateutil>2.2:devel/py-dateutil@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}easygui>=0:x11-toolkits/py-easygui@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}gobject3>0:devel/py-gobject3@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}gphoto2>=1.4.0:graphics/py-gphoto2@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}gstreamer1>=1.0:multimedia/py-gstreamer1@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}notify2>0:devel/py-notify2@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}psutil>=3.4.2:sysutils/py-psutil@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}pymediainfo>=1.0:multimedia/py-pymediainfo@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}pyzmq>0:net/py-pyzmq@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}rawkit>0:graphics/py-rawkit@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}requests>=0:www/py-requests@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}sortedcontainers>0:devel/py-sortedcontainers@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}sqlite3>0:databases/py-sqlite3@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}tenacity>0:devel/py-tenacity@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}tornado>=4.1:www/py-tornado@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}xdg>0:devel/py-xdg@${PY_FLAVOR} \ exiftool:graphics/p5-Image-ExifTool USES= desktop-file-utils gettext pyqt:5 python:3.4+ qt:5 USE_PYTHON= autoplist distutils noflavors USE_QT= imageformats_run USE_PYQT= core gui network sip widgets BINARY_ALIAS= python3=${PYTHON_VERSION} NO_ARCH= yes OPTIONS_DEFINE= COLOUR PROGRESS OPTIONS_DEFAULT= COLOUR PROGRESS COLOUR_DESC= generates coloured program output PROGRESS_DESC= shows a progress bar on the command line COLOUR_RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}colorlog>0:devel/py-colorlog@${PY_FLAVOR} PROGRESS_RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}pyprind>=1.4.0:misc/py-pyprind@${PY_FLAVOR} + +post-patch: + @${REINPLACE_CMD} -e 's|'share/man/man1'|'man/man1'|' \ + ${WRKSRC}/setup.py .include Index: head/graphics/rapid-photo-downloader/distinfo =================================================================== --- head/graphics/rapid-photo-downloader/distinfo (revision 533751) +++ head/graphics/rapid-photo-downloader/distinfo (revision 533752) @@ -1,3 +1,3 @@ -TIMESTAMP = 1568565754 -SHA256 (rapid-photo-downloader-0.9.17.tar.gz) = 26dbce5d2e775af39ce8f17224a862ed71a86a47768a7ebb04193d96535c7883 -SIZE (rapid-photo-downloader-0.9.17.tar.gz) = 6877573 +TIMESTAMP = 1587355599 +SHA256 (rapid-photo-downloader-0.9.23.tar.gz) = 2bfe30e237803870486ee5e79e482529da4c592930e48d1ba20c03f36f6719f4 +SIZE (rapid-photo-downloader-0.9.23.tar.gz) = 8101336 Index: head/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py =================================================================== --- head/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py (revision 533751) +++ head/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py (revision 533752) @@ -1,140 +1,140 @@ ---- raphodo/rapid.py.orig 2019-08-18 03:58:11 UTC +--- raphodo/rapid.py.orig 2020-04-17 01:22:23 UTC +++ raphodo/rapid.py -@@ -98,7 +98,7 @@ from PyQt5.QtNetwork import QLocalSocket, QLocalServer +@@ -96,7 +96,7 @@ from PyQt5.QtNetwork import QLocalSocket, QLocalServer import sip from raphodo.storage import ( - ValidMounts, CameraHotplug, UDisks2Monitor, GVolumeMonitor, have_gio, + ValidMounts, CameraHotplug, GVolumeMonitor, have_gio, has_one_or_more_folders, mountPaths, get_desktop_environment, get_desktop, gvfs_controls_mounts, get_default_file_manager, validate_download_folder, validate_source_folder, get_fdo_cache_thumb_base_directory, WatchDownloadDirs, get_media_dir, -@@ -584,12 +584,12 @@ class RapidWindow(QMainWindow): +@@ -609,12 +609,12 @@ class RapidWindow(QMainWindow): self.prefs.backup_files = backup else: logging.info("Backing up files: %s", self.prefs.backup_files) - + if backup_auto_detect is not None: self.prefs.backup_device_autodetection = backup_auto_detect elif self.prefs.backup_files: logging.info("Backup device auto detection: %s", self.prefs.backup_device_autodetection) - + if photo_backup_identifier is not None: self.prefs.photo_backup_identifier = photo_backup_identifier elif self.prefs.backup_files and self.prefs.backup_device_autodetection: -@@ -599,7 +599,7 @@ class RapidWindow(QMainWindow): +@@ -624,7 +624,7 @@ class RapidWindow(QMainWindow): self.prefs.video_backup_identifier = video_backup_identifier elif self.prefs.backup_files and self.prefs.backup_device_autodetection: logging.info("video backup identifier: %s", self.prefs.video_backup_identifier) - + if photo_backup_location is not None: self.prefs.backup_photo_location = photo_backup_location elif self.prefs.backup_files and not self.prefs.backup_device_autodetection: -@@ -934,18 +934,6 @@ class RapidWindow(QMainWindow): +@@ -939,18 +939,6 @@ class RapidWindow(QMainWindow): logging.debug("Starting camera hotplug monitor...") QTimer.singleShot(0, self.cameraHotplugThread.start) - # Monitor when the user adds or removes a partition - self.udisks2Monitor = UDisks2Monitor(self.validMounts) - self.udisks2MonitorThread = QThread() - self.udisks2MonitorThread.started.connect(self.udisks2Monitor.startMonitor) - self.udisks2Unmount.connect(self.udisks2Monitor.unmount_volume) - self.udisks2Monitor.moveToThread(self.udisks2MonitorThread) - self.udisks2Monitor.partitionMounted.connect(self.partitionMounted) - self.udisks2Monitor.partitionUnmounted.connect(self.partitionUmounted) - # Start the monitor only on the thread it will be running on - logging.debug("Starting UDisks2 monitor...") - QTimer.singleShot(0, self.udisks2MonitorThread.start) - if self.gvfsControlsMounts: # Gio.VolumeMonitor must be in the main thread, according to # Gnome documentation -@@ -2119,7 +2107,7 @@ class RapidWindow(QMainWindow): +@@ -2189,7 +2177,7 @@ class RapidWindow(QMainWindow): select_text=_('Select a destination folder') ) self.photoDestination.addWidget(self.photoDestinationWidget) - + self.videoDestinationDisplay = DestinationDisplay( menu=True, file_type=FileType.video, parent=self ) -@@ -2582,11 +2570,11 @@ class RapidWindow(QMainWindow): +@@ -2655,11 +2643,11 @@ class RapidWindow(QMainWindow): body = _( r"""Please report the problem at {website}.

- Include in your bug report the program's log files. The bug report must include - {log_file}, but attaching the other log files is often helpful.

+ Include in your bug report the program's log files. The bug report must include + {log_file}, but attaching the other log files is often helpful.

If possible, please also include the program's configuration file - {config_file}.

- Click here to open the log directory, and + {config_file}.

+ Click here to open the log directory, and here to open the configuration directory. """ ).format( -@@ -2622,7 +2610,7 @@ class RapidWindow(QMainWindow): +@@ -2695,7 +2683,7 @@ class RapidWindow(QMainWindow): :param message: the text to display :param rich_text: whether it text to display is in HTML format - :param title: optional title for message box, else defaults to + :param title: optional title for message box, else defaults to localized 'Rapid Photo Downloader' :return: the message box """ -@@ -4652,8 +4640,6 @@ Do you want to proceed with the download? +@@ -4766,8 +4754,6 @@ Do you want to proceed with the download? self.sendTerminateToThread(self.backup_controller) if not self.gvfsControlsMounts: - self.udisks2MonitorThread.quit() - self.udisks2MonitorThread.wait() self.cameraHotplugThread.quit() self.cameraHotplugThread.wait() else: -@@ -5254,7 +5240,7 @@ Do you want to proceed with the download? +@@ -5384,7 +5370,7 @@ Do you want to proceed with the download? After a preference change, rescan already scanned devices :param ignore_cameras: if True, don't rescan cameras :param rescan_path: if True, include manually specified paths - (i.e. This Computer) + (i.e. This Computer) """ if rescan_path: -@@ -6243,7 +6229,7 @@ def main(): +@@ -6499,7 +6485,7 @@ def main(): logger = iplogging.setup_main_process_logging(logging_level=logging_level) logging.info("Rapid Photo Downloader is starting") - + if args.photo_renaming: photo_rename = args.photo_renaming == 'on' if photo_rename: -@@ -6252,7 +6238,7 @@ def main(): +@@ -6508,7 +6494,7 @@ def main(): logging.info("Photo renaming turned off from command line") else: photo_rename = None - + if args.video_renaming: video_rename = args.video_renaming == 'on' if video_rename: -@@ -6313,13 +6299,13 @@ def main(): +@@ -6569,13 +6555,13 @@ def main(): logging.info("This Computer path set from command line: %s", this_computer_location) else: this_computer_location=None - + if args.photo_location: photo_location = os.path.abspath(args.photo_location) logging.info("Photo location set from command line: %s", photo_location) else: photo_location=None - + if args.video_location: video_location = os.path.abspath(args.video_location) logging.info("video location set from command line: %s", video_location) Index: head/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py =================================================================== --- head/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py (revision 533751) +++ head/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py (revision 533752) @@ -1,319 +1,319 @@ ---- raphodo/storage.py.orig 2019-07-09 21:12:19 UTC +--- raphodo/storage.py.orig 2020-04-17 01:22:23 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) + run_media_dir = '/run/media' distro = get_distro() @@ -278,7 +277,7 @@ class ValidMounts(): self.validMountFolders, e.g. /media/, 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], +@@ -649,7 +648,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], +@@ -794,7 +793,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): +@@ -1041,259 +1040,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, +@@ -1692,7 +1438,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 """ Index: head/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py =================================================================== --- head/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py (revision 533751) +++ head/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py (revision 533752) @@ -1,62 +1,62 @@ ---- raphodo/utilities.py.orig 2019-08-18 03:58:11 UTC +--- raphodo/utilities.py.orig 2020-04-17 01:22:23 UTC +++ raphodo/utilities.py -@@ -76,10 +76,11 @@ if arrow_version >= parse_version('0.14.3') and arrow_ +@@ -82,10 +82,11 @@ if arrow_version >= parse_version('0.14.3') and arrow_ # Linux specific code to ensure child processes exit when parent dies # See http://stackoverflow.com/questions/19447603/ # how-to-kill-a-python-child-process-created-with-subprocess-check-output-when-t/ -libc = ctypes.CDLL("libc.so.6") +libc = ctypes.CDLL("libc.so.7") def set_pdeathsig(sig = signal.SIGTERM): def callable(): - return libc.prctl(1, sig) + return 0 + #return libc.procctl(0, 0, 11, sig) return callable -@@ -195,8 +196,8 @@ def show_errors(): +@@ -201,8 +202,8 @@ def show_errors(): # kilobytes, etc. suffixes = [_('B'), _('KB'), _('MB'), _('GB'), _('TB'), _('PB'), _('EB'), _('ZB'), _('YB')] -def format_size_for_user(size_in_bytes: int, - zero_string: str='', +def format_size_for_user(size_in_bytes: int, + zero_string: str='', no_decimals: int=2) -> str: r""" Humanize display of bytes. -@@ -382,12 +383,12 @@ def find_mount_point(path: str) -> str: +@@ -388,12 +389,12 @@ def find_mount_point(path: str) -> str: Find the mount point of a path See: http://stackoverflow.com/questions/4453602/how-to-find-the-mountpoint-a-file-resides-on - + >>> print(find_mount_point('/crazy/path')) / - - :param path: - :return: + + :param path: + :return: """ path = os.path.realpath(path) while not os.path.ismount(path): -@@ -724,13 +725,13 @@ def _collect_duplicates(basenames, paths): +@@ -743,13 +744,13 @@ def _collect_duplicates(basenames, paths): def make_path_end_snippets_unique(*paths) -> List[str]: r""" - Make list of path ends unique given possible common path endings. - - A snippet starts from the end of the path, in extreme cases possibly up the path start. + Make list of path ends unique given possible common path endings. + A snippet starts from the end of the path, in extreme cases possibly up the path start. + :param paths: sequence of paths to generate unique end snippets for :return: list of unique snippets - + >>> p0 = '/home/damon/photos' >>> p1 = '/media/damon/backup1/photos' >>> p2 = '/media/damon/backup2/photos' Index: head/graphics/rapid-photo-downloader/files/patch-setup.py =================================================================== --- head/graphics/rapid-photo-downloader/files/patch-setup.py (nonexistent) +++ head/graphics/rapid-photo-downloader/files/patch-setup.py (revision 533752) @@ -0,0 +1,10 @@ +--- setup.py.orig 2020-04-17 01:22:23 UTC ++++ setup.py +@@ -271,7 +271,6 @@ setup( + 'scandir;python_version<"3.5"', + 'typing;python_version<"3.5"', + 'PyGObject', +- 'PyQt5', + 'babel', + ], + extras_require={ Property changes on: head/graphics/rapid-photo-downloader/files/patch-setup.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property