GrampsLocale: Replace calls to sys.getfilesystemencoding

On MSWin and OSX, this call always returns the correct
value (utf-8 on OSX, 'mbcs' on MSWin), but on Linux the
return value is bizarrely dependent upon the environment.

Replace it with a GrampsLocale function which returns 'utf-8'
(the correct value for most Linux file systems) regardless of
the environment.

Also replace its use in print and write functions: It's the
encoding of paths in the filesystem, not of the files's content,
nor of the terminal's capabilities. The former is almost
always utf-8 as long as we write the file, the latter is
given by sys.stdout.encoding. Use the 'backslashreplace' error
handler to avoid exceptions when we need to output unicode
text to an ASCII terminal.

svn: r21146
This commit is contained in:
John Ralls 2013-01-17 19:47:36 +00:00
parent ef7e047b4b
commit a58ef2b73f
16 changed files with 54 additions and 123 deletions

View File

@ -186,9 +186,9 @@ class ArgHandler(object):
else:
# Need to convert to system file encoding before printing
# For non latin characters in path/file/user names
print(msg1.encode(sys.getfilesystemencoding()), file=sys.stderr)
print(msg1.encode(sys.stdout.encoding, 'backslashreplace'), file=sys.stderr)
if msg2 is not None:
print(msg2.encode(sys.getfilesystemencoding()), file=sys.stderr)
print(msg2.encode(sys.stdout.encoding, 'backslashreplace'), file=sys.stderr)
#-------------------------------------------------------------------------
# Argument parser: sorts out given arguments
@ -295,7 +295,7 @@ class ArgHandler(object):
else:
ask = input
ans = ask(_('OK to overwrite? (yes/no) ') \
.encode(sys.getfilesystemencoding()))
.encode(sys.stdout.encoding, 'backslashreplace'))
except EOFError:
print()
sys.exit(0)
@ -409,26 +409,26 @@ class ArgHandler(object):
if self.list:
print(_('List of known family trees in your database path\n').\
encode(sys.getfilesystemencoding()))
encode(sys.stdout.encoding, 'backslashreplace'))
for name, dirname in sorted(self.dbman.family_tree_list(),
key=lambda pair: pair[0].lower()):
print((_("%(full_DB_path)s with name \"%(f_t_name)s\"") % \
{'full_DB_path' : dirname,
'f_t_name' : name}).encode(sys.getfilesystemencoding()))
'f_t_name' : name}).encode(sys.stdout.encoding, 'backslashreplace'))
sys.exit(0)
if self.list_more:
print(_('Gramps Family Trees:').encode(sys.getfilesystemencoding()))
print(_('Gramps Family Trees:').encode(sys.stdout.encoding, 'backslashreplace'))
summary_list = self.dbman.family_tree_summary()
for summary in sorted(summary_list,
key=lambda sum: sum["Family tree"].lower()):
print(_("Family Tree \"%s\":").\
encode(sys.getfilesystemencoding()) % summary["Family tree"])
encode(sys.stdout.encoding, 'backslashreplace') % summary["Family tree"])
for item in sorted(summary):
if item != "Family tree":
print((" %s: %s" % (item, summary[item])).\
encode(sys.getfilesystemencoding()))
encode(sys.stdout.encoding, 'backslashreplace'))
sys.exit(0)
self.__open_action()
@ -443,7 +443,7 @@ class ArgHandler(object):
for expt in self.exports:
# Need to convert path/filename to str before printing
# For non latin characters in Windows path/file/user names
fn = expt[0].encode(sys.getfilesystemencoding())
fn = expt[0].encode(sys.stdout.encoding, 'backslashreplace')
fmt = str(expt[1])
print(_("Exporting: file %(filename)s, "
"format %(format)s.") % \
@ -481,7 +481,7 @@ class ArgHandler(object):
self.imp_db_path, title = self.dbman.create_new_db_cli()
else:
self.imp_db_path = get_empty_tempdir("import_dbdir") \
.encode(sys.getfilesystemencoding())
.encode(sys.stdout.encoding, 'backslashreplace')
newdb = DbBsddb()
newdb.write_version(self.imp_db_path)
@ -495,7 +495,7 @@ class ArgHandler(object):
sys.exit(0)
for imp in self.imports:
fn = imp[0].encode(sys.getfilesystemencoding())
fn = imp[0].encode(sys.stdout.encoding, 'backslashreplace')
fmt = str(imp[1])
msg = _("Importing: file %(filename)s, format %(format)s.") % \
{'filename' : fn, 'format' : fmt}
@ -624,10 +624,10 @@ class ArgHandler(object):
# Print cli report name ([item[0]), GUI report name (item[4])
if len(pdata.id) <= 25:
print(" %s%s- %s" % ( pdata.id, " " * (26 - len(pdata.id)),
pdata.name.encode(sys.getfilesystemencoding())), file=sys.stderr)
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
else:
print(" %s\t- %s" % (pdata.id,
pdata.name.encode(sys.getfilesystemencoding())), file=sys.stderr)
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
elif action == "tool":
from gramps.gui.plug import tool
@ -665,10 +665,10 @@ class ArgHandler(object):
# Print cli report name ([item[0]), GUI report name (item[4])
if len(pdata.id) <= 25:
print(" %s%s- %s" % ( pdata.id, " " * (26 - len(pdata.id)),
pdata.name.encode(sys.getfilesystemencoding())), file=sys.stderr)
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
else:
print(" %s\t- %s" % (pdata.id,
pdata.name.encode(sys.getfilesystemencoding())), file=sys.stderr)
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
elif action == "book":
try:

View File

@ -293,7 +293,7 @@ class ArgParser(object):
self.list_more = True
elif option in ('-s','--show'):
print ("Gramps config settings from %s:" % \
config.filename.encode(sys.getfilesystemencoding()))
config.filename.encode(sys.stdout.encoding, 'backslashreplace'))
for section in config.data:
for setting in config.data[section]:
print ("%s.%s=%s" % (
@ -403,7 +403,7 @@ class ArgParser(object):
"""
if self.help:
# Convert Help messages to file system encoding before printing
print (_HELP.encode(sys.getfilesystemencoding()))
print (_HELP.encode(sys.stdout.encoding, 'backslashreplace'))
sys.exit(0)
def print_usage(self):
@ -412,5 +412,5 @@ class ArgParser(object):
"""
if self.usage:
# Convert Help messages to file system encoding before printing
print (_USAGE.encode(sys.getfilesystemencoding()))
print (_USAGE.encode(sys.stdout.encoding, 'backslashreplace'))
sys.exit(0)

View File

@ -192,7 +192,7 @@ class CLIDbManager(object):
retval["Locked?"] = "no"
retval["DB version"] = version
if sys.version_info[0] < 3:
retval["Family tree"] = name.encode(sys.getfilesystemencoding())
retval["Family tree"] = name.encode(glocale.getfilesystemencoding())
else:
retval["Family tree"] = name
retval["Path"] = dirpath
@ -207,7 +207,7 @@ class CLIDbManager(object):
# make the default directory if it does not exist
dbdir = os.path.expanduser(config.get('behavior.database-path'))
if sys.version_info[0] < 3:
dbdir = dbdir.encode(sys.getfilesystemencoding())
dbdir = dbdir.encode(glocale.getfilesystemencoding())
db_ok = make_dbdir(dbdir)
self.current_names = []
@ -414,7 +414,7 @@ def make_dbdir(dbdir):
if not os.path.isdir(dbdir):
os.makedirs(dbdir)
except (IOError, OSError) as msg:
msg = conv_to_unicode(str(msg), sys.getfilesystemencoding())
msg = conv_to_unicode(str(msg), glocale.getfilesystemencoding())
LOG.error(_("\nERROR: Wrong database path in Edit Menu->Preferences.\n"
"Open preferences and set correct database path.\n\n"
"Details: Could not make database directory:\n %s\n\n") % msg)
@ -443,7 +443,7 @@ def find_next_db_dir():
base = "%x" % int(time.time())
dbdir = os.path.expanduser(config.get('behavior.database-path'))
if sys.version_info[0] < 3:
dbdir = dbdir.encode(sys.getfilesystemencoding())
dbdir = dbdir.encode(glocale.getfilesystemencoding())
new_path = os.path.join(dbdir, base)
if not os.path.isdir(new_path):
break
@ -486,7 +486,7 @@ def find_locker_name(dirpath):
# Convert username to unicode according to system encoding
# Otherwise problems with non ASCII characters in
# username in Windows
username = conv_to_unicode(username, sys.getfilesystemencoding())
username = conv_to_unicode(username, glocale.getfilesystemencoding())
# feature request 2356: avoid genitive form
last = _("Locked by %s") % username
ifile.close()

View File

@ -297,10 +297,10 @@ def startcli(errors, argparser):
#already errors encountered. Show first one on terminal and exit
# Convert error message to file system encoding before print
errmsg = _('Error encountered: %s') % errors[0][0]
errmsg = errmsg.encode(sys.getfilesystemencoding())
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
print(errmsg)
errmsg = _(' Details: %s') % errors[0][1]
errmsg = errmsg.encode(sys.getfilesystemencoding())
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
print(errmsg)
sys.exit(1)
@ -308,10 +308,10 @@ def startcli(errors, argparser):
# Convert error message to file system encoding before print
errmsg = _('Error encountered in argument parsing: %s') \
% argparser.errors[0][0]
errmsg = errmsg.encode(sys.getfilesystemencoding())
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
print(errmsg)
errmsg = _(' Details: %s') % argparser.errors[0][1]
errmsg = errmsg.encode(sys.getfilesystemencoding())
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
print(errmsg)
sys.exit(1)

View File

@ -571,11 +571,11 @@ class CommandLineReport(object):
# Make the output nicer to read, assume a tab has 8 spaces
tabs = '\t\t' if len(key) < 10 else '\t'
optmsg = " %s%s%s (%s)" % (key, tabs, opt[1], opt[0])
print(optmsg.encode(sys.getfilesystemencoding()))
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
else:
optmsg = " %s%s%s" % (key, tabs,
_('(no help available)'))
print(optmsg.encode(sys.getfilesystemencoding()))
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
print((_(" Use '%(donottranslate)s' to see description "
"and acceptable values") %
{'donottranslate' : "show=option"}))
@ -588,10 +588,10 @@ class CommandLineReport(object):
if isinstance(vals, (list, tuple)):
for val in vals:
optmsg = " %s" % val
print(optmsg.encode(sys.getfilesystemencoding()))
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
else:
optmsg = " %s" % opt[2]
print(optmsg.encode(sys.getfilesystemencoding()))
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
else:
#there was a show option given, but the option is invalid

View File

@ -1091,7 +1091,7 @@ class PluginRegister(object):
lenpd = len(self.__plugindata)
full_filename = os.path.join(dir, filename)
if sys.version_info[0] < 3:
full_filename = full_filename.encode(sys.getfilesystemencoding())
full_filename = full_filename.encode(glocale.getfilesystemencoding())
local_gettext = glocale.get_addon_translator(full_filename).gettext
try:
#execfile(full_filename,

View File

@ -658,7 +658,7 @@ class GVPsDoc(GVDocBase):
# :cairo does not work with Graphviz 2.26.3 and later See issue 4164
# Covert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -706,7 +706,7 @@ class GVSvgDoc(GVDocBase):
dotfile.close()
# Covert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -749,7 +749,7 @@ class GVSvgzDoc(GVDocBase):
dotfile.close()
# Covert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -792,7 +792,7 @@ class GVPngDoc(GVDocBase):
dotfile.close()
# Covert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -835,7 +835,7 @@ class GVJpegDoc(GVDocBase):
dotfile.close()
# Covert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -878,7 +878,7 @@ class GVGifDoc(GVDocBase):
dotfile.close()
# Covert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -924,7 +924,7 @@ class GVPdfGvDoc(GVDocBase):
dotfile.close()
# Convert filename to str using file system encoding.
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
@ -989,7 +989,7 @@ class GVPdfGsDoc(GVDocBase):
# Convert to PDF using ghostscript
if sys.version_info[0] < 3:
fname = self._filename.encode(sys.getfilesystemencoding())
fname = self._filename.encode(glocale.getfilesystemencoding())
else:
fname = self._filename
command = '%s -q -sDEVICE=pdfwrite -dNOPAUSE -dDEVICEWIDTHPOINTS=%d' \

View File

@ -338,73 +338,6 @@ class GrampsLocale(object):
return "utf-8"
#-------------------------------------------------------------------------
#
# GrampsTranslation Class
#
#-------------------------------------------------------------------------
class GrampsTranslations(gettext.GNUTranslations):
"""
Overrides and extends gettext.GNUTranslations. See the Python gettext
"Class API" documentation for how to use this.
"""
def language(self):
"""
Return the target languge of this translations object.
"""
return self.info()["language"]
def gettext(self, msgid):
"""
Obtain translation of gettext, return a unicode object
:param msgid: The string to translated.
:type msgid: unicode
:returns: Translation or the original.
:rtype: unicode
"""
# If msgid =="" then gettext will return po file header
# and that's not what we want.
if len(msgid.strip()) == 0:
return msgid
if sys.version_info[0] < 3:
return gettext.GNUTranslations.ugettext(self, msgid)
else:
return gettext.GNUTranslations.gettext(self, msgid)
def ngettext(self, singular, plural, num):
"""
The translation of singular/plural is returned unless the translation is
not available and the singular contains the separator. In that case,
the returned value is the singular.
:param singular: The singular form of the string to be translated.
may contain a context seperator
:type singular: unicode
:param plural: The plural form of the string to be translated.
:type plural: unicode
:param num: the amount for which to decide the translation
:type num: int
:returns: Translation or the original.
:rtype: unicode
"""
if sys.version_info[0] < 3:
return gettext.GNUTranslations.ungettext(self, singular,
plural, num)
else:
return gettext.GNUTranslations.ngettext(self, singular,
plural, num)
def sgettext(self, msgid, sep='|'):
"""
Even with a null translator we need to filter out the translator hint.
"""
msgval = self.gettext(msgid)
if msgval == msgid:
sep_idx = msgid.rfind(sep)
msgval = msgid[sep_idx+1:]
return msgval
#-------------------------------------------------------------------------
#
# Translations Classes
@ -483,7 +416,6 @@ class GrampsTranslations(gettext.GNUTranslations):
msgval = msgid[sep_idx+1:]
return msgval
class GrampsNullTranslations(gettext.NullTranslations):
"""
Extends gettext.NullTranslations to provide the sgettext method.

View File

@ -193,7 +193,7 @@ class ErrorDialog(Gtk.MessageDialog):
class RunDatabaseRepair(ErrorDialog):
def __init__(self, msg, parent=None):
if sys.version_info[0] < 3:
msg = cuni(str(msg).decode(sys.getfilesystemencoding()))
msg = cuni(str(msg).decode(glocale.getfilesystemencoding()))
else:
msg = str(msg)
ErrorDialog.__init__(
@ -208,7 +208,7 @@ class RunDatabaseRepair(ErrorDialog):
class DBErrorDialog(ErrorDialog):
def __init__(self, msg, parent=None):
if sys.version_info[0] < 3:
msg = cuni(str(msg).decode(sys.getfilesystemencoding()))
msg = cuni(str(msg).decode(glocale.getfilesystemencoding()))
else:
msg = str(msg)
ErrorDialog.__init__(

View File

@ -520,7 +520,7 @@ class GalleryTab(ButtonTab, DbGUIElement):
if protocol == "file":
name = fix_encoding(mfile)
name = cuni(url2pathname(
name.encode(sys.getfilesystemencoding())))
name.encode(glocale.getfilesystemencoding())))
mime = get_type(name)
if not is_valid_type(mime):
return

View File

@ -1365,7 +1365,7 @@ class ViewManager(CLIManager):
if value:
(filename, title) = value
if sys.version_info[0] < 3:
filename = filename.encode(sys.getfilesystemencoding())
filename = filename.encode(glocale.getfilesystemencoding())
self.db_loader.read_file(filename)
self._post_load_newdb(filename, 'x-directory/normal', title)
@ -1567,7 +1567,7 @@ class ViewManager(CLIManager):
basefile = file_entry.get_text()
basefile = basefile.replace("/", r"-")
filename = os.path.join(path_entry.get_text(), basefile)
filename = filename.encode(sys.getfilesystemencoding())
filename = filename.encode(glocale.getfilesystemencoding())
if os.path.exists(filename):
sfilename = get_unicode_path_from_env_var(filename)
question = QuestionDialog2(

View File

@ -89,7 +89,7 @@ class PdfDoc(libcairodoc.CairoDoc):
# create cairo context and pango layout
filename = self._backend.filename
if sys.version_info[0] < 3:
filename = filename.encode(sys.getfilesystemencoding())
filename = self._backend.filename.encode(glocale.getfilesystemencoding())
try:
surface = cairo.PDFSurface(filename, paper_width, paper_height)
except IOError as msg:

View File

@ -153,13 +153,13 @@ class GeoGraphyView(OsmGps, NavigationView):
('gramps-geo-mainmap' + '.png' ))
pathu = path
if sys.version_info[0] < 3:
pathu = path.encode(sys.getfilesystemencoding())
pathu = path.encode(glocale.getfilesystemencoding())
self.geo_mainmap = cairo.ImageSurface.create_from_png(pathu)
path = os.path.join(ROOT_DIR, "images", "48x48",
('gramps-geo-altmap' + '.png' ))
pathu = path
if sys.version_info[0] < 3:
pathu = path.encode(sys.getfilesystemencoding())
pathu = path.encode(glocale.getfilesystemencoding())
self.geo_altmap = cairo.ImageSurface.create_from_png(pathu)
if ( config.get('geography.map_service') in
( constants.OPENSTREETMAP,
@ -176,7 +176,7 @@ class GeoGraphyView(OsmGps, NavigationView):
(constants.ICONS.get(int(ident), default_image) + '.png' ))
pathu = path
if sys.version_info[0] < 3:
pathu = path.encode(sys.getfilesystemencoding())
pathu = path.encode(glocale.getfilesystemencoding())
self.geo_othermap[ident] = cairo.ImageSurface.create_from_png(pathu)
def change_page(self):

View File

@ -690,8 +690,8 @@ class CheckIntegrity(object):
photo_desc = obj.get_description()
if photo_name is not None and photo_name != "" and not find_file(photo_name):
if cl:
# Convert to file system encoding before prining
fn = os.path.basename(photo_name).encode(sys.getfilesystemencoding())
# Convert to stdout encoding before prining
fn = os.path.basename(photo_name).encode(sys.stdout.encoding, 'backslashreplace')
logging.warning(" FAIL: media file %s was not found." %
fn)
self.bad_photo.append(ObjectId)
@ -2195,8 +2195,7 @@ class Report(ManagedWindow):
def __init__(self, uistate, text, cl=0):
if cl:
# Convert to file system encoding before printing
print (text.encode(sys.getfilesystemencoding()))
print (text.encode(sys.stdout.encoding, 'backslashreplace'))
return
ManagedWindow.__init__(self, uistate, [], self)

View File

@ -196,7 +196,7 @@ class MediaView(ListView):
protocol, site, mfile, j, k, l = urlparse(clean_string)
if protocol == "file":
name = cuni(url2pathname(
mfile.encode(sys.getfilesystemencoding())))
mfile.encode(glocale.getfilesystemencoding())))
mime = get_type(name)
if not is_valid_type(mime):
return

View File

@ -209,7 +209,7 @@ class PersonBoxWidgetCairo(_PersonWidgetBase):
if image:
image_path = self.get_image(dbstate, person)
if sys.version_info[0] < 3 and isinstance(image_path, STRTYPE):
image_path = image_path.encode(sys.getfilesystemencoding())
image_path = image_path.encode(glocale.getfilesystemencoding())
if image_path and os.path.exists(image_path):
self.img_surf = cairo.ImageSurface.create_from_png(image_path)