mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-05-08 17:59:50 +00:00
Compare commits
5 Commits
7658cdafbc
...
092cf1471b
Author | SHA1 | Date | |
---|---|---|---|
092cf1471b | |||
4f252480d3 | |||
5cc439d846 | |||
ee2671a5f3 | |||
e05c72ad8c |
@ -224,7 +224,7 @@ class Directories:
|
|||||||
root = ET.parse(infile).getroot()
|
root = ET.parse(infile).getroot()
|
||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
for rdn in root.getiterator("root_directory"):
|
for rdn in root.iter("root_directory"):
|
||||||
attrib = rdn.attrib
|
attrib = rdn.attrib
|
||||||
if "path" not in attrib:
|
if "path" not in attrib:
|
||||||
continue
|
continue
|
||||||
@ -233,7 +233,7 @@ class Directories:
|
|||||||
self.add_path(Path(path))
|
self.add_path(Path(path))
|
||||||
except (AlreadyThereError, InvalidPathError):
|
except (AlreadyThereError, InvalidPathError):
|
||||||
pass
|
pass
|
||||||
for sn in root.getiterator("state"):
|
for sn in root.iter("state"):
|
||||||
attrib = sn.attrib
|
attrib = sn.attrib
|
||||||
if not ("path" in attrib and "value" in attrib):
|
if not ("path" in attrib and "value" in attrib):
|
||||||
continue
|
continue
|
||||||
|
@ -241,13 +241,13 @@ class Results(Markable):
|
|||||||
|
|
||||||
self.apply_filter(None)
|
self.apply_filter(None)
|
||||||
root = ET.parse(infile).getroot()
|
root = ET.parse(infile).getroot()
|
||||||
group_elems = list(root.getiterator("group"))
|
group_elems = list(root.iter("group"))
|
||||||
groups = []
|
groups = []
|
||||||
marked = set()
|
marked = set()
|
||||||
for group_elem in j.iter_with_progress(group_elems, every=100):
|
for group_elem in j.iter_with_progress(group_elems, every=100):
|
||||||
group = engine.Group()
|
group = engine.Group()
|
||||||
dupes = []
|
dupes = []
|
||||||
for file_elem in group_elem.getiterator("file"):
|
for file_elem in group_elem.iter("file"):
|
||||||
path = file_elem.get("path")
|
path = file_elem.get("path")
|
||||||
words = file_elem.get("words", "")
|
words = file_elem.get("words", "")
|
||||||
if not path:
|
if not path:
|
||||||
@ -260,7 +260,7 @@ class Results(Markable):
|
|||||||
dupes.append(file)
|
dupes.append(file)
|
||||||
if file_elem.get("marked") == "y":
|
if file_elem.get("marked") == "y":
|
||||||
marked.add(file)
|
marked.add(file)
|
||||||
for match_elem in group_elem.getiterator("match"):
|
for match_elem in group_elem.iter("match"):
|
||||||
try:
|
try:
|
||||||
attrs = match_elem.attrib
|
attrs = match_elem.attrib
|
||||||
first_file = dupes[int(attrs["first"])]
|
first_file = dupes[int(attrs["first"])]
|
||||||
|
@ -8,7 +8,7 @@ import os
|
|||||||
import os.path as op
|
import os.path as op
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from pytest import mark
|
import pytest
|
||||||
from hscommon.path import Path
|
from hscommon.path import Path
|
||||||
import hscommon.conflict
|
import hscommon.conflict
|
||||||
import hscommon.util
|
import hscommon.util
|
||||||
@ -109,7 +109,7 @@ class TestCaseDupeGuru:
|
|||||||
add_fake_files_to_directories(app.directories, [f1, f2])
|
add_fake_files_to_directories(app.directories, [f1, f2])
|
||||||
app.start_scanning() # no exception
|
app.start_scanning() # no exception
|
||||||
|
|
||||||
@mark.skipif("not hasattr(os, 'link')")
|
@pytest.mark.skipif("not hasattr(os, 'link')")
|
||||||
def test_ignore_hardlink_matches(self, tmpdir):
|
def test_ignore_hardlink_matches(self, tmpdir):
|
||||||
# If the ignore_hardlink_matches option is set, don't match files hardlinking to the same
|
# If the ignore_hardlink_matches option is set, don't match files hardlinking to the same
|
||||||
# inode.
|
# inode.
|
||||||
@ -133,8 +133,9 @@ class TestCaseDupeGuru:
|
|||||||
|
|
||||||
|
|
||||||
class TestCaseDupeGuru_clean_empty_dirs:
|
class TestCaseDupeGuru_clean_empty_dirs:
|
||||||
def pytest_funcarg__do_setup(self, request):
|
@pytest.fixture
|
||||||
monkeypatch = request.getfuncargvalue("monkeypatch")
|
def do_setup(self, request):
|
||||||
|
monkeypatch = request.getfixturevalue("monkeypatch")
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
hscommon.util,
|
hscommon.util,
|
||||||
"delete_if_empty",
|
"delete_if_empty",
|
||||||
@ -175,7 +176,8 @@ class TestCaseDupeGuru_clean_empty_dirs:
|
|||||||
|
|
||||||
|
|
||||||
class TestCaseDupeGuruWithResults:
|
class TestCaseDupeGuruWithResults:
|
||||||
def pytest_funcarg__do_setup(self, request):
|
@pytest.fixture
|
||||||
|
def do_setup(self, request):
|
||||||
app = TestApp()
|
app = TestApp()
|
||||||
self.app = app.app
|
self.app = app.app
|
||||||
self.objects, self.matches, self.groups = GetTestGroups()
|
self.objects, self.matches, self.groups = GetTestGroups()
|
||||||
@ -184,7 +186,7 @@ class TestCaseDupeGuruWithResults:
|
|||||||
self.dtree = app.dtree
|
self.dtree = app.dtree
|
||||||
self.rtable = app.rtable
|
self.rtable = app.rtable
|
||||||
self.rtable.refresh()
|
self.rtable.refresh()
|
||||||
tmpdir = request.getfuncargvalue("tmpdir")
|
tmpdir = request.getfixturevalue("tmpdir")
|
||||||
tmppath = Path(str(tmpdir))
|
tmppath = Path(str(tmpdir))
|
||||||
tmppath["foo"].mkdir()
|
tmppath["foo"].mkdir()
|
||||||
tmppath["bar"].mkdir()
|
tmppath["bar"].mkdir()
|
||||||
@ -430,8 +432,9 @@ class TestCaseDupeGuruWithResults:
|
|||||||
|
|
||||||
|
|
||||||
class TestCaseDupeGuru_renameSelected:
|
class TestCaseDupeGuru_renameSelected:
|
||||||
def pytest_funcarg__do_setup(self, request):
|
@pytest.fixture
|
||||||
tmpdir = request.getfuncargvalue("tmpdir")
|
def do_setup(self, request):
|
||||||
|
tmpdir = request.getfixturevalue("tmpdir")
|
||||||
p = Path(str(tmpdir))
|
p = Path(str(tmpdir))
|
||||||
fp = open(str(p["foo bar 1"]), mode="w")
|
fp = open(str(p["foo bar 1"]), mode="w")
|
||||||
fp.close()
|
fp.close()
|
||||||
@ -493,8 +496,9 @@ class TestCaseDupeGuru_renameSelected:
|
|||||||
|
|
||||||
|
|
||||||
class TestAppWithDirectoriesInTree:
|
class TestAppWithDirectoriesInTree:
|
||||||
def pytest_funcarg__do_setup(self, request):
|
@pytest.fixture
|
||||||
tmpdir = request.getfuncargvalue("tmpdir")
|
def do_setup(self, request):
|
||||||
|
tmpdir = request.getfixturevalue("tmpdir")
|
||||||
p = Path(str(tmpdir))
|
p = Path(str(tmpdir))
|
||||||
p["sub1"].mkdir()
|
p["sub1"].mkdir()
|
||||||
p["sub2"].mkdir()
|
p["sub2"].mkdir()
|
||||||
|
@ -147,6 +147,8 @@ def GetTestGroups():
|
|||||||
|
|
||||||
|
|
||||||
class TestApp(TestAppBase):
|
class TestApp(TestAppBase):
|
||||||
|
__test__ = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
def link_gui(gui):
|
def link_gui(gui):
|
||||||
gui.view = self.make_logger()
|
gui.view = self.make_logger()
|
||||||
|
@ -1 +1 @@
|
|||||||
from hscommon.testutil import pytest_funcarg__app # noqa
|
from hscommon.testutil import app # noqa
|
||||||
|
@ -414,12 +414,12 @@ class TestCaseResultsMarkings:
|
|||||||
f.seek(0)
|
f.seek(0)
|
||||||
doc = ET.parse(f)
|
doc = ET.parse(f)
|
||||||
root = doc.getroot()
|
root = doc.getroot()
|
||||||
g1, g2 = root.getiterator("group")
|
g1, g2 = root.iter("group")
|
||||||
d1, d2, d3 = g1.getiterator("file")
|
d1, d2, d3 = g1.iter("file")
|
||||||
eq_("n", d1.get("marked"))
|
eq_("n", d1.get("marked"))
|
||||||
eq_("n", d2.get("marked"))
|
eq_("n", d2.get("marked"))
|
||||||
eq_("y", d3.get("marked"))
|
eq_("y", d3.get("marked"))
|
||||||
d1, d2 = g2.getiterator("file")
|
d1, d2 = g2.iter("file")
|
||||||
eq_("n", d1.get("marked"))
|
eq_("n", d1.get("marked"))
|
||||||
eq_("y", d2.get("marked"))
|
eq_("y", d2.get("marked"))
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from hscommon.jobprogress import job
|
from hscommon.jobprogress import job
|
||||||
from hscommon.path import Path
|
from hscommon.path import Path
|
||||||
from hscommon.testutil import eq_
|
from hscommon.testutil import eq_
|
||||||
@ -33,10 +35,11 @@ class NamedObject:
|
|||||||
no = NamedObject
|
no = NamedObject
|
||||||
|
|
||||||
|
|
||||||
def pytest_funcarg__fake_fileexists(request):
|
@pytest.fixture
|
||||||
|
def fake_fileexists(request):
|
||||||
# This is a hack to avoid invalidating all previous tests since the scanner started to test
|
# This is a hack to avoid invalidating all previous tests since the scanner started to test
|
||||||
# for file existence before doing the match grouping.
|
# for file existence before doing the match grouping.
|
||||||
monkeypatch = request.getfuncargvalue("monkeypatch")
|
monkeypatch = request.getfixturevalue("monkeypatch")
|
||||||
monkeypatch.setattr(Path, "exists", lambda _: True)
|
monkeypatch.setattr(Path, "exists", lambda _: True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
from collections import Sequence, MutableSequence
|
from collections.abc import Sequence, MutableSequence
|
||||||
|
|
||||||
from .base import GUIObject
|
from .base import GUIObject
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
from collections import MutableSequence, namedtuple
|
from collections.abc import MutableSequence
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from .base import GUIObject
|
from .base import GUIObject
|
||||||
from .selectable_list import Selectable
|
from .selectable_list import Selectable
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
from collections import MutableSequence
|
from collections.abc import MutableSequence
|
||||||
|
|
||||||
from .base import GUIObject
|
from .base import GUIObject
|
||||||
|
|
||||||
|
@ -257,6 +257,6 @@ def log_io_error(func):
|
|||||||
msg = 'Error "{0}" during operation "{1}" on "{2}": "{3}"'
|
msg = 'Error "{0}" during operation "{1}" on "{2}": "{3}"'
|
||||||
classname = e.__class__.__name__
|
classname = e.__class__.__name__
|
||||||
funcname = func.__name__
|
funcname = func.__name__
|
||||||
logging.warn(msg.format(classname, funcname, str(path), str(e)))
|
logging.warning(msg.format(classname, funcname, str(path), str(e)))
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
@ -6,7 +6,15 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
from ..conflict import *
|
import pytest
|
||||||
|
|
||||||
|
from ..conflict import (
|
||||||
|
get_conflicted_name,
|
||||||
|
get_unconflicted_name,
|
||||||
|
is_conflicted,
|
||||||
|
smart_copy,
|
||||||
|
smart_move,
|
||||||
|
)
|
||||||
from ..path import Path
|
from ..path import Path
|
||||||
from ..testutil import eq_
|
from ..testutil import eq_
|
||||||
|
|
||||||
@ -59,8 +67,9 @@ class TestCase_IsConflicted:
|
|||||||
|
|
||||||
|
|
||||||
class TestCase_move_copy:
|
class TestCase_move_copy:
|
||||||
def pytest_funcarg__do_setup(self, request):
|
@pytest.fixture
|
||||||
tmpdir = request.getfuncargvalue("tmpdir")
|
def do_setup(self, request):
|
||||||
|
tmpdir = request.getfixturevalue("tmpdir")
|
||||||
self.path = Path(str(tmpdir))
|
self.path = Path(str(tmpdir))
|
||||||
self.path["foo"].open("w").close()
|
self.path["foo"].open("w").close()
|
||||||
self.path["bar"].open("w").close()
|
self.path["bar"].open("w").close()
|
||||||
|
@ -28,8 +28,8 @@ class HelloRepeater(Repeater):
|
|||||||
|
|
||||||
def create_pair():
|
def create_pair():
|
||||||
b = Broadcaster()
|
b = Broadcaster()
|
||||||
l = HelloListener(b)
|
listener = HelloListener(b)
|
||||||
return b, l
|
return b, listener
|
||||||
|
|
||||||
|
|
||||||
def test_disconnect_during_notification():
|
def test_disconnect_during_notification():
|
||||||
@ -60,53 +60,53 @@ def test_disconnect_during_notification():
|
|||||||
|
|
||||||
def test_disconnect():
|
def test_disconnect():
|
||||||
# After a disconnect, the listener doesn't hear anything.
|
# After a disconnect, the listener doesn't hear anything.
|
||||||
b, l = create_pair()
|
b, listener = create_pair()
|
||||||
l.connect()
|
listener.connect()
|
||||||
l.disconnect()
|
listener.disconnect()
|
||||||
b.notify("hello")
|
b.notify("hello")
|
||||||
eq_(l.hello_count, 0)
|
eq_(listener.hello_count, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_disconnect_when_not_connected():
|
def test_disconnect_when_not_connected():
|
||||||
# When disconnecting an already disconnected listener, nothing happens.
|
# When disconnecting an already disconnected listener, nothing happens.
|
||||||
b, l = create_pair()
|
b, listener = create_pair()
|
||||||
l.disconnect()
|
listener.disconnect()
|
||||||
|
|
||||||
|
|
||||||
def test_not_connected_on_init():
|
def test_not_connected_on_init():
|
||||||
# A listener is not initialized connected.
|
# A listener is not initialized connected.
|
||||||
b, l = create_pair()
|
b, listener = create_pair()
|
||||||
b.notify("hello")
|
b.notify("hello")
|
||||||
eq_(l.hello_count, 0)
|
eq_(listener.hello_count, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_notify():
|
def test_notify():
|
||||||
# The listener listens to the broadcaster.
|
# The listener listens to the broadcaster.
|
||||||
b, l = create_pair()
|
b, listener = create_pair()
|
||||||
l.connect()
|
listener.connect()
|
||||||
b.notify("hello")
|
b.notify("hello")
|
||||||
eq_(l.hello_count, 1)
|
eq_(listener.hello_count, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_reconnect():
|
def test_reconnect():
|
||||||
# It's possible to reconnect a listener after disconnection.
|
# It's possible to reconnect a listener after disconnection.
|
||||||
b, l = create_pair()
|
b, listener = create_pair()
|
||||||
l.connect()
|
listener.connect()
|
||||||
l.disconnect()
|
listener.disconnect()
|
||||||
l.connect()
|
listener.connect()
|
||||||
b.notify("hello")
|
b.notify("hello")
|
||||||
eq_(l.hello_count, 1)
|
eq_(listener.hello_count, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_repeater():
|
def test_repeater():
|
||||||
b = Broadcaster()
|
b = Broadcaster()
|
||||||
r = HelloRepeater(b)
|
r = HelloRepeater(b)
|
||||||
l = HelloListener(r)
|
listener = HelloListener(r)
|
||||||
r.connect()
|
r.connect()
|
||||||
l.connect()
|
listener.connect()
|
||||||
b.notify("hello")
|
b.notify("hello")
|
||||||
eq_(r.hello_count, 1)
|
eq_(r.hello_count, 1)
|
||||||
eq_(l.hello_count, 1)
|
eq_(listener.hello_count, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_repeater_with_repeated_notifications():
|
def test_repeater_with_repeated_notifications():
|
||||||
@ -124,15 +124,15 @@ def test_repeater_with_repeated_notifications():
|
|||||||
|
|
||||||
b = Broadcaster()
|
b = Broadcaster()
|
||||||
r = MyRepeater(b)
|
r = MyRepeater(b)
|
||||||
l = HelloListener(r)
|
listener = HelloListener(r)
|
||||||
r.connect()
|
r.connect()
|
||||||
l.connect()
|
listener.connect()
|
||||||
b.notify("hello")
|
b.notify("hello")
|
||||||
b.notify(
|
b.notify(
|
||||||
"foo"
|
"foo"
|
||||||
) # if the repeater repeated this notif, we'd get a crash on HelloListener
|
) # if the repeater repeated this notif, we'd get a crash on HelloListener
|
||||||
eq_(r.hello_count, 1)
|
eq_(r.hello_count, 1)
|
||||||
eq_(l.hello_count, 1)
|
eq_(listener.hello_count, 1)
|
||||||
eq_(r.foo_count, 1)
|
eq_(r.foo_count, 1)
|
||||||
|
|
||||||
|
|
||||||
@ -140,18 +140,18 @@ def test_repeater_doesnt_try_to_dispatch_to_self_if_it_cant():
|
|||||||
# if a repeater doesn't handle a particular message, it doesn't crash and simply repeats it.
|
# if a repeater doesn't handle a particular message, it doesn't crash and simply repeats it.
|
||||||
b = Broadcaster()
|
b = Broadcaster()
|
||||||
r = Repeater(b) # doesnt handle hello
|
r = Repeater(b) # doesnt handle hello
|
||||||
l = HelloListener(r)
|
listener = HelloListener(r)
|
||||||
r.connect()
|
r.connect()
|
||||||
l.connect()
|
listener.connect()
|
||||||
b.notify("hello") # no crash
|
b.notify("hello") # no crash
|
||||||
eq_(l.hello_count, 1)
|
eq_(listener.hello_count, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_bind_messages():
|
def test_bind_messages():
|
||||||
b, l = create_pair()
|
b, listener = create_pair()
|
||||||
l.bind_messages({"foo", "bar"}, l.hello)
|
listener.bind_messages({"foo", "bar"}, listener.hello)
|
||||||
l.connect()
|
listener.connect()
|
||||||
b.notify("foo")
|
b.notify("foo")
|
||||||
b.notify("bar")
|
b.notify("bar")
|
||||||
b.notify("hello") # Normal dispatching still work
|
b.notify("hello") # Normal dispatching still work
|
||||||
eq_(l.hello_count, 3)
|
eq_(listener.hello_count, 3)
|
||||||
|
@ -9,14 +9,15 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from pytest import raises, mark
|
import pytest
|
||||||
|
|
||||||
from ..path import Path, pathify
|
from ..path import Path, pathify
|
||||||
from ..testutil import eq_
|
from ..testutil import eq_
|
||||||
|
|
||||||
|
|
||||||
def pytest_funcarg__force_ossep(request):
|
@pytest.fixture
|
||||||
monkeypatch = request.getfuncargvalue("monkeypatch")
|
def force_ossep(request):
|
||||||
|
monkeypatch = request.getfixturevalue("monkeypatch")
|
||||||
monkeypatch.setattr(os, "sep", "/")
|
monkeypatch.setattr(os, "sep", "/")
|
||||||
|
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ def test_init_with_tuple_and_list(force_ossep):
|
|||||||
|
|
||||||
def test_init_with_invalid_value(force_ossep):
|
def test_init_with_invalid_value(force_ossep):
|
||||||
try:
|
try:
|
||||||
path = Path(42)
|
path = Path(42) # noqa: F841
|
||||||
assert False
|
assert False
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
@ -142,8 +143,8 @@ def test_path_slice(force_ossep):
|
|||||||
eq_((), foobar[:foobar])
|
eq_((), foobar[:foobar])
|
||||||
abcd = Path("a/b/c/d")
|
abcd = Path("a/b/c/d")
|
||||||
a = Path("a")
|
a = Path("a")
|
||||||
b = Path("b")
|
b = Path("b") # noqa: #F841
|
||||||
c = Path("c")
|
c = Path("c") # noqa: #F841
|
||||||
d = Path("d")
|
d = Path("d")
|
||||||
z = Path("z")
|
z = Path("z")
|
||||||
eq_("b/c", abcd[a:d])
|
eq_("b/c", abcd[a:d])
|
||||||
@ -236,12 +237,12 @@ def test_getitem_path(force_ossep):
|
|||||||
eq_(p[Path("baz/bleh")], Path("/foo/bar/baz/bleh"))
|
eq_(p[Path("baz/bleh")], Path("/foo/bar/baz/bleh"))
|
||||||
|
|
||||||
|
|
||||||
@mark.xfail(reason="pytest's capture mechanism is flaky, I have to investigate")
|
@pytest.mark.xfail(reason="pytest's capture mechanism is flaky, I have to investigate")
|
||||||
def test_log_unicode_errors(force_ossep, monkeypatch, capsys):
|
def test_log_unicode_errors(force_ossep, monkeypatch, capsys):
|
||||||
# When an there's a UnicodeDecodeError on path creation, log it so it can be possible
|
# When an there's a UnicodeDecodeError on path creation, log it so it can be possible
|
||||||
# to debug the cause of it.
|
# to debug the cause of it.
|
||||||
monkeypatch.setattr(sys, "getfilesystemencoding", lambda: "ascii")
|
monkeypatch.setattr(sys, "getfilesystemencoding", lambda: "ascii")
|
||||||
with raises(UnicodeDecodeError):
|
with pytest.raises(UnicodeDecodeError):
|
||||||
Path(["", b"foo\xe9"])
|
Path(["", b"foo\xe9"])
|
||||||
out, err = capsys.readouterr()
|
out, err = capsys.readouterr()
|
||||||
assert repr(b"foo\xe9") in err
|
assert repr(b"foo\xe9") in err
|
||||||
|
@ -95,7 +95,7 @@ def test_make_sure_theres_no_messup_between_queries():
|
|||||||
threads.append(t)
|
threads.append(t)
|
||||||
while threads:
|
while threads:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
threads = [t for t in threads if t.isAlive()]
|
threads = [t for t in threads if t.is_alive()]
|
||||||
|
|
||||||
|
|
||||||
def test_query_after_close():
|
def test_query_after_close():
|
||||||
|
@ -11,6 +11,8 @@ from ..gui.table import Table, GUITable, Row
|
|||||||
|
|
||||||
|
|
||||||
class TestRow(Row):
|
class TestRow(Row):
|
||||||
|
__test__ = False
|
||||||
|
|
||||||
def __init__(self, table, index, is_new=False):
|
def __init__(self, table, index, is_new=False):
|
||||||
Row.__init__(self, table)
|
Row.__init__(self, table)
|
||||||
self.is_new = is_new
|
self.is_new = is_new
|
||||||
@ -28,6 +30,8 @@ class TestRow(Row):
|
|||||||
|
|
||||||
|
|
||||||
class TestGUITable(GUITable):
|
class TestGUITable(GUITable):
|
||||||
|
__test__ = False
|
||||||
|
|
||||||
def __init__(self, rowcount, viewclass=CallLogger):
|
def __init__(self, rowcount, viewclass=CallLogger):
|
||||||
GUITable.__init__(self)
|
GUITable.__init__(self)
|
||||||
self.view = viewclass()
|
self.view = viewclass()
|
||||||
|
@ -12,7 +12,31 @@ from pytest import raises
|
|||||||
|
|
||||||
from ..testutil import eq_
|
from ..testutil import eq_
|
||||||
from ..path import Path
|
from ..path import Path
|
||||||
from ..util import *
|
from ..util import (
|
||||||
|
nonone,
|
||||||
|
tryint,
|
||||||
|
minmax,
|
||||||
|
first,
|
||||||
|
flatten,
|
||||||
|
dedupe,
|
||||||
|
stripfalse,
|
||||||
|
extract,
|
||||||
|
allsame,
|
||||||
|
trailiter,
|
||||||
|
format_time,
|
||||||
|
format_time_decimal,
|
||||||
|
format_size,
|
||||||
|
remove_invalid_xml,
|
||||||
|
multi_replace,
|
||||||
|
delete_if_empty,
|
||||||
|
open_if_filename,
|
||||||
|
FileOrPath,
|
||||||
|
iterconsume,
|
||||||
|
escape,
|
||||||
|
get_file_ext,
|
||||||
|
rem_file_ext,
|
||||||
|
pluralize,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_nonone():
|
def test_nonone():
|
||||||
@ -214,42 +238,46 @@ def test_multi_replace():
|
|||||||
|
|
||||||
# --- Files
|
# --- Files
|
||||||
|
|
||||||
|
# These test cases needed https://github.com/hsoft/pytest-monkeyplus/ which appears to not be compatible with latest
|
||||||
|
# pytest, looking at where this is used only appears to be in hscommon.localize_all_stringfiles at top level.
|
||||||
|
# Right now this repo does not seem to utilize any of that functionality so going to leave these tests out for now.
|
||||||
|
# TODO decide if fixing these tests is worth it or not.
|
||||||
|
|
||||||
class TestCase_modified_after:
|
# class TestCase_modified_after:
|
||||||
def test_first_is_modified_after(self, monkeyplus):
|
# def test_first_is_modified_after(self, monkeyplus):
|
||||||
monkeyplus.patch_osstat("first", st_mtime=42)
|
# monkeyplus.patch_osstat("first", st_mtime=42)
|
||||||
monkeyplus.patch_osstat("second", st_mtime=41)
|
# monkeyplus.patch_osstat("second", st_mtime=41)
|
||||||
assert modified_after("first", "second")
|
# assert modified_after("first", "second")
|
||||||
|
|
||||||
def test_second_is_modified_after(self, monkeyplus):
|
# def test_second_is_modified_after(self, monkeyplus):
|
||||||
monkeyplus.patch_osstat("first", st_mtime=42)
|
# monkeyplus.patch_osstat("first", st_mtime=42)
|
||||||
monkeyplus.patch_osstat("second", st_mtime=43)
|
# monkeyplus.patch_osstat("second", st_mtime=43)
|
||||||
assert not modified_after("first", "second")
|
# assert not modified_after("first", "second")
|
||||||
|
|
||||||
def test_same_mtime(self, monkeyplus):
|
# def test_same_mtime(self, monkeyplus):
|
||||||
monkeyplus.patch_osstat("first", st_mtime=42)
|
# monkeyplus.patch_osstat("first", st_mtime=42)
|
||||||
monkeyplus.patch_osstat("second", st_mtime=42)
|
# monkeyplus.patch_osstat("second", st_mtime=42)
|
||||||
assert not modified_after("first", "second")
|
# assert not modified_after("first", "second")
|
||||||
|
|
||||||
def test_first_file_does_not_exist(self, monkeyplus):
|
# def test_first_file_does_not_exist(self, monkeyplus):
|
||||||
# when the first file doesn't exist, we return False
|
# # when the first file doesn't exist, we return False
|
||||||
monkeyplus.patch_osstat("second", st_mtime=42)
|
# monkeyplus.patch_osstat("second", st_mtime=42)
|
||||||
assert not modified_after("does_not_exist", "second") # no crash
|
# assert not modified_after("does_not_exist", "second") # no crash
|
||||||
|
|
||||||
def test_second_file_does_not_exist(self, monkeyplus):
|
# def test_second_file_does_not_exist(self, monkeyplus):
|
||||||
# when the second file doesn't exist, we return True
|
# # when the second file doesn't exist, we return True
|
||||||
monkeyplus.patch_osstat("first", st_mtime=42)
|
# monkeyplus.patch_osstat("first", st_mtime=42)
|
||||||
assert modified_after("first", "does_not_exist") # no crash
|
# assert modified_after("first", "does_not_exist") # no crash
|
||||||
|
|
||||||
def test_first_file_is_none(self, monkeyplus):
|
# def test_first_file_is_none(self, monkeyplus):
|
||||||
# when the first file is None, we return False
|
# # when the first file is None, we return False
|
||||||
monkeyplus.patch_osstat("second", st_mtime=42)
|
# monkeyplus.patch_osstat("second", st_mtime=42)
|
||||||
assert not modified_after(None, "second") # no crash
|
# assert not modified_after(None, "second") # no crash
|
||||||
|
|
||||||
def test_second_file_is_none(self, monkeyplus):
|
# def test_second_file_is_none(self, monkeyplus):
|
||||||
# when the second file is None, we return True
|
# # when the second file is None, we return True
|
||||||
monkeyplus.patch_osstat("first", st_mtime=42)
|
# monkeyplus.patch_osstat("first", st_mtime=42)
|
||||||
assert modified_after("first", None) # no crash
|
# assert modified_after("first", None) # no crash
|
||||||
|
|
||||||
|
|
||||||
class TestCase_delete_if_empty:
|
class TestCase_delete_if_empty:
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import py.path
|
import py.path
|
||||||
|
|
||||||
@ -148,7 +150,7 @@ class TestApp:
|
|||||||
return gui
|
return gui
|
||||||
|
|
||||||
|
|
||||||
# To use @with_app, you have to import pytest_funcarg__app in your conftest.py file.
|
# To use @with_app, you have to import app in your conftest.py file.
|
||||||
def with_app(setupfunc):
|
def with_app(setupfunc):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
func.setupfunc = setupfunc
|
func.setupfunc = setupfunc
|
||||||
@ -157,7 +159,8 @@ def with_app(setupfunc):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def pytest_funcarg__app(request):
|
@pytest.fixture
|
||||||
|
def app(request):
|
||||||
setupfunc = request.function.setupfunc
|
setupfunc = request.function.setupfunc
|
||||||
if hasattr(setupfunc, "__code__"):
|
if hasattr(setupfunc, "__code__"):
|
||||||
argnames = setupfunc.__code__.co_varnames[: setupfunc.__code__.co_argcount]
|
argnames = setupfunc.__code__.co_varnames[: setupfunc.__code__.co_argcount]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
pytest>=2.0.0,<3.0
|
pytest>=5,<6
|
||||||
pytest-monkeyplus>=1.0.0
|
|
||||||
flake8
|
flake8
|
||||||
tox-travis
|
tox-travis
|
||||||
black
|
black
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
PyQt5 >=5.4,<6.0
|
PyQt5 >=5.4,<6.0
|
||||||
pypiwin32>=200
|
pywin32>=200
|
||||||
pyinstaller>=3.4,<4.0
|
pyinstaller>=3.4,<4.0
|
2
run.py
2
run.py
@ -16,7 +16,7 @@ from PyQt5.QtWidgets import QApplication
|
|||||||
from hscommon.trans import install_gettext_trans_under_qt
|
from hscommon.trans import install_gettext_trans_under_qt
|
||||||
from qtlib.error_report_dialog import install_excepthook
|
from qtlib.error_report_dialog import install_excepthook
|
||||||
from qtlib.util import setupQtLogging
|
from qtlib.util import setupQtLogging
|
||||||
from qt import dg_rc
|
from qt import dg_rc # noqa: F401
|
||||||
from qt.platform import BASE_PATH
|
from qt.platform import BASE_PATH
|
||||||
from core import __version__, __appname__
|
from core import __version__, __appname__
|
||||||
|
|
||||||
|
2
tox.ini
2
tox.ini
@ -31,7 +31,7 @@ commands =
|
|||||||
python package.py
|
python package.py
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
exclude = .tox,env,build,hscommon/tests,cocoalib,cocoa,help,./qt/dg_rc.py,qt/run_template.py,cocoa/run_template.py,./run.py,./pkg
|
exclude = .tox,env,build,cocoalib,cocoa,help,./qt/dg_rc.py,cocoa/run_template.py,./pkg
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
ignore = E731,E203,E501,W503
|
ignore = E731,E203,E501,W503
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user