7327: friendlier diagnostics during parsing

In preparation for fixing the bug, discovered minor glitches
in the open/lock/close logic on error paths. Using the RAII syntax
for xml_file and removing redundant unlock-before-close.

The parse errors now have friendlier verbiage, give action suggestions,
and point to the actual file location for better usability and
maintainability.
This commit is contained in:
Vassilii Khachaturov 2013-12-26 19:39:40 +02:00
parent 5b17d597fe
commit aa3a3c8270

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2004-2007 Donald N. Allingham # Copyright (C) 2004-2007 Donald N. Allingham
# Copyright (C) 2013 Vassilii Khachaturov
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -18,8 +19,6 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# #
# $Id$
# Written by Alex Roitman # Written by Alex Roitman
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -40,7 +39,8 @@ try:
except: except:
use_lock = False use_lock = False
from .const import HOME_DIR from gramps.gen.const import HOME_DIR, GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -184,26 +184,23 @@ class RecentFiles(object):
""" """
Saves the current Gramps RecentFiles collection to the associated file. Saves the current Gramps RecentFiles collection to the associated file.
""" """
xml_file = open(os.path.expanduser(GRAMPS_FILENAME),'w') with open(os.path.expanduser(GRAMPS_FILENAME), 'w') as xml_file:
if use_lock:
if use_lock: fcntl.lockf(xml_file,fcntl.LOCK_EX)
fcntl.lockf(xml_file,fcntl.LOCK_EX) xml_file.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
xml_file.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n") xml_file.write('<RecentFiles>\n')
xml_file.write('<RecentFiles>\n') index = 0
index = 0 for item in self.gramps_recent_files:
for item in self.gramps_recent_files: index += 1
index += 1 if index > MAX_GRAMPS_ITEMS:
if index > MAX_GRAMPS_ITEMS: break
break xml_file.write(' <RecentItem>\n')
xml_file.write(' <RecentItem>\n') xml_file.write(' <Path><![CDATA[%s]]></Path>\n' % item.get_path())
xml_file.write(' <Path><![CDATA[%s]]></Path>\n' % item.get_path()) xml_file.write(' <Name><![CDATA[%s]]></Name>\n' % item.get_name())
xml_file.write(' <Name><![CDATA[%s]]></Name>\n' % item.get_name()) xml_file.write(' <Timestamp>%d</Timestamp>\n' % item.get_time())
xml_file.write(' <Timestamp>%d</Timestamp>\n' % item.get_time()) xml_file.write(' </RecentItem>\n')
xml_file.write(' </RecentItem>\n') xml_file.write('</RecentFiles>\n')
xml_file.write('</RecentFiles>\n') # all advisory locks on a file are released on close
if use_lock:
fcntl.lockf(xml_file,fcntl.LOCK_UN)
xml_file.close()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -218,36 +215,34 @@ class RecentParser(object):
def __init__(self): def __init__(self):
self.recent_files = [] self.recent_files = []
if not os.path.exists(os.path.expanduser(GRAMPS_FILENAME)): fname = os.path.expanduser(GRAMPS_FILENAME)
if not os.path.exists(fname):
return # it's the first time gramps has ever been run return # it's the first time gramps has ever been run
xml_file = None
# Python3's expat wants bytes, Python2's wants a string.
try: try:
if sys.version_info[0] < 3: # Python3's expat wants bytes, Python2's wants a string.
xml_file = open(os.path.expanduser(GRAMPS_FILENAME), "r") fmode = "r" if sys.version_info[0] < 3 else "rb"
else: with open(fname, fmode) as xml_file:
xml_file = open(os.path.expanduser(GRAMPS_FILENAME), "rb") if use_lock:
fcntl.lockf(xml_file,fcntl.LOCK_SH)
if use_lock: p = ParserCreate()
fcntl.lockf(xml_file,fcntl.LOCK_SH) p.StartElementHandler = self.startElement
p.EndElementHandler = self.endElement
p = ParserCreate() p.CharacterDataHandler = self.characters
p.StartElementHandler = self.startElement p.ParseFile(xml_file)
p.EndElementHandler = self.endElement # all advisory locks on a file are released on close
p.CharacterDataHandler = self.characters
p.ParseFile(xml_file)
if use_lock:
fcntl.lockf(xml_file,fcntl.LOCK_UN)
xml_file.close()
except IOError as err: except IOError as err:
logging.warning("Unable to open recent file %s because %s", logging.warning(
os.path.expanduser(GRAMPS_FILENAME), str(err)) _("Unable to open list of recent DBs file {fname}: {error}"
).format(fname=fname, error=err))
except Exception as err: except Exception as err:
logging.error("Recent file parse error %s", str(err)) logging.error(
if xml_file: _("Error parsing list of recent DBs from file {fname}: {error}.\n"
xml_file.close() "This might indicate a damage to your files.\n"
"If you're sure there is no problem with other files, "
"delete it, and restart Gramps."
).format(fname=fname, error=err))
def get(self): def get(self):
return self.recent_files return self.recent_files