1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-22 14:41:39 +00:00

Integrated the jobprogress library into hscommon

I have a fix to make in it and it's really silly to pretend that this
lib is of any use to anybody outside HS apps. Bringing it back here will
make things more simple.
This commit is contained in:
Virgil Dupras
2014-10-05 16:31:16 -04:00
parent 87c2fa2573
commit ac32305532
21 changed files with 775 additions and 487 deletions

View File

@@ -1,15 +1,15 @@
# Created By: Virgil Dupras
# Created On: 2006/02/27
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "BSD" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
#
# This software is licensed under the "BSD" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from xml.etree import ElementTree as ET
import logging
from jobprogress import job
from hscommon.jobprogress import job
from hscommon.path import Path
from hscommon.util import FileOrPath
@@ -24,7 +24,7 @@ __all__ = [
class DirectoryState:
"""Enum describing how a folder should be considered.
* DirectoryState.Normal: Scan all files normally
* DirectoryState.Reference: Scan files, but make sure never to delete any of them
* DirectoryState.Excluded: Don't scan this folder
@@ -41,10 +41,10 @@ class InvalidPathError(Exception):
class Directories:
"""Holds user folder selection.
Manages the selection that the user make through the folder selection dialog. It also manages
folder states, and how recursion applies to them.
Then, when the user starts the scan, :meth:`get_files` is called to retrieve all files (wrapped
in :mod:`core.fs`) that have to be scanned according to the chosen folders/states.
"""
@@ -55,28 +55,28 @@ class Directories:
self.states = {}
self.fileclasses = fileclasses
self.folderclass = fs.Folder
def __contains__(self, path):
for p in self._dirs:
if path in p:
return True
return False
def __delitem__(self,key):
self._dirs.__delitem__(key)
def __getitem__(self,key):
return self._dirs.__getitem__(key)
def __len__(self):
return len(self._dirs)
#---Private
def _default_state_for_path(self, path):
# Override this in subclasses to specify the state of some special folders.
if path.name.startswith('.'): # hidden
return DirectoryState.Excluded
def _get_files(self, from_path, j):
j.check_if_cancelled()
state = self.get_state(from_path)
@@ -102,7 +102,7 @@ class Directories:
yield file
except (EnvironmentError, fs.InvalidPath):
pass
def _get_folders(self, from_folder, j):
j.check_if_cancelled()
try:
@@ -116,16 +116,16 @@ class Directories:
yield from_folder
except (EnvironmentError, fs.InvalidPath):
pass
#---Public
def add_path(self, path):
"""Adds ``path`` to self, if not already there.
Raises :exc:`AlreadyThereError` if ``path`` is already in self. If path is a directory
containing some of the directories already present in self, ``path`` will be added, but all
directories under it will be removed. Can also raise :exc:`InvalidPathError` if ``path``
does not exist.
:param Path path: path to add
"""
if path in self:
@@ -134,11 +134,11 @@ class Directories:
raise InvalidPathError()
self._dirs = [p for p in self._dirs if p not in path]
self._dirs.append(path)
@staticmethod
def get_subfolders(path):
"""Returns a sorted list of paths corresponding to subfolders in ``path``.
:param Path path: get subfolders from there
:rtype: list of Path
"""
@@ -148,29 +148,29 @@ class Directories:
return subpaths
except EnvironmentError:
return []
def get_files(self, j=job.nulljob):
"""Returns a list of all files that are not excluded.
Returned files also have their ``is_ref`` attr set if applicable.
"""
for path in self._dirs:
for file in self._get_files(path, j):
yield file
def get_folders(self, j=job.nulljob):
"""Returns a list of all folders that are not excluded.
Returned folders also have their ``is_ref`` attr set if applicable.
"""
for path in self._dirs:
from_folder = self.folderclass(path)
for folder in self._get_folders(from_folder, j):
yield folder
def get_state(self, path):
"""Returns the state of ``path``.
:rtype: :class:`DirectoryState`
"""
if path in self.states:
@@ -183,12 +183,12 @@ class Directories:
return self.get_state(parent)
else:
return DirectoryState.Normal
def has_any_file(self):
"""Returns whether selected folders contain any file.
Because it stops at the first file it finds, it's much faster than get_files().
:rtype: bool
"""
try:
@@ -196,10 +196,10 @@ class Directories:
return True
except StopIteration:
return False
def load_from_file(self, infile):
"""Load folder selection from ``infile``.
:param file infile: path or file pointer to XML generated through :meth:`save_to_file`
"""
try:
@@ -222,10 +222,10 @@ class Directories:
path = attrib['path']
state = attrib['value']
self.states[Path(path)] = int(state)
def save_to_file(self, outfile):
"""Save folder selection as XML to ``outfile``.
:param file outfile: path or file pointer to XML file to save to.
"""
with FileOrPath(outfile, 'wb') as fp:
@@ -239,10 +239,10 @@ class Directories:
state_node.set('value', str(state))
tree = ET.ElementTree(root)
tree.write(fp, encoding='utf-8')
def set_state(self, path, state):
"""Set the state of folder at ``path``.
:param Path path: path of the target folder
:param state: state to set folder to
:type state: :class:`DirectoryState`
@@ -253,4 +253,4 @@ class Directories:
if path.is_parent_of(iter_path):
del self.states[iter_path]
self.states[path] = state