1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-22 06:37:17 +00:00

Format all files with black correcting line length

This commit is contained in:
2021-08-15 04:10:18 -05:00
parent 9446f37fad
commit ffe6b7047c
80 changed files with 517 additions and 970 deletions

View File

@@ -11,9 +11,7 @@ from setuptools import setup, Extension
def get_parser():
parser = argparse.ArgumentParser(description="Build an arbitrary Python extension.")
parser.add_argument(
"source_files", nargs="+", help="List of source files to compile"
)
parser.add_argument("source_files", nargs="+", help="List of source files to compile")
parser.add_argument("name", nargs=1, help="Name of the resulting extension")
return parser
@@ -23,7 +21,8 @@ def main():
print("Building {}...".format(args.name[0]))
ext = Extension(args.name[0], args.source_files)
setup(
script_args=["build_ext", "--inplace"], ext_modules=[ext],
script_args=["build_ext", "--inplace"],
ext_modules=[ext],
)

View File

@@ -48,15 +48,13 @@ def get_unconflicted_name(name):
def is_conflicted(name):
"""Returns whether ``name`` is prepended with a bracketed number.
"""
"""Returns whether ``name`` is prepended with a bracketed number."""
return re_conflict.match(name) is not None
@pathify
def _smart_move_or_copy(operation, source_path: Path, dest_path: Path):
"""Use move() or copy() to move and copy file with the conflict management.
"""
"""Use move() or copy() to move and copy file with the conflict management."""
if dest_path.isdir() and not source_path.isdir():
dest_path = dest_path[source_path.name]
if dest_path.exists():
@@ -68,14 +66,12 @@ def _smart_move_or_copy(operation, source_path: Path, dest_path: Path):
def smart_move(source_path, dest_path):
"""Same as :func:`smart_copy`, but it moves files instead.
"""
"""Same as :func:`smart_copy`, but it moves files instead."""
_smart_move_or_copy(shutil.move, source_path, dest_path)
def smart_copy(source_path, dest_path):
"""Copies ``source_path`` to ``dest_path``, recursively and with conflict resolution.
"""
"""Copies ``source_path`` to ``dest_path``, recursively and with conflict resolution."""
try:
_smart_move_or_copy(shutil.copy, source_path, dest_path)
except IOError as e:

View File

@@ -16,20 +16,17 @@ class SpecialFolder:
def open_url(url):
"""Open ``url`` with the default browser.
"""
"""Open ``url`` with the default browser."""
_open_url(url)
def open_path(path):
"""Open ``path`` with its associated application.
"""
"""Open ``path`` with its associated application."""
_open_path(str(path))
def reveal_path(path):
"""Open the folder containing ``path`` with the default file browser.
"""
"""Open the folder containing ``path`` with the default file browser."""
_reveal_path(str(path))

View File

@@ -149,8 +149,7 @@ class Rect:
return l1, l2, l3, l4
def scaled_rect(self, dx, dy):
"""Returns a rect that has the same borders at self, but grown/shrunk by dx/dy on each side.
"""
"""Returns a rect that has the same borders at self, but grown/shrunk by dx/dy on each side."""
x, y, w, h = self
x -= dx
y -= dy
@@ -159,8 +158,7 @@ class Rect:
return Rect(x, y, w, h)
def united(self, other):
"""Returns the bounding rectangle of this rectangle and `other`.
"""
"""Returns the bounding rectangle of this rectangle and `other`."""
# ul=upper left lr=lower right
ulcorner1, lrcorner1 = self.corners()
ulcorner2, lrcorner2 = other.corners()

View File

@@ -80,8 +80,7 @@ class PrefAccessInterface:
"""
def set_default(self, key, value):
"""Set the value ``value`` for ``key`` in the currently running app's preference store.
"""
"""Set the value ``value`` for ``key`` in the currently running app's preference store."""
class Columns(GUIObject):
@@ -140,33 +139,27 @@ class Columns(GUIObject):
# --- Public
def column_by_index(self, index):
"""Return the :class:`Column` having the :attr:`~Column.logical_index` ``index``.
"""
"""Return the :class:`Column` having the :attr:`~Column.logical_index` ``index``."""
return self.column_list[index]
def column_by_name(self, name):
"""Return the :class:`Column` having the :attr:`~Column.name` ``name``.
"""
"""Return the :class:`Column` having the :attr:`~Column.name` ``name``."""
return self.coldata[name]
def columns_count(self):
"""Returns the number of columns in our set.
"""
"""Returns the number of columns in our set."""
return len(self.column_list)
def column_display(self, colname):
"""Returns display name for column named ``colname``, or ``''`` if there's none.
"""
"""Returns display name for column named ``colname``, or ``''`` if there's none."""
return self._get_colname_attr(colname, "display", "")
def column_is_visible(self, colname):
"""Returns visibility for column named ``colname``, or ``True`` if there's none.
"""
"""Returns visibility for column named ``colname``, or ``True`` if there's none."""
return self._get_colname_attr(colname, "visible", True)
def column_width(self, colname):
"""Returns width for column named ``colname``, or ``0`` if there's none.
"""
"""Returns width for column named ``colname``, or ``0`` if there's none."""
return self._get_colname_attr(colname, "width", 0)
def columns_to_right(self, colname):
@@ -177,11 +170,7 @@ class Columns(GUIObject):
"""
column = self.coldata[colname]
index = column.ordered_index
return [
col.name
for col in self.column_list
if (col.visible and col.ordered_index > index)
]
return [col.name for col in self.column_list if (col.visible and col.ordered_index > index)]
def menu_items(self):
"""Returns a list of items convenient for quick visibility menu generation.
@@ -207,8 +196,7 @@ class Columns(GUIObject):
self.set_column_order(colnames)
def reset_to_defaults(self):
"""Reset all columns' width and visibility to their default values.
"""
"""Reset all columns' width and visibility to their default values."""
self.set_column_order([col.name for col in self.column_list])
for col in self._optional_columns():
col.visible = col.default_visible
@@ -216,13 +204,11 @@ class Columns(GUIObject):
self.view.restore_columns()
def resize_column(self, colname, newwidth):
"""Set column ``colname``'s width to ``newwidth``.
"""
"""Set column ``colname``'s width to ``newwidth``."""
self._set_colname_attr(colname, "width", newwidth)
def restore_columns(self):
"""Restore's column persistent attributes from the last :meth:`save_columns`.
"""
"""Restore's column persistent attributes from the last :meth:`save_columns`."""
if not (self.prefaccess and self.savename and self.coldata):
if (not self.savename) and (self.coldata):
# This is a table that will not have its coldata saved/restored. we should
@@ -241,8 +227,7 @@ class Columns(GUIObject):
self.view.restore_columns()
def save_columns(self):
"""Save column attributes in persistent storage for restoration in :meth:`restore_columns`.
"""
"""Save column attributes in persistent storage for restoration in :meth:`restore_columns`."""
if not (self.prefaccess and self.savename and self.coldata):
return
for col in self.column_list:
@@ -263,15 +248,13 @@ class Columns(GUIObject):
col.ordered_index = i
def set_column_visible(self, colname, visible):
"""Set the visibility of column ``colname``.
"""
"""Set the visibility of column ``colname``."""
self.table.save_edits() # the table on the GUI side will stop editing when the columns change
self._set_colname_attr(colname, "visible", visible)
self.view.set_column_visible(colname, visible)
def set_default_width(self, colname, width):
"""Set the default width or column ``colname``.
"""
"""Set the default width or column ``colname``."""
self._set_colname_attr(colname, "default_width", width)
def toggle_menu_item(self, index):
@@ -289,14 +272,10 @@ class Columns(GUIObject):
# --- Properties
@property
def ordered_columns(self):
"""List of :class:`Column` in visible order.
"""
return [
col for col in sorted(self.column_list, key=lambda col: col.ordered_index)
]
"""List of :class:`Column` in visible order."""
return [col for col in sorted(self.column_list, key=lambda col: col.ordered_index)]
@property
def colnames(self):
"""List of column names in visible order.
"""
"""List of column names in visible order."""
return [col.name for col in self.ordered_columns]

View File

@@ -21,12 +21,10 @@ class ProgressWindowView:
"""
def show(self):
"""Show the dialog.
"""
"""Show the dialog."""
def close(self):
"""Close the dialog.
"""
"""Close the dialog."""
def set_progress(self, progress):
"""Set the progress of the progress bar to ``progress``.
@@ -76,8 +74,7 @@ class ProgressWindow(GUIObject, ThreadedJobPerformer):
self.jobid = None
def cancel(self):
"""Call for a user-initiated job cancellation.
"""
"""Call for a user-initiated job cancellation."""
# The UI is sometimes a bit buggy and calls cancel() on self.view.close(). We just want to
# make sure that this doesn't lead us to think that the user acually cancelled the task, so
# we verify that the job is still running.

View File

@@ -27,9 +27,7 @@ class Selectable(Sequence):
self._selected_indexes = []
if not self._selected_indexes:
return
self._selected_indexes = [
index for index in self._selected_indexes if index < len(self)
]
self._selected_indexes = [index for index in self._selected_indexes if index < len(self)]
if not self._selected_indexes:
self._selected_indexes = [len(self) - 1]

View File

@@ -71,8 +71,7 @@ class TextField(GUIObject):
# --- Public
def refresh(self):
"""Triggers a view :meth:`~TextFieldView.refresh`.
"""
"""Triggers a view :meth:`~TextFieldView.refresh`."""
self.view.refresh()
@property

View File

@@ -55,8 +55,7 @@ class Node(MutableSequence):
# --- Public
def clear(self):
"""Clears the node of all its children.
"""
"""Clears the node of all its children."""
del self[:]
def find(self, predicate, include_self=True):
@@ -103,14 +102,12 @@ class Node(MutableSequence):
@property
def children_count(self):
"""Same as ``len(self)``.
"""
"""Same as ``len(self)``."""
return len(self)
@property
def name(self):
"""Name for the node, supplied on init.
"""
"""Name for the node, supplied on init."""
return self._name
@property

View File

@@ -56,8 +56,7 @@ class Job:
# ---Private
def _subjob_callback(self, progress, desc=""):
"""This is the callback passed to children jobs.
"""
"""This is the callback passed to children jobs."""
self.set_progress(progress, desc)
return True # if JobCancelled has to be raised, it will be at the highest level

View File

@@ -154,9 +154,7 @@ def strings2pot(target, dest):
def allstrings2pot(lprojpath, dest, excludes=None):
allstrings = files_with_ext(lprojpath, ".strings")
if excludes:
allstrings = [
p for p in allstrings if op.splitext(op.basename(p))[0] not in excludes
]
allstrings = [p for p in allstrings if op.splitext(op.basename(p))[0] not in excludes]
for strings_path in allstrings:
strings2pot(strings_path, dest)
@@ -195,11 +193,7 @@ def generate_cocoa_strings_from_code(code_folder, dest_folder):
# genstrings produces utf-16 files with comments. After having generated the files, we convert
# them to utf-8 and remove the comments.
ensure_empty_folder(dest_folder)
print_and_do(
'genstrings -o "{}" `find "{}" -name *.m | xargs`'.format(
dest_folder, code_folder
)
)
print_and_do('genstrings -o "{}" `find "{}" -name *.m | xargs`'.format(dest_folder, code_folder))
for stringsfile in os.listdir(dest_folder):
stringspath = op.join(dest_folder, stringsfile)
with open(stringspath, "rt", encoding="utf-16") as fp:
@@ -214,9 +208,7 @@ def generate_cocoa_strings_from_code(code_folder, dest_folder):
def generate_cocoa_strings_from_xib(xib_folder):
xibs = [
op.join(xib_folder, fn) for fn in os.listdir(xib_folder) if fn.endswith(".xib")
]
xibs = [op.join(xib_folder, fn) for fn in os.listdir(xib_folder) if fn.endswith(".xib")]
for xib in xibs:
dest = xib.replace(".xib", ".strings")
print_and_do("ibtool {} --generate-strings-file {}".format(xib, dest))
@@ -234,10 +226,6 @@ def localize_stringsfile(stringsfile, dest_root_folder):
def localize_all_stringsfiles(src_folder, dest_root_folder):
stringsfiles = [
op.join(src_folder, fn)
for fn in os.listdir(src_folder)
if fn.endswith(".strings")
]
stringsfiles = [op.join(src_folder, fn) for fn in os.listdir(src_folder) if fn.endswith(".strings")]
for path in stringsfiles:
localize_stringsfile(path, dest_root_folder)

View File

@@ -16,8 +16,7 @@ from collections import defaultdict
class Broadcaster:
"""Broadcasts messages that are received by all listeners.
"""
"""Broadcasts messages that are received by all listeners."""
def __init__(self):
self.listeners = set()
@@ -39,8 +38,7 @@ class Broadcaster:
class Listener:
"""A listener is initialized with the broadcaster it's going to listen to. Initially, it is not connected.
"""
"""A listener is initialized with the broadcaster it's going to listen to. Initially, it is not connected."""
def __init__(self, broadcaster):
self.broadcaster = broadcaster
@@ -57,13 +55,11 @@ class Listener:
self._bound_notifications[message].append(func)
def connect(self):
"""Connects the listener to its broadcaster.
"""
"""Connects the listener to its broadcaster."""
self.broadcaster.add_listener(self)
def disconnect(self):
"""Disconnects the listener from its broadcaster.
"""
"""Disconnects the listener from its broadcaster."""
self.broadcaster.remove_listener(self)
def dispatch(self, msg):

View File

@@ -85,9 +85,7 @@ class Path(tuple):
def __getitem__(self, key):
if isinstance(key, slice):
if isinstance(key.start, Path):
equal_elems = list(
takewhile(lambda pair: pair[0] == pair[1], zip(self, key.start))
)
equal_elems = list(takewhile(lambda pair: pair[0] == pair[1], zip(self, key.start)))
key = slice(len(equal_elems), key.stop, key.step)
if isinstance(key.stop, Path):
equal_elems = list(
@@ -226,9 +224,7 @@ def pathify(f):
Calling ``foo('/bar', 0)`` will convert ``'/bar'`` to ``Path('/bar')``.
"""
sig = signature(f)
pindexes = {
i for i, p in enumerate(sig.parameters.values()) if p.annotation is Path
}
pindexes = {i for i, p in enumerate(sig.parameters.values()) if p.annotation is Path}
pkeys = {k: v for k, v in sig.parameters.items() if v.annotation is Path}
def path_or_none(p):
@@ -236,9 +232,7 @@ def pathify(f):
@wraps(f)
def wrapped(*args, **kwargs):
args = tuple(
(path_or_none(a) if i in pindexes else a) for i, a in enumerate(args)
)
args = tuple((path_or_none(a) if i in pindexes else a) for i, a in enumerate(args))
kwargs = {k: (path_or_none(v) if k in pkeys else v) for k, v in kwargs.items()}
return f(*args, **kwargs)
@@ -246,8 +240,7 @@ def pathify(f):
def log_io_error(func):
""" Catches OSError, IOError and WindowsError and log them
"""
"""Catches OSError, IOError and WindowsError and log them"""
@wraps(func)
def wrapper(path, *args, **kwargs):

View File

@@ -110,22 +110,14 @@ def _visit_pyfiles(list, dirname, names):
# get extension for python source files
if "_py_ext" not in globals():
global _py_ext
_py_ext = [
triple[0] for triple in imp.get_suffixes() if triple[2] == imp.PY_SOURCE
][0]
_py_ext = [triple[0] for triple in imp.get_suffixes() if triple[2] == imp.PY_SOURCE][0]
# don't recurse into CVS directories
if "CVS" in names:
names.remove("CVS")
# add all *.py files to list
list.extend(
[
os.path.join(dirname, file)
for file in names
if os.path.splitext(file)[1] == _py_ext
]
)
list.extend([os.path.join(dirname, file) for file in names if os.path.splitext(file)[1] == _py_ext])
def _get_modpkg_path(dotted_name, pathlist=None):
@@ -406,8 +398,7 @@ def main(source_files, outpath, keywords=None):
eater(*_token)
except tokenize.TokenError as e:
print(
"%s: %s, line %d, column %d"
% (e.args[0], filename, e.args[1][0], e.args[1][1]),
"%s: %s, line %d, column %d" % (e.args[0], filename, e.args[1][0], e.args[1][1]),
file=sys.stderr,
)
finally:

View File

@@ -22,9 +22,7 @@ def tixgen(tixurl):
"""This is a filter *generator*. tixurl is a url pattern for the tix with a {0} placeholder
for the tix #
"""
urlpattern = tixurl.format(
"\\1"
) # will be replaced buy the content of the first group in re
urlpattern = tixurl.format("\\1") # will be replaced buy the content of the first group in re
R = re.compile(r"#(\d+)")
repl = "`#\\1 <{}>`__".format(urlpattern)
return lambda text: R.sub(repl, text)
@@ -61,9 +59,7 @@ def gen(
# The format of the changelog descriptions is in markdown, but since we only use bulled list
# and links, it's not worth depending on the markdown package. A simple regexp suffice.
description = re.sub(r"\[(.*?)\]\((.*?)\)", "`\\1 <\\2>`__", description)
rendered = CHANGELOG_FORMAT.format(
version=log["version"], date=log["date_str"], description=description
)
rendered = CHANGELOG_FORMAT.format(version=log["version"], date=log["date_str"], description=description)
rendered_logs.append(rendered)
confrepl["version"] = changelog[0]["version"]
changelog_out = op.join(basepath, "changelog.rst")
@@ -75,6 +71,4 @@ def gen(
try:
sphinx_build([basepath, destpath])
except SystemExit:
print(
"Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit"
)
print("Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit")

View File

@@ -31,8 +31,8 @@ class FakeCursor(list):
class _ActualThread(threading.Thread):
""" We can't use this class directly because thread object are not automatically freed when
nothing refers to it, making it hang the application if not explicitely closed.
"""We can't use this class directly because thread object are not automatically freed when
nothing refers to it, making it hang the application if not explicitely closed.
"""
def __init__(self, dbname, autocommit):

View File

@@ -80,9 +80,7 @@ class TestCase_move_copy:
assert self.path["baz"].exists()
assert not self.path["foo"].exists()
def test_copy_no_conflict(
self, do_setup
): # No need to duplicate the rest of the tests... Let's just test on move
def test_copy_no_conflict(self, do_setup): # No need to duplicate the rest of the tests... Let's just test on move
smart_copy(self.path + "foo", self.path + "baz")
assert self.path["baz"].exists()
assert self.path["foo"].exists()

View File

@@ -128,9 +128,7 @@ def test_repeater_with_repeated_notifications():
r.connect()
listener.connect()
b.notify("hello")
b.notify(
"foo"
) # if the repeater repeated this notif, we'd get a crash on HelloListener
b.notify("foo") # if the repeater repeated this notif, we'd get a crash on HelloListener
eq_(r.hello_count, 1)
eq_(listener.hello_count, 1)
eq_(r.foo_count, 1)

View File

@@ -87,8 +87,7 @@ def test_filename(force_ossep):
def test_deal_with_empty_components(force_ossep):
"""Keep ONLY a leading space, which means we want a leading slash.
"""
"""Keep ONLY a leading space, which means we want a leading slash."""
eq_("foo//bar", str(Path(("foo", "", "bar"))))
eq_("/foo/bar", str(Path(("", "foo", "bar"))))
eq_("foo/bar", str(Path("foo/bar/")))
@@ -154,8 +153,7 @@ def test_path_slice(force_ossep):
def test_add_with_root_path(force_ossep):
"""if I perform /a/b/c + /d/e/f, I want /a/b/c/d/e/f, not /a/b/c//d/e/f
"""
"""if I perform /a/b/c + /d/e/f, I want /a/b/c/d/e/f, not /a/b/c//d/e/f"""
eq_("/foo/bar", str(Path("/foo") + Path("/bar")))
@@ -166,8 +164,7 @@ def test_create_with_tuple_that_have_slash_inside(force_ossep, monkeypatch):
def test_auto_decode_os_sep(force_ossep, monkeypatch):
"""Path should decode any either / or os.sep, but always encode in os.sep.
"""
"""Path should decode any either / or os.sep, but always encode in os.sep."""
eq_(("foo\\bar", "bleh"), Path("foo\\bar/bleh"))
monkeypatch.setattr(os, "sep", "\\")
eq_(("foo", "bar/bleh"), Path("foo\\bar/bleh"))

View File

@@ -44,9 +44,7 @@ def test_guicalls():
# A GUISelectableList appropriately calls its view.
sl = GUISelectableList(["foo", "bar"])
sl.view = CallLogger()
sl.view.check_gui_calls(
["refresh"]
) # Upon setting the view, we get a call to refresh()
sl.view.check_gui_calls(["refresh"]) # Upon setting the view, we get a call to refresh()
sl[1] = "baz"
sl.view.check_gui_calls(["refresh"])
sl.append("foo")

View File

@@ -105,9 +105,7 @@ def test_findall_dont_include_self():
# When calling findall with include_self=False, the node itself is never evaluated.
t = tree_with_some_nodes()
del t._name # so that if the predicate is called on `t`, we crash
r = t.findall(
lambda n: not n.name.startswith("sub"), include_self=False
) # no crash
r = t.findall(lambda n: not n.name.startswith("sub"), include_self=False) # no crash
eq_(set(r), set([t[0], t[1], t[2]]))

View File

@@ -105,9 +105,7 @@ def test_iterconsume():
# We just want to make sure that we return *all* items and that we're not mistakenly skipping
# one.
eq_(list(range(2500)), list(iterconsume(list(range(2500)))))
eq_(
list(reversed(range(2500))), list(iterconsume(list(range(2500)), reverse=False))
)
eq_(list(reversed(range(2500))), list(iterconsume(list(range(2500)), reverse=False)))
# --- String

View File

@@ -86,9 +86,7 @@ class CallLogger:
eq_(set(self.calls), set(expected))
self.clear_calls()
def check_gui_calls_partial(
self, expected=None, not_expected=None, verify_order=False
):
def check_gui_calls_partial(self, expected=None, not_expected=None, verify_order=False):
"""Checks that the expected calls have been made to 'self', then clears the log.
`expected` is an iterable of strings representing method names. Order doesn't matter.
@@ -99,25 +97,17 @@ class CallLogger:
__tracebackhide__ = True
if expected is not None:
not_called = set(expected) - set(self.calls)
assert not not_called, "These calls haven't been made: {0}".format(
not_called
)
assert not not_called, "These calls haven't been made: {0}".format(not_called)
if verify_order:
max_index = 0
for call in expected:
index = self.calls.index(call)
if index < max_index:
raise AssertionError(
"The call {0} hasn't been made in the correct order".format(
call
)
)
raise AssertionError("The call {0} hasn't been made in the correct order".format(call))
max_index = index
if not_expected is not None:
called = set(not_expected) & set(self.calls)
assert not called, "These calls shouldn't have been made: {0}".format(
called
)
assert not called, "These calls shouldn't have been made: {0}".format(called)
self.clear_calls()
@@ -193,27 +183,25 @@ def jointhreads():
def _unify_args(func, args, kwargs, args_to_ignore=None):
""" Unify args and kwargs in the same dictionary.
"""Unify args and kwargs in the same dictionary.
The result is kwargs with args added to it. func.func_code.co_varnames is used to determine
under what key each elements of arg will be mapped in kwargs.
The result is kwargs with args added to it. func.func_code.co_varnames is used to determine
under what key each elements of arg will be mapped in kwargs.
if you want some arguments not to be in the results, supply a list of arg names in
args_to_ignore.
if you want some arguments not to be in the results, supply a list of arg names in
args_to_ignore.
if f is a function that takes *args, func_code.co_varnames is empty, so args will be put
under 'args' in kwargs.
if f is a function that takes *args, func_code.co_varnames is empty, so args will be put
under 'args' in kwargs.
def foo(bar, baz)
_unifyArgs(foo, (42,), {'baz': 23}) --> {'bar': 42, 'baz': 23}
_unifyArgs(foo, (42,), {'baz': 23}, ['bar']) --> {'baz': 23}
def foo(bar, baz)
_unifyArgs(foo, (42,), {'baz': 23}) --> {'bar': 42, 'baz': 23}
_unifyArgs(foo, (42,), {'baz': 23}, ['bar']) --> {'baz': 23}
"""
result = kwargs.copy()
if hasattr(func, "__code__"): # built-in functions don't have func_code
args = list(args)
if (
getattr(func, "__self__", None) is not None
): # bound method, we have to add self to args list
if getattr(func, "__self__", None) is not None: # bound method, we have to add self to args list
args = [func.__self__] + args
defaults = list(func.__defaults__) if func.__defaults__ is not None else []
arg_count = func.__code__.co_argcount
@@ -234,11 +222,11 @@ def _unify_args(func, args, kwargs, args_to_ignore=None):
def log_calls(func):
""" Logs all func calls' arguments under func.calls.
"""Logs all func calls' arguments under func.calls.
func.calls is a list of _unify_args() result (dict).
func.calls is a list of _unify_args() result (dict).
Mostly used for unit testing.
Mostly used for unit testing.
"""
def wrapper(*args, **kwargs):

View File

@@ -110,9 +110,7 @@ def install_gettext_trans(base_folder, lang):
if not lang:
return lambda s: s
try:
return gettext.translation(
domain, localedir=base_folder, languages=[lang]
).gettext
return gettext.translation(domain, localedir=base_folder, languages=[lang]).gettext
except IOError:
return lambda s: s

View File

@@ -19,8 +19,7 @@ from .path import Path, pathify, log_io_error
def nonone(value, replace_value):
"""Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise.
"""
"""Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise."""
if value is None:
return replace_value
else:
@@ -28,8 +27,7 @@ def nonone(value, replace_value):
def tryint(value, default=0):
"""Tries to convert ``value`` to in ``int`` and returns ``default`` if it fails.
"""
"""Tries to convert ``value`` to in ``int`` and returns ``default`` if it fails."""
try:
return int(value)
except (TypeError, ValueError):
@@ -37,8 +35,7 @@ def tryint(value, default=0):
def minmax(value, min_value, max_value):
"""Returns `value` or one of the min/max bounds if `value` is not between them.
"""
"""Returns `value` or one of the min/max bounds if `value` is not between them."""
return min(max(value, min_value), max_value)
@@ -75,8 +72,7 @@ def flatten(iterables, start_with=None):
def first(iterable):
"""Returns the first item of ``iterable``.
"""
"""Returns the first item of ``iterable``."""
try:
return next(iter(iterable))
except StopIteration:
@@ -84,14 +80,12 @@ def first(iterable):
def stripfalse(seq):
"""Returns a sequence with all false elements stripped out of 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.
"""
"""Separates the wheat from the shaft (`predicate` defines what's the wheat), and returns both."""
wheat = []
shaft = []
for item in iterable:
@@ -103,8 +97,7 @@ def extract(predicate, iterable):
def allsame(iterable):
"""Returns whether all elements of 'iterable' are the same.
"""
"""Returns whether all elements of 'iterable' are the same."""
it = iter(iterable)
try:
first_item = next(it)
@@ -152,14 +145,12 @@ def iterconsume(seq, reverse=True):
def escape(s, to_escape, escape_with="\\"):
"""Returns ``s`` with characters in ``to_escape`` all prepended with ``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)
def get_file_ext(filename):
"""Returns the lowercase extension part of filename, without the dot.
"""
"""Returns the lowercase extension part of filename, without the dot."""
pos = filename.rfind(".")
if pos > -1:
return filename[pos + 1 :].lower()
@@ -168,8 +159,7 @@ def get_file_ext(filename):
def rem_file_ext(filename):
"""Returns the filename without extension.
"""
"""Returns the filename without extension."""
pos = filename.rfind(".")
if pos > -1:
return filename[:pos]
@@ -217,8 +207,7 @@ def format_time(seconds, with_hours=True):
def format_time_decimal(seconds):
"""Transforms seconds in a strings like '3.4 minutes'.
"""
"""Transforms seconds in a strings like '3.4 minutes'."""
minus = seconds < 0
if minus:
seconds *= -1
@@ -320,8 +309,7 @@ ONE_DAY = timedelta(1)
def iterdaterange(start, end):
"""Yields every day between ``start`` and ``end``.
"""
"""Yields every day between ``start`` and ``end``."""
date = start
while date <= end:
yield date
@@ -365,8 +353,7 @@ def find_in_path(name, paths=None):
@log_io_error
@pathify
def delete_if_empty(path: Path, files_to_delete=[]):
"""Deletes the directory at 'path' if it is empty or if it only contains files_to_delete.
"""
"""Deletes the directory at 'path' if it is empty or if it only contains files_to_delete."""
if not path.exists() or not path.isdir():
return
contents = path.listdir()
@@ -411,8 +398,7 @@ def ensure_file(path):
def delete_files_with_pattern(folder_path, pattern, recursive=True):
"""Delete all files (or folders) in `folder_path` that match the glob `pattern`.
"""
"""Delete all files (or folders) in `folder_path` that match the glob `pattern`."""
to_delete = glob.glob(op.join(folder_path, pattern))
for fn in to_delete:
if op.isdir(fn):