mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-22 14:41:39 +00:00
Format files with black
- Format all files with black - Update tox.ini flake8 arguments to be compatible - Add black to requirements-extra.txt - Reduce ignored flake8 rules and fix a few violations
This commit is contained in:
113
hscommon/util.py
113
hscommon/util.py
@@ -17,6 +17,7 @@ from datetime import timedelta
|
||||
|
||||
from .path import Path, pathify, log_io_error
|
||||
|
||||
|
||||
def nonone(value, replace_value):
|
||||
"""Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise.
|
||||
"""
|
||||
@@ -25,6 +26,7 @@ def nonone(value, replace_value):
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def tryint(value, default=0):
|
||||
"""Tries to convert ``value`` to in ``int`` and returns ``default`` if it fails.
|
||||
"""
|
||||
@@ -33,12 +35,15 @@ def tryint(value, default=0):
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
def minmax(value, min_value, max_value):
|
||||
"""Returns `value` or one of the min/max bounds if `value` is not between them.
|
||||
"""
|
||||
return min(max(value, min_value), max_value)
|
||||
|
||||
#--- Sequence related
|
||||
|
||||
# --- Sequence related
|
||||
|
||||
|
||||
def dedupe(iterable):
|
||||
"""Returns a list of elements in ``iterable`` with all dupes removed.
|
||||
@@ -54,6 +59,7 @@ def dedupe(iterable):
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
|
||||
def flatten(iterables, start_with=None):
|
||||
"""Takes a list of lists ``iterables`` and returns a list containing elements of every list.
|
||||
|
||||
@@ -67,6 +73,7 @@ def flatten(iterables, start_with=None):
|
||||
result.extend(iterable)
|
||||
return result
|
||||
|
||||
|
||||
def first(iterable):
|
||||
"""Returns the first item of ``iterable``.
|
||||
"""
|
||||
@@ -75,11 +82,13 @@ def first(iterable):
|
||||
except StopIteration:
|
||||
return None
|
||||
|
||||
|
||||
def stripfalse(seq):
|
||||
"""Returns a sequence with all false elements stripped out of seq.
|
||||
"""
|
||||
return [x for x in seq if x]
|
||||
|
||||
|
||||
def extract(predicate, iterable):
|
||||
"""Separates the wheat from the shaft (`predicate` defines what's the wheat), and returns both.
|
||||
"""
|
||||
@@ -92,6 +101,7 @@ def extract(predicate, iterable):
|
||||
shaft.append(item)
|
||||
return wheat, shaft
|
||||
|
||||
|
||||
def allsame(iterable):
|
||||
"""Returns whether all elements of 'iterable' are the same.
|
||||
"""
|
||||
@@ -102,6 +112,7 @@ def allsame(iterable):
|
||||
raise ValueError("iterable cannot be empty")
|
||||
return all(element == first_item for element in it)
|
||||
|
||||
|
||||
def trailiter(iterable, skipfirst=False):
|
||||
"""Yields (prev_element, element), starting with (None, first_element).
|
||||
|
||||
@@ -120,6 +131,7 @@ def trailiter(iterable, skipfirst=False):
|
||||
yield prev, item
|
||||
prev = item
|
||||
|
||||
|
||||
def iterconsume(seq, reverse=True):
|
||||
"""Iterate over ``seq`` and pops yielded objects.
|
||||
|
||||
@@ -135,31 +147,36 @@ def iterconsume(seq, reverse=True):
|
||||
while seq:
|
||||
yield seq.pop()
|
||||
|
||||
#--- String related
|
||||
|
||||
def escape(s, to_escape, escape_with='\\'):
|
||||
# --- String related
|
||||
|
||||
|
||||
def escape(s, to_escape, escape_with="\\"):
|
||||
"""Returns ``s`` with characters in ``to_escape`` all prepended with ``escape_with``.
|
||||
"""
|
||||
return ''.join((escape_with + c if c in to_escape else c) for c in s)
|
||||
return "".join((escape_with + c if c in to_escape else c) for c in s)
|
||||
|
||||
|
||||
def get_file_ext(filename):
|
||||
"""Returns the lowercase extension part of filename, without the dot.
|
||||
"""
|
||||
pos = filename.rfind('.')
|
||||
pos = filename.rfind(".")
|
||||
if pos > -1:
|
||||
return filename[pos + 1:].lower()
|
||||
return filename[pos + 1 :].lower()
|
||||
else:
|
||||
return ''
|
||||
return ""
|
||||
|
||||
|
||||
def rem_file_ext(filename):
|
||||
"""Returns the filename without extension.
|
||||
"""
|
||||
pos = filename.rfind('.')
|
||||
pos = filename.rfind(".")
|
||||
if pos > -1:
|
||||
return filename[:pos]
|
||||
else:
|
||||
return filename
|
||||
|
||||
|
||||
def pluralize(number, word, decimals=0, plural_word=None):
|
||||
"""Returns a pluralized string with ``number`` in front of ``word``.
|
||||
|
||||
@@ -173,11 +190,12 @@ def pluralize(number, word, decimals=0, plural_word=None):
|
||||
format = "%%1.%df %%s" % decimals
|
||||
if number > 1:
|
||||
if plural_word is None:
|
||||
word += 's'
|
||||
word += "s"
|
||||
else:
|
||||
word = plural_word
|
||||
return format % (number, word)
|
||||
|
||||
|
||||
def format_time(seconds, with_hours=True):
|
||||
"""Transforms seconds in a hh:mm:ss string.
|
||||
|
||||
@@ -189,14 +207,15 @@ def format_time(seconds, with_hours=True):
|
||||
m, s = divmod(seconds, 60)
|
||||
if with_hours:
|
||||
h, m = divmod(m, 60)
|
||||
r = '%02d:%02d:%02d' % (h, m, s)
|
||||
r = "%02d:%02d:%02d" % (h, m, s)
|
||||
else:
|
||||
r = '%02d:%02d' % (m,s)
|
||||
r = "%02d:%02d" % (m, s)
|
||||
if minus:
|
||||
return '-' + r
|
||||
return "-" + r
|
||||
else:
|
||||
return r
|
||||
|
||||
|
||||
def format_time_decimal(seconds):
|
||||
"""Transforms seconds in a strings like '3.4 minutes'.
|
||||
"""
|
||||
@@ -204,20 +223,23 @@ def format_time_decimal(seconds):
|
||||
if minus:
|
||||
seconds *= -1
|
||||
if seconds < 60:
|
||||
r = pluralize(seconds, 'second', 1)
|
||||
r = pluralize(seconds, "second", 1)
|
||||
elif seconds < 3600:
|
||||
r = pluralize(seconds / 60.0, 'minute', 1)
|
||||
r = pluralize(seconds / 60.0, "minute", 1)
|
||||
elif seconds < 86400:
|
||||
r = pluralize(seconds / 3600.0, 'hour', 1)
|
||||
r = pluralize(seconds / 3600.0, "hour", 1)
|
||||
else:
|
||||
r = pluralize(seconds / 86400.0, 'day', 1)
|
||||
r = pluralize(seconds / 86400.0, "day", 1)
|
||||
if minus:
|
||||
return '-' + r
|
||||
return "-" + r
|
||||
else:
|
||||
return r
|
||||
|
||||
SIZE_DESC = ('B','KB','MB','GB','TB','PB','EB','ZB','YB')
|
||||
SIZE_VALS = tuple(1024 ** i for i in range(1,9))
|
||||
|
||||
SIZE_DESC = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
|
||||
SIZE_VALS = tuple(1024 ** i for i in range(1, 9))
|
||||
|
||||
|
||||
def format_size(size, decimal=0, forcepower=-1, showdesc=True):
|
||||
"""Transform a byte count in a formatted string (KB, MB etc..).
|
||||
|
||||
@@ -238,12 +260,12 @@ def format_size(size, decimal=0, forcepower=-1, showdesc=True):
|
||||
else:
|
||||
i = forcepower
|
||||
if i > 0:
|
||||
div = SIZE_VALS[i-1]
|
||||
div = SIZE_VALS[i - 1]
|
||||
else:
|
||||
div = 1
|
||||
format = '%%%d.%df' % (decimal,decimal)
|
||||
format = "%%%d.%df" % (decimal, decimal)
|
||||
negative = size < 0
|
||||
divided_size = ((0.0 + abs(size)) / div)
|
||||
divided_size = (0.0 + abs(size)) / div
|
||||
if decimal == 0:
|
||||
divided_size = ceil(divided_size)
|
||||
else:
|
||||
@@ -252,18 +274,21 @@ def format_size(size, decimal=0, forcepower=-1, showdesc=True):
|
||||
divided_size *= -1
|
||||
result = format % divided_size
|
||||
if showdesc:
|
||||
result += ' ' + SIZE_DESC[i]
|
||||
result += " " + SIZE_DESC[i]
|
||||
return result
|
||||
|
||||
_valid_xml_range = '\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD'
|
||||
if sys.maxunicode > 0x10000:
|
||||
_valid_xml_range += '%s-%s' % (chr(0x10000), chr(min(sys.maxunicode, 0x10FFFF)))
|
||||
RE_INVALID_XML_SUB = re.compile('[^%s]' % _valid_xml_range, re.U).sub
|
||||
|
||||
def remove_invalid_xml(s, replace_with=' '):
|
||||
_valid_xml_range = "\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD"
|
||||
if sys.maxunicode > 0x10000:
|
||||
_valid_xml_range += "%s-%s" % (chr(0x10000), chr(min(sys.maxunicode, 0x10FFFF)))
|
||||
RE_INVALID_XML_SUB = re.compile("[^%s]" % _valid_xml_range, re.U).sub
|
||||
|
||||
|
||||
def remove_invalid_xml(s, replace_with=" "):
|
||||
return RE_INVALID_XML_SUB(replace_with, s)
|
||||
|
||||
def multi_replace(s, replace_from, replace_to=''):
|
||||
|
||||
def multi_replace(s, replace_from, replace_to=""):
|
||||
"""A function like str.replace() with multiple replacements.
|
||||
|
||||
``replace_from`` is a list of things you want to replace. Ex: ['a','bc','d']
|
||||
@@ -280,17 +305,20 @@ def multi_replace(s, replace_from, replace_to=''):
|
||||
if isinstance(replace_to, str) and (len(replace_from) != len(replace_to)):
|
||||
replace_to = [replace_to for r in replace_from]
|
||||
if len(replace_from) != len(replace_to):
|
||||
raise ValueError('len(replace_from) must be equal to len(replace_to)')
|
||||
raise ValueError("len(replace_from) must be equal to len(replace_to)")
|
||||
replace = list(zip(replace_from, replace_to))
|
||||
for r_from, r_to in [r for r in replace if r[0] in s]:
|
||||
s = s.replace(r_from, r_to)
|
||||
return s
|
||||
|
||||
#--- Date related
|
||||
|
||||
# --- Date related
|
||||
|
||||
# It might seem like needless namespace pollution, but the speedup gained by this constant is
|
||||
# significant, so it stays.
|
||||
ONE_DAY = timedelta(1)
|
||||
|
||||
|
||||
def iterdaterange(start, end):
|
||||
"""Yields every day between ``start`` and ``end``.
|
||||
"""
|
||||
@@ -299,7 +327,9 @@ def iterdaterange(start, end):
|
||||
yield date
|
||||
date += ONE_DAY
|
||||
|
||||
#--- Files related
|
||||
|
||||
# --- Files related
|
||||
|
||||
|
||||
@pathify
|
||||
def modified_after(first_path: Path, second_path: Path):
|
||||
@@ -317,19 +347,21 @@ def modified_after(first_path: Path, second_path: Path):
|
||||
return True
|
||||
return first_mtime > second_mtime
|
||||
|
||||
|
||||
def find_in_path(name, paths=None):
|
||||
"""Search for `name` in all directories of `paths` and return the absolute path of the first
|
||||
occurrence. If `paths` is None, $PATH is used.
|
||||
"""
|
||||
if paths is None:
|
||||
paths = os.environ['PATH']
|
||||
if isinstance(paths, str): # if it's not a string, it's already a list
|
||||
paths = os.environ["PATH"]
|
||||
if isinstance(paths, str): # if it's not a string, it's already a list
|
||||
paths = paths.split(os.pathsep)
|
||||
for path in paths:
|
||||
if op.exists(op.join(path, name)):
|
||||
return op.join(path, name)
|
||||
return None
|
||||
|
||||
|
||||
@log_io_error
|
||||
@pathify
|
||||
def delete_if_empty(path: Path, files_to_delete=[]):
|
||||
@@ -345,7 +377,8 @@ def delete_if_empty(path: Path, files_to_delete=[]):
|
||||
path.rmdir()
|
||||
return True
|
||||
|
||||
def open_if_filename(infile, mode='rb'):
|
||||
|
||||
def open_if_filename(infile, mode="rb"):
|
||||
"""If ``infile`` is a string, it opens and returns it. If it's already a file object, it simply returns it.
|
||||
|
||||
This function returns ``(file, should_close_flag)``. The should_close_flag is True is a file has
|
||||
@@ -364,15 +397,18 @@ def open_if_filename(infile, mode='rb'):
|
||||
else:
|
||||
return (infile, False)
|
||||
|
||||
|
||||
def ensure_folder(path):
|
||||
"Create `path` as a folder if it doesn't exist."
|
||||
if not op.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def ensure_file(path):
|
||||
"Create `path` as an empty file if it doesn't exist."
|
||||
if not op.exists(path):
|
||||
open(path, 'w').close()
|
||||
open(path, "w").close()
|
||||
|
||||
|
||||
def delete_files_with_pattern(folder_path, pattern, recursive=True):
|
||||
"""Delete all files (or folders) in `folder_path` that match the glob `pattern`.
|
||||
@@ -389,6 +425,7 @@ def delete_files_with_pattern(folder_path, pattern, recursive=True):
|
||||
for p in subfolders:
|
||||
delete_files_with_pattern(p, pattern, True)
|
||||
|
||||
|
||||
class FileOrPath:
|
||||
"""Does the same as :func:`open_if_filename`, but it can be used with a ``with`` statement.
|
||||
|
||||
@@ -397,7 +434,8 @@ class FileOrPath:
|
||||
with FileOrPath(infile):
|
||||
dostuff()
|
||||
"""
|
||||
def __init__(self, file_or_path, mode='rb'):
|
||||
|
||||
def __init__(self, file_or_path, mode="rb"):
|
||||
self.file_or_path = file_or_path
|
||||
self.mode = mode
|
||||
self.mustclose = False
|
||||
@@ -410,4 +448,3 @@ class FileOrPath:
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if self.fp and self.mustclose:
|
||||
self.fp.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user