improving the pylint score
This commit is contained in:
parent
edd9dda7ce
commit
4d60d19fd9
@ -1,4 +1,5 @@
|
|||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
""" Test program for import modules """
|
||||||
#
|
#
|
||||||
# Gramps - a GTK+/GNOME based genealogy program
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
#
|
#
|
||||||
@ -23,13 +24,12 @@ import unittest
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
import time
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from gramps.gen.merge.diff import diff_dbs, import_as_dict
|
from gramps.gen.merge.diff import diff_dbs, import_as_dict
|
||||||
from gramps.gen.simple import SimpleAccess
|
from gramps.gen.simple import SimpleAccess
|
||||||
from gramps.gen.utils.id import set_det_id
|
from gramps.gen.utils.id import set_det_id
|
||||||
from gramps.cli import user
|
from gramps.cli.user import User
|
||||||
from gramps.gen.const import TEMP_DIR, DATA_DIR
|
from gramps.gen.const import TEMP_DIR, DATA_DIR
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -42,21 +42,21 @@ TEST_DIR = os.path.abspath(os.path.join(DATA_DIR, "tests"))
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def todate(t):
|
|
||||||
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t))
|
|
||||||
|
|
||||||
|
|
||||||
class CompleteCheck(unittest.TestCase):
|
class CompleteCheck(unittest.TestCase):
|
||||||
"""The test class cases will be dynamically created at import time from
|
"""The test class cases will be dynamically created at import time from
|
||||||
files to be tested. The following defs are used by the test cases"""
|
files to be tested. The following defs are used by the test cases"""
|
||||||
|
|
||||||
def prepare_result(self, diffs, added, missing):
|
def prepare_result(self, diffs, added, missing):
|
||||||
|
""" Looks through the diffs, added, and missing items and begins
|
||||||
|
reporting process. Returns True if there were significant errors. """
|
||||||
|
# pylint: disable=E1101
|
||||||
|
# pylint does not like dynamically created methods
|
||||||
deltas = False
|
deltas = False
|
||||||
if diffs:
|
if diffs:
|
||||||
for diff in diffs:
|
for diff in diffs:
|
||||||
obj_type, item1, item2 = diff
|
obj_type, item1, item2 = diff
|
||||||
msg = self.report_diff(obj_type, item1.to_struct(),
|
msg = self._report_diff(obj_type, item1.to_struct(),
|
||||||
item2.to_struct())
|
item2.to_struct())
|
||||||
if msg != "":
|
if msg != "":
|
||||||
if hasattr(item1, "gramps_id"):
|
if hasattr(item1, "gramps_id"):
|
||||||
self.msg += "%s: %s handle=%s\n" % \
|
self.msg += "%s: %s handle=%s\n" % \
|
||||||
@ -68,63 +68,20 @@ class CompleteCheck(unittest.TestCase):
|
|||||||
deltas = True
|
deltas = True
|
||||||
if missing:
|
if missing:
|
||||||
deltas = True
|
deltas = True
|
||||||
sa = SimpleAccess(self.database1)
|
sac = SimpleAccess(self.database1)
|
||||||
for pair in missing:
|
for pair in missing:
|
||||||
obj_type, item = pair
|
obj_type, item = pair
|
||||||
self.msg += "Missing %s: %s\n" % (obj_type, sa.describe(item))
|
self.msg += "Missing %s: %s\n" % (obj_type, sac.describe(item))
|
||||||
if added:
|
if added:
|
||||||
deltas = True
|
deltas = True
|
||||||
sa = SimpleAccess(self.database2)
|
sac = SimpleAccess(self.database2)
|
||||||
for pair in added:
|
for pair in added:
|
||||||
obj_type, item = pair
|
obj_type, item = pair
|
||||||
self.msg += "Added %s: %s\n" % (obj_type, sa.describe(item))
|
self.msg += "Added %s: %s\n" % (obj_type, sac.describe(item))
|
||||||
return deltas
|
return deltas
|
||||||
|
|
||||||
def format_struct_path(self, path):
|
|
||||||
retval = ""
|
|
||||||
parts = path.split(".")
|
|
||||||
for part in parts:
|
|
||||||
if retval:
|
|
||||||
retval += ", "
|
|
||||||
if "[" in part and "]" in part:
|
|
||||||
part, index = re.match("(.*)\[(\d*)\]", part).groups()
|
|
||||||
retval += "%s #%s" % (part.replace("_", " "), int(index) + 1)
|
|
||||||
else:
|
|
||||||
retval += part
|
|
||||||
return retval
|
|
||||||
|
|
||||||
def report_details(self, path, diff1, diff2):
|
def _report_diff(self, path, struct1, struct2):
|
||||||
if isinstance(diff1, bool):
|
|
||||||
desc1 = repr(diff1)
|
|
||||||
else:
|
|
||||||
desc1 = str(diff1) if diff1 else ""
|
|
||||||
if isinstance(diff2, bool):
|
|
||||||
desc2 = repr(diff2)
|
|
||||||
else:
|
|
||||||
desc2 = str(diff2) if diff2 else ""
|
|
||||||
d1t = type(diff1)
|
|
||||||
d2t = type(diff2)
|
|
||||||
# the xml exporter edits the data base by stripping spaces, so
|
|
||||||
# we have to ignore these differeces
|
|
||||||
if d1t == str: diff1 = diff1.strip()
|
|
||||||
if d2t == str: diff2 = diff2.strip()
|
|
||||||
d1l = len(diff1) if d1t == str else ""
|
|
||||||
d2l = len(diff2) if d2t == str else ""
|
|
||||||
# 'change' date is not significant for comparison
|
|
||||||
if path.endswith(".change"):
|
|
||||||
return ""
|
|
||||||
# the xml exporter edits the data base by converting media path
|
|
||||||
# to unix '/' conventions, so we have to ignore these differences
|
|
||||||
if path == "Media.path":
|
|
||||||
diff1 = diff1.replace('\\', '/')
|
|
||||||
if diff1 != diff2:
|
|
||||||
msg = " Diff on: %s\n %s%s: %s\n %s%s: %s\n" % \
|
|
||||||
(self.format_struct_path(path), d1t, d1l, desc1,
|
|
||||||
d2t, d2l, desc2)
|
|
||||||
return msg
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def report_diff(self, path, struct1, struct2):
|
|
||||||
"""
|
"""
|
||||||
Compare two struct objects and report differences.
|
Compare two struct objects and report differences.
|
||||||
"""
|
"""
|
||||||
@ -138,7 +95,7 @@ class CompleteCheck(unittest.TestCase):
|
|||||||
for pos in range(max(len1, len2)):
|
for pos in range(max(len1, len2)):
|
||||||
value1 = struct1[pos] if pos < len1 else None
|
value1 = struct1[pos] if pos < len1 else None
|
||||||
value2 = struct2[pos] if pos < len2 else None
|
value2 = struct2[pos] if pos < len2 else None
|
||||||
msg += self.report_diff(path + ("[%d]" % pos), value1, value2)
|
msg += self._report_diff(path + ("[%d]" % pos), value1, value2)
|
||||||
elif isinstance(struct1, dict) or isinstance(struct2, dict):
|
elif isinstance(struct1, dict) or isinstance(struct2, dict):
|
||||||
keys = struct1.keys() if isinstance(struct1, dict)\
|
keys = struct1.keys() if isinstance(struct1, dict)\
|
||||||
else struct2.keys()
|
else struct2.keys()
|
||||||
@ -146,40 +103,92 @@ class CompleteCheck(unittest.TestCase):
|
|||||||
value1 = struct1[key] if struct1 is not None else None
|
value1 = struct1[key] if struct1 is not None else None
|
||||||
value2 = struct2[key] if struct2 is not None else None
|
value2 = struct2[key] if struct2 is not None else None
|
||||||
if key == "dict": # a raw dict, not a struct
|
if key == "dict": # a raw dict, not a struct
|
||||||
msg += self.report_details(path, value1, value2)
|
msg += _report_details(path, value1, value2)
|
||||||
else:
|
else:
|
||||||
msg += self.report_diff(path + "." + key, value1, value2)
|
msg += self._report_diff(path + "." + key, value1, value2)
|
||||||
else:
|
else:
|
||||||
msg += self.report_details(path, struct1, struct2)
|
msg += _report_details(path, struct1, struct2)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
# The following make_test_function creates a test function (a method,
|
def _report_details(path, diff1, diff2):
|
||||||
# to be precise) that compares the import file with the expected
|
""" Checks if a detail is significant, needs adjusting for xml filter
|
||||||
# result '.gramps' file.
|
effects, and returns a string describing the specific difference."""
|
||||||
def make_tst_function(tstfile, fname):
|
if isinstance(diff1, bool):
|
||||||
|
desc1 = repr(diff1)
|
||||||
|
else:
|
||||||
|
desc1 = str(diff1) if diff1 else ""
|
||||||
|
if isinstance(diff2, bool):
|
||||||
|
desc2 = repr(diff2)
|
||||||
|
else:
|
||||||
|
desc2 = str(diff2) if diff2 else ""
|
||||||
|
d1t = type(diff1)
|
||||||
|
d2t = type(diff2)
|
||||||
|
# the xml exporter edits the data base by stripping spaces, so
|
||||||
|
# we have to ignore these differences
|
||||||
|
if d1t == str:
|
||||||
|
diff1 = diff1.strip()
|
||||||
|
if d2t == str:
|
||||||
|
diff2 = diff2.strip()
|
||||||
|
d1l = len(diff1) if d1t == str else ""
|
||||||
|
d2l = len(diff2) if d2t == str else ""
|
||||||
|
# 'change' date is not significant for comparison
|
||||||
|
if path.endswith(".change"):
|
||||||
|
return ""
|
||||||
|
# the xml exporter edits the data base by converting media path
|
||||||
|
# to unix '/' conventions, so we have to ignore these differences
|
||||||
|
if path == "Media.path":
|
||||||
|
diff1 = diff1.replace('\\', '/')
|
||||||
|
if diff1 != diff2:
|
||||||
|
msg = " Diff on: %s\n %s%s: %s\n %s%s: %s\n" % \
|
||||||
|
(_format_struct_path(path), d1t, d1l, desc1,
|
||||||
|
d2t, d2l, desc2)
|
||||||
|
return msg
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _format_struct_path(path):
|
||||||
|
""" prepares a 'path' string for the report out of the structure. """
|
||||||
|
retval = ""
|
||||||
|
parts = path.split(".")
|
||||||
|
for part in parts:
|
||||||
|
if retval:
|
||||||
|
retval += ", "
|
||||||
|
if "[" in part and "]" in part:
|
||||||
|
part, index = re.match(r"(.*)\[(\d*)\]", part).groups()
|
||||||
|
retval += "%s #%s" % (part.replace("_", " "), int(index) + 1)
|
||||||
|
else:
|
||||||
|
retval += part
|
||||||
|
return retval
|
||||||
|
|
||||||
|
|
||||||
|
def make_tst_function(tstfile, file_name):
|
||||||
|
""" This is here to support the dynamic function creation. This creates
|
||||||
|
the test function (a method, to be precise). """
|
||||||
def tst(self):
|
def tst(self):
|
||||||
self._user = user.User(quiet=True)
|
""" This compares the import file with the expected result '.gramps'
|
||||||
f1 = os.path.join(TEST_DIR, tstfile)
|
file. """
|
||||||
f2 = os.path.join(TEST_DIR, (fname + ".gramps"))
|
self.user = User(quiet=True)
|
||||||
fres = os.path.join(TEMP_DIR, (fname + ".difs"))
|
fn1 = os.path.join(TEST_DIR, tstfile)
|
||||||
|
fn2 = os.path.join(TEST_DIR, (file_name + ".gramps"))
|
||||||
|
fres = os.path.join(TEMP_DIR, (file_name + ".difs"))
|
||||||
try:
|
try:
|
||||||
os.remove(fres)
|
os.remove(fres)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
logging.info("\n**** %s ****" % tstfile)
|
logging.info("\n**** %s ****", tstfile)
|
||||||
set_det_id(True)
|
set_det_id(True)
|
||||||
self.database1 = import_as_dict(f1, self._user)
|
self.database1 = import_as_dict(fn1, self.user)
|
||||||
set_det_id(True)
|
set_det_id(True)
|
||||||
self.database2 = import_as_dict(f2, self._user)
|
self.database2 = import_as_dict(fn2, self.user)
|
||||||
self.assertIsNotNone(self.database1,
|
self.assertIsNotNone(self.database1,
|
||||||
"Unable to import file: %s" % f1)
|
"Unable to import file: %s" % fn1)
|
||||||
self.assertIsNotNone(self.database2,
|
self.assertIsNotNone(self.database2,
|
||||||
"Unable to import expected result file: %s" % f2)
|
"Unable to import expected result file: %s" % fn2)
|
||||||
if self.database2 is None or self.database1 is None:
|
if self.database2 is None or self.database1 is None:
|
||||||
return
|
return
|
||||||
diffs, added, missing = diff_dbs(self.database1,
|
diffs, added, missing = diff_dbs(self.database1,
|
||||||
self.database2, self._user)
|
self.database2, self.user)
|
||||||
self.msg = "Mismatch on file: %s\n" % tstfile
|
self.msg = "Mismatch on file: %s\n" % tstfile
|
||||||
deltas = self.prepare_result(diffs, added, missing)
|
deltas = self.prepare_result(diffs, added, missing)
|
||||||
# We save a copy of any issues in the users Gramps TEMP_DIR in a file
|
# We save a copy of any issues in the users Gramps TEMP_DIR in a file
|
||||||
@ -190,12 +199,12 @@ def make_tst_function(tstfile, fname):
|
|||||||
hres.write(self.msg)
|
hres.write(self.msg)
|
||||||
hres.close()
|
hres.close()
|
||||||
# let's see if we have any allowed exception file
|
# let's see if we have any allowed exception file
|
||||||
fdif = os.path.join(TEST_DIR, (fname + ".difs"))
|
fdif = os.path.join(TEST_DIR, (file_name + ".difs"))
|
||||||
try:
|
try:
|
||||||
hdif = open(fdif)
|
hdif = open(fdif)
|
||||||
msg = hdif.read()
|
msg = hdif.read()
|
||||||
hdif.close()
|
hdif.close()
|
||||||
except:
|
except (FileNotFoundError, IOError):
|
||||||
msg = ""
|
msg = ""
|
||||||
# if exception file matches exactly, we are done.
|
# if exception file matches exactly, we are done.
|
||||||
if self.msg != msg:
|
if self.msg != msg:
|
||||||
@ -205,30 +214,31 @@ def make_tst_function(tstfile, fname):
|
|||||||
# let's see if we have a single file to run, example;
|
# let's see if we have a single file to run, example;
|
||||||
# "python test_import.py -i sample.ged"
|
# "python test_import.py -i sample.ged"
|
||||||
# This only works for files in normal test directory, so don't add a path
|
# This only works for files in normal test directory, so don't add a path
|
||||||
tstfile = ""
|
#pylint: disable=invalid-name
|
||||||
|
_tstfile = ""
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
for i, option in enumerate(sys.argv):
|
for i, option in enumerate(sys.argv):
|
||||||
if option == '-i':
|
if option == '-i':
|
||||||
tstfile = sys.argv[i+1]
|
_tstfile = sys.argv[i+1]
|
||||||
del sys.argv[i]
|
del sys.argv[i]
|
||||||
del sys.argv[i]
|
del sys.argv[i]
|
||||||
# The following code dynamically creates the methods for each test file.
|
# The following code dynamically creates the methods for each test file.
|
||||||
# The methods are inserted at load time into the 'CompleteCheck' class
|
# The methods are inserted at load time into the 'CompleteCheck' class
|
||||||
# via the modules' globals, taking advantage that they are a dict.
|
# via the modules' globals, taking advantage that they are a dict.
|
||||||
if tstfile: # single file mode
|
if _tstfile: # single file mode
|
||||||
(fname, ext) = os.path.splitext(os.path.basename(tstfile))
|
(fname, ext) = os.path.splitext(os.path.basename(_tstfile))
|
||||||
test_func = make_tst_function(tstfile, fname)
|
test_func = make_tst_function(_tstfile, fname)
|
||||||
clname = 'Import_{0}'.format(tstfile)
|
clname = 'Import_{0}'.format(_tstfile)
|
||||||
globals()[clname] = type(clname,
|
globals()[clname] = type(clname,
|
||||||
(CompleteCheck,),
|
(CompleteCheck,),
|
||||||
{"testit": test_func})
|
{"testit": test_func})
|
||||||
else:
|
else:
|
||||||
for tstfile in os.listdir(TEST_DIR):
|
for _tstfile in os.listdir(TEST_DIR):
|
||||||
(fname, ext) = os.path.splitext(os.path.basename(tstfile))
|
(fname, ext) = os.path.splitext(os.path.basename(_tstfile))
|
||||||
if ext == ".gramps" or ext == ".difs" or ext == ".bak":
|
if ext == ".gramps" or ext == ".difs" or ext == ".bak":
|
||||||
continue
|
continue
|
||||||
test_func = make_tst_function(tstfile, fname)
|
test_func = make_tst_function(_tstfile, fname)
|
||||||
clname = 'Import_{0}'.format(tstfile)
|
clname = 'Import_{0}'.format(_tstfile)
|
||||||
globals()[clname] = type(clname,
|
globals()[clname] = type(clname,
|
||||||
(CompleteCheck,),
|
(CompleteCheck,),
|
||||||
{"testit": test_func})
|
{"testit": test_func})
|
||||||
|
Loading…
Reference in New Issue
Block a user