gramps/src/Utils.py
2009-06-24 21:56:07 +00:00

908 lines
32 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
#
# 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
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
import os
import sys
import locale
import random
import time
from TransUtils import sgettext as _
#-------------------------------------------------------------------------
#
# GNOME/GTK
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from BasicUtils import name_displayer
import gen.lib
import Errors
from QuestionDialog import WarningDialog, ErrorDialog
from const import TEMP_DIR, USER_HOME
import shutil
#-------------------------------------------------------------------------
#
# Constants from config .ini keys
#
#-------------------------------------------------------------------------
#obtain the values once, they do not change!
try:
import Config
_MAX_AGE_PROB_ALIVE = Config.get(Config.MAX_AGE_PROB_ALIVE)
_MAX_SIB_AGE_DIFF = Config.get(Config.MAX_SIB_AGE_DIFF)
_MIN_GENERATION_YEARS = Config.get(Config.MIN_GENERATION_YEARS)
_AVG_GENERATION_GAP = Config.get(Config.AVG_GENERATION_GAP)
except ImportError:
# Utils used as module not part of GRAMPS
_MAX_AGE_PROB_ALIVE = 110
_MAX_SIB_AGE_DIFF = 20
_MIN_GENERATION_YEARS = 13
_AVG_GENERATION_GAP = 20
#-------------------------------------------------------------------------
#
# Integer to String mappings for constants
#
#-------------------------------------------------------------------------
gender = {
gen.lib.Person.MALE : _("male"),
gen.lib.Person.FEMALE : _("female"),
gen.lib.Person.UNKNOWN : _("unknown"),
}
def format_gender( type):
return gender.get(type[0], _("Invalid"))
confidence = {
gen.lib.SourceRef.CONF_VERY_HIGH : _("Very High"),
gen.lib.SourceRef.CONF_HIGH : _("High"),
gen.lib.SourceRef.CONF_NORMAL : _("Normal"),
gen.lib.SourceRef.CONF_LOW : _("Low"),
gen.lib.SourceRef.CONF_VERY_LOW : _("Very Low"),
}
family_rel_descriptions = {
gen.lib.FamilyRelType.MARRIED : _("A legal or common-law relationship "
"between a husband and wife"),
gen.lib.FamilyRelType.UNMARRIED : _("No legal or common-law relationship "
"between man and woman"),
gen.lib.FamilyRelType.CIVIL_UNION : _("An established relationship between "
"members of the same sex"),
gen.lib.FamilyRelType.UNKNOWN : _("Unknown relationship between a man "
"and woman"),
gen.lib.FamilyRelType.CUSTOM : _("An unspecified relationship between "
"a man and woman"),
}
#-------------------------------------------------------------------------
#
# modified flag
#
#-------------------------------------------------------------------------
_history_brokenFlag = 0
def history_broken():
global _history_brokenFlag
_history_brokenFlag = 1
data_recover_msg = _('The data can only be recovered by Undo operation '
'or by quitting with abandoning changes.')
def fix_encoding(value):
if not isinstance(value, unicode):
try:
return unicode(value)
except:
try:
codeset = locale.getpreferredencoding()
except:
codeset = "UTF-8"
return unicode(value, codeset)
else:
return value
def xml_lang():
loc = locale.getlocale()
if loc[0] is None:
return ""
else:
return loc[0].replace('_', '-')
#-------------------------------------------------------------------------
#
# force_unicode
#
#-------------------------------------------------------------------------
def force_unicode(n):
if not isinstance(n, unicode):
return (unicode(n).lower(), unicode(n))
else:
return (n.lower(), n)
#-------------------------------------------------------------------------
#
# Clears the modified flag. Should be called after data is saved.
#
#-------------------------------------------------------------------------
def clearHistory_broken():
global _history_brokenFlag
_history_brokenFlag = 0
def wasHistory_broken():
return _history_brokenFlag
#-------------------------------------------------------------------------
#
# Short hand function to return either the person's name, or an empty
# string if the person is None
#
#-------------------------------------------------------------------------
def family_name(family, db, noname=_("unknown")):
"""Builds a name for the family from the parents names"""
father_handle = family.get_father_handle()
mother_handle = family.get_mother_handle()
father = db.get_person_from_handle(father_handle)
mother = db.get_person_from_handle(mother_handle)
if father and mother:
fname = name_displayer.display(father)
mname = name_displayer.display(mother)
name = _("%(father)s and %(mother)s") % {
"father" : fname,
"mother" : mname}
elif father:
name = name_displayer.display(father)
elif mother:
name = name_displayer.display(mother)
else:
name = noname
return name
def family_upper_name(family, db):
"""Builds a name for the family from the parents names"""
father_handle = family.get_father_handle()
mother_handle = family.get_mother_handle()
father = db.get_person_from_handle(father_handle)
mother = db.get_person_from_handle(mother_handle)
if father and mother:
fname = father.get_primary_name().get_upper_name()
mname = mother.get_primary_name().get_upper_name()
name = _("%(father)s and %(mother)s") % {
'father' : fname,
'mother' : mname
}
elif father:
name = father.get_primary_name().get_upper_name()
else:
name = mother.get_primary_name().get_upper_name()
return name
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def find_file( filename):
# try the filename we got
try:
fname = filename
if os.path.isfile( filename):
return( filename)
except:
pass
# Build list of alternate encodings
encodings = set()
for enc in [sys.getfilesystemencoding, locale.getpreferredencoding]:
try:
encodings.add(enc)
except:
pass
encodings.add('UTF-8')
encodings.add('ISO-8859-1')
for enc in encodings:
try:
fname = filename.encode(enc)
if os.path.isfile( fname):
return fname
except:
pass
# not found
return ''
def find_folder( filename):
# try the filename we got
try:
fname = filename
if os.path.isdir( filename):
return( filename)
except:
pass
# Build list of elternate encodings
try:
encodings = [sys.getfilesystemencoding(),
locale.getpreferredencoding(),
'UTF-8', 'ISO-8859-1']
except:
encodings = [sys.getfilesystemencoding(), 'UTF-8', 'ISO-8859-1']
encodings = list(set(encodings))
for enc in encodings:
try:
fname = filename.encode(enc)
if os.path.isdir( fname):
return fname
except:
pass
# not found
return ''
def get_unicode_path(path):
"""
Return the Unicode version of a path string.
:type path: str
:param path: The path to be converted to Unicode
:rtype: unicode
:returns: The Unicode version of path.
"""
if os.sys.platform == "win32":
return unicode(path)
else:
return unicode(path,sys.getfilesystemencoding())
#-------------------------------------------------------------------------
#
# Iterate over ancestors.
#
#-------------------------------------------------------------------------
def for_each_ancestor(db, start, func, data):
"""
Recursively iterate (breadth-first) over ancestors of
people listed in start.
Call func(data, pid) for the Id of each person encountered.
Exit and return 1, as soon as func returns true.
Return 0 otherwise.
"""
todo = start
done_ids = set()
while len(todo):
p_handle = todo.pop()
p = db.get_person_from_handle(p_handle)
# Don't process the same handle twice. This can happen
# if there is a cycle in the database, or if the
# initial list contains X and some of X's ancestors.
if p_handle in done_ids:
continue
done_ids.add(p_handle)
if func(data, p_handle):
return 1
for fam_handle in p.get_parent_family_handle_list():
fam = db.get_family_from_handle(fam_handle)
if fam:
f_handle = fam.get_father_handle()
m_handle = fam.get_mother_handle()
if f_handle: todo.append(f_handle)
if m_handle: todo.append(m_handle)
return 0
def title(n):
return '<span weight="bold" size="larger">%s</span>' % n
def set_title_label(xmlobj, t):
title_label = xmlobj.get_widget('title')
title_label.set_text('<span weight="bold" size="larger">%s</span>' % t)
title_label.set_use_markup(True)
from warnings import warn
def set_titles(window, title, t, msg=None):
warn('The Utils.set_titles is deprecated. Use ManagedWindow methods')
def search_for(name):
if name.startswith( '"' ):
name = name.split('"')[1]
else:
name = name.split()[0]
if os.sys.platform == "win32":
for i in os.environ['PATH'].split(';'):
fname = os.path.join(i, name)
if os.access(fname, os.X_OK) and not os.path.isdir(fname):
return 1
else:
for i in os.environ['PATH'].split(':'):
fname = os.path.join(i, name)
if os.access(fname, os.X_OK) and not os.path.isdir(fname):
return 1
return 0
#-------------------------------------------------------------------------
#
# create_id
#
#-------------------------------------------------------------------------
rand = random.Random(time.time())
def create_id():
return "%08x%08x" % ( int(time.time()*10000),
rand.randint(0, sys.maxint))
#-------------------------------------------------------------------------
#
# probably_alive
#
#-------------------------------------------------------------------------
def probably_alive(person, db, current_date=None, limit=0):
"""Return true if the person may be alive on current_date.
This works by a process of emlimination. If we can't find a good
reason to believe that someone is dead then we assume they must
be alive.
:param current_date: a date object that is not estimated or modified
(defaults to today)
:param limit: number of years to check beyond death_date
"""
if current_date is None:
current_date = gen.lib.Date()
# yr, mon, day:
current_date.set_yr_mon_day(*time.localtime(time.time())[0:3])
death_date = None
# If the recorded death year is before current year then
# things are simple.
death_ref = person.get_death_ref()
if death_ref and death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
death = db.get_event_from_handle(death_ref.ref)
if death.get_date_object().get_start_date() != gen.lib.Date.EMPTY:
death_date = death.get_date_object()
if death_date.copy_offset_ymd(year=limit).match(current_date, "<<"):
return False
# Look for Cause Of Death, Burial or Cremation events.
# These are fairly good indications that someone's not alive.
for ev_ref in person.get_primary_event_ref_list():
ev = db.get_event_from_handle(ev_ref.ref)
if ev and ev.type in [gen.lib.EventType.CAUSE_DEATH,
gen.lib.EventType.BURIAL,
gen.lib.EventType.CREMATION]:
if not death_date:
death_date = ev.get_date_object()
if ev.get_date_object().get_start_date() != gen.lib.Date.EMPTY:
if ev.get_date_object().copy_offset_ymd(year=limit).match(current_date,"<<"):
return False
# For any other event of this person, check whether it happened
# too long ago. If so then the person is likely dead now.
elif ev and too_old(ev.get_date_object(), current_date.get_year()):
return False
birth_date = None
# If they were born within 100 years before current year then
# assume they are alive (we already know they are not dead).
birth_ref = person.get_birth_ref()
if birth_ref and birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
birth = db.get_event_from_handle(birth_ref.ref)
if (birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY):
if not birth_date:
birth_date = birth.get_date_object()
# Check whether the birth event is too old because the
# code above did not look at birth, only at other events
birth_obj = birth.get_date_object()
if birth_obj.get_valid():
# only if this is a valid birth:
if too_old(birth_obj, current_date.get_year()):
return False
if not_too_old(birth_obj, current_date.get_year()):
return True
if not birth_date and death_date:
if death_date.match(current_date.copy_offset_ymd(year=_MAX_AGE_PROB_ALIVE), ">>"):
# person died more than MAX after current year
return False
# Neither birth nor death events are available. Try looking
# at siblings. If a sibling was born more than 120 years past,
# or more than 20 future, then probably this person is
# not alive. If the sibling died more than 120 years
# past, or more than 120 years future, then probably not alive.
family_list = person.get_parent_family_handle_list()
for family_handle in family_list:
family = db.get_family_from_handle(family_handle)
for child_ref in family.get_child_ref_list():
child_handle = child_ref.ref
child = db.get_person_from_handle(child_handle)
child_birth_ref = child.get_birth_ref()
if child_birth_ref:
child_birth = db.get_event_from_handle(child_birth_ref.ref)
dobj = child_birth.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
# if sibling birth date too far away, then not alive:
year = dobj.get_year()
if year != 0:
if not (current_date.copy_offset_ymd(-(_MAX_AGE_PROB_ALIVE + _MAX_SIB_AGE_DIFF)).match(dobj,"<<") and
dobj.match(current_date.copy_offset_ymd(_MAX_SIB_AGE_DIFF),"<<")):
return False
child_death_ref = child.get_death_ref()
if child_death_ref:
child_death = db.get_event_from_handle(child_death_ref.ref)
dobj = child_death.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
# if sibling death date too far away, then not alive:
year = dobj.get_year()
if year != 0:
if not (current_date.copy_offset_ymd(-(_MAX_AGE_PROB_ALIVE + _MAX_SIB_AGE_DIFF)).match(dobj,"<<") and
dobj.match(current_date.copy_offset_ymd(_MAX_AGE_PROB_ALIVE),"<<")):
return False
# Try looking for descendants that were born more than a lifespan
# ago.
def descendants_too_old (person, years):
for family_handle in person.get_family_handle_list():
family = db.get_family_from_handle(family_handle)
for child_ref in family.get_child_ref_list():
child_handle = child_ref.ref
child = db.get_person_from_handle(child_handle)
child_birth_ref = child.get_birth_ref()
if child_birth_ref:
child_birth = db.get_event_from_handle(child_birth_ref.ref)
dobj = child_birth.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
d = gen.lib.Date(dobj)
val = d.get_start_date()
val = d.get_year() - years
d.set_year(val)
if not not_too_old (d, current_date.get_year()):
return True
child_death_ref = child.get_death_ref()
if child_death_ref:
child_death = db.get_event_from_handle(child_death_ref.ref)
dobj = child_death.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
if not not_too_old (dobj, current_date.get_year()):
return True
if descendants_too_old (child, years + _MIN_GENERATION_YEARS):
return True
return False
# If there are descendants that are too old for the person to have
# been alive in the current year then they must be dead.
try:
if descendants_too_old(person, _MIN_GENERATION_YEARS):
return False
except RuntimeError:
raise Errors.DatabaseError(
_("Database error: %s is defined as his or her own ancestor") %
name_displayer.display(person))
def ancestors_too_old(person, year):
family_handle = person.get_main_parents_family_handle()
if family_handle:
family = db.get_family_from_handle(family_handle)
father_handle = family.get_father_handle()
if father_handle:
father = db.get_person_from_handle(father_handle)
father_birth_ref = father.get_birth_ref()
if father_birth_ref and father_birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
father_birth = db.get_event_from_handle(
father_birth_ref.ref)
dobj = father_birth.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
if not not_too_old (dobj, year - _AVG_GENERATION_GAP):
return True
father_death_ref = father.get_death_ref()
if father_death_ref and father_death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
father_death = db.get_event_from_handle(
father_death_ref.ref)
dobj = father_death.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
if dobj.get_year() < year - _AVG_GENERATION_GAP:
return True
if ancestors_too_old (father, year - _AVG_GENERATION_GAP):
return True
mother_handle = family.get_mother_handle()
if mother_handle:
mother = db.get_person_from_handle(mother_handle)
mother_birth_ref = mother.get_birth_ref()
if mother_birth_ref and mother_birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
mother_birth = db.get_event_from_handle(mother_birth_ref.ref)
dobj = mother_birth.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
if not not_too_old (dobj, year - _AVG_GENERATION_GAP):
return True
mother_death_ref = mother.get_death_ref()
if mother_death_ref and mother_death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
mother_death = db.get_event_from_handle(
mother_death_ref.ref)
dobj = mother_death.get_date_object()
if dobj.get_start_date() != gen.lib.Date.EMPTY:
if dobj.get_year() < year - _AVG_GENERATION_GAP:
return True
if ancestors_too_old (mother, year - _AVG_GENERATION_GAP):
return True
return False
# If there are ancestors that would be too old in the current year
# then assume our person must be dead too.
if ancestors_too_old (person, current_date.get_year()):
return False
# If we can't find any reason to believe that they are dead we
# must assume they are alive.
return True
def not_too_old(date, current_year=None):
if not current_year:
time_struct = time.localtime(time.time())
current_year = time_struct[0]
year = date.get_year()
if year > current_year:
return False
return (year != 0 and current_year - year < _MAX_AGE_PROB_ALIVE)
def too_old(date, current_year=None):
if current_year:
the_current_year = current_year
else:
time_struct = time.localtime(time.time())
the_current_year = time_struct[0]
year = date.get_year()
if year > the_current_year:
return True
return (year != 0 and the_current_year - year > _MAX_AGE_PROB_ALIVE)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_referents(handle, db, primary_objects):
""" Find objects that refer to an object.
This function is the base for other get_<object>_referents finctions.
"""
# Use one pass through the reference map to grab all the references
object_list = [item for item in db.find_backlink_handles(handle)]
# Then form the object-specific lists
the_lists = ()
for primary in primary_objects:
primary_list = [item[1] for item in object_list if item[0] == primary]
the_lists = the_lists + (primary_list, )
return the_lists
def get_source_referents(source_handle, db):
""" Find objects that refer the source.
This function finds all primary objects that refer (directly or through
secondary child-objects) to a given source handle in a given database.
"""
_primaries = ('Person', 'Family', 'Event', 'Place',
'Source', 'MediaObject', 'Repository')
return (get_referents(source_handle, db, _primaries))
def get_media_referents(media_handle, db):
""" Find objects that refer the media object.
This function finds all primary objects that refer
to a given media handle in a given database.
"""
_primaries = ('Person', 'Family', 'Event', 'Place', 'Source')
return (get_referents(media_handle, db, _primaries))
def get_note_referents(note_handle, db):
""" Find objects that refer a note object.
This function finds all primary objects that refer
to a given note handle in a given database.
"""
_primaries = ('Person', 'Family', 'Event', 'Place',
'Source', 'MediaObject', 'Repository')
return (get_referents(note_handle, db, _primaries))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
_NEW_NAME_PATTERN = '%s%sUntitled_%d.%s'
def get_new_filename(ext, folder='~/'):
ix = 1
while os.path.isfile(os.path.expanduser(_NEW_NAME_PATTERN %
(folder, os.path.sep, ix, ext))):
ix = ix + 1
return os.path.expanduser(_NEW_NAME_PATTERN % (folder, os.path.sep, ix, ext))
def get_empty_tempdir(dirname):
""" Return path to TEMP_DIR/dirname, a guaranteed empty directory
makes intervening directories if required
fails if _file_ by that name already exists,
or for inadequate permissions to delete dir/files or create dir(s)
"""
dirpath = os.path.join(TEMP_DIR,dirname)
if os.path.isdir(dirpath):
shutil.rmtree(dirpath)
os.makedirs(dirpath)
return dirpath
def rm_tempdir(path):
"""Remove a tempdir created with get_empty_tempdir"""
if path.startswith(TEMP_DIR) and os.path.isdir(path):
shutil.rmtree(path)
def cast_to_bool(val):
if val == str(True):
return True
return False
def get_type_converter(val):
"""
Return function that converts strings into the type of val.
"""
val_type = type(val)
if val_type in (str, unicode):
return unicode
elif val_type == int:
return int
elif val_type == float:
return float
elif val_type == bool:
return cast_to_bool
elif val_type in (list, tuple):
return list
def type_name(val):
"""
Return the name the type of val.
Only numbers and strings are supported.
The rest becomes strings (unicode).
"""
val_type = type(val)
if val_type == int:
return 'int'
elif val_type == float:
return 'float'
elif val_type == bool:
return 'bool'
elif val_type in (str, unicode):
return 'unicode'
return 'unicode'
def get_type_converter_by_name(val_str):
"""
Return function that converts strings into the type given by val_str.
Only numbers and strings are supported.
The rest becomes strings (unicode).
"""
if val_str == 'int':
return int
elif val_str == 'float':
return float
elif val_str == 'bool':
return cast_to_bool
elif val_str in ('str', 'unicode'):
return unicode
return unicode
def relative_path(original, base):
"""
Calculate the relative path from base to original, with base a directory,
and original an absolute path
On problems, original is returned unchanged
"""
if not os.path.isdir(base):
return original
#original and base must be absolute paths
if not os.path.isabs(base):
return original
if not os.path.isabs(original):
return original
original = os.path.normpath(original)
base = os.path.normpath(base)
# If the db_dir and obj_dir are on different drives (win only)
# then there cannot be a relative path. Return original obj_path
(base_drive, base) = os.path.splitdrive(base)
(orig_drive, orig_name) = os.path.splitdrive(original)
if base_drive.upper() != orig_drive.upper():
return original
# Starting from the filepath root, work out how much of the filepath is
# shared by base and target.
base_list = (base).split(os.sep)
target_list = (orig_name).split(os.sep)
# make sure '/home/person' and 'c:/home/person' both give
# list ['home', 'person']
base_list = [word for word in base_list if word]
target_list = [word for word in target_list if word]
i = -1
for i in range(min(len(base_list), len(target_list))):
if base_list[i] <> target_list[i]: break
else:
#if break did not happen we are here at end, and add 1.
i += 1
rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:]
return os.path.join(*rel_list)
def media_path(db):
"""
Given a database, return the mediapath to use as basedir for media
"""
mpath = db.get_mediapath()
if mpath is None:
#use home dir
mpath = USER_HOME
return mpath
def media_path_full(db, filename):
"""
Given a database and a filename of a media, return the media filename
is full form, eg 'graves/tomb.png' becomes '/home/me/genea/graves/tomb.png
"""
if os.path.isabs(filename):
return filename
mpath = media_path(db)
return os.path.join(mpath, filename)
def profile(func, *args):
import hotshot.stats
prf = hotshot.Profile('mystats.profile')
print "Start"
prf.runcall(func, *args)
print "Finished"
prf.close()
print "Loading profile"
stats = hotshot.stats.load('mystats.profile')
print "done"
stats.strip_dirs()
stats.sort_stats('time', 'calls')
stats.print_stats(100)
stats.print_callers(100)
#-------------------------------------------------------------------------
#
# Keyword translation interface
#
#-------------------------------------------------------------------------
# keyword, code, translated standard, translated upper
KEYWORDS = [("title", "t", _("Person|Title"), _("Person|TITLE")),
("given", "f", _("Given"), _("GIVEN")),
("prefix", "p", _("Prefix"), _("PREFIX")),
("surname", "l", _("Surname"), _("SURNAME")),
("suffix", "s", _("Suffix"), _("SUFFIX")),
("patronymic","y", _("Patronymic"),_("PATRONYMIC")),
("call", "c", _("Call"), _("CALL")),
("common", "x", _("Common"), _("COMMON")),
("initials", "i", _("Initials"), _("INITIALS"))
]
KEY_TO_TRANS = {}
TRANS_TO_KEY = {}
for (key, code, standard, upper) in KEYWORDS:
KEY_TO_TRANS[key] = standard
KEY_TO_TRANS[key.upper()] = upper
KEY_TO_TRANS["%" + ("%s" % code)] = standard
KEY_TO_TRANS["%" + ("%s" % code.upper())] = upper
TRANS_TO_KEY[standard.lower()] = key
TRANS_TO_KEY[standard] = key
TRANS_TO_KEY[upper] = key.upper()
def get_translation_from_keyword(keyword):
""" Return the translation of keyword """
return KEY_TO_TRANS.get(keyword, keyword)
def get_keyword_from_translation(word):
""" Return the keyword of translation """
return TRANS_TO_KEY.get(word, word)
def get_keywords():
""" Get all keywords, longest to shortest """
keys = KEY_TO_TRANS.keys()
keys.sort(lambda a,b: -cmp(len(a), len(b)))
return keys
def get_translations():
""" Get all translations, longest to shortest """
trans = TRANS_TO_KEY.keys()
trans.sort(lambda a,b: -cmp(len(a), len(b)))
return trans
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_researcher():
import gen.lib
import Config
n = Config.get(Config.RESEARCHER_NAME)
a = Config.get(Config.RESEARCHER_ADDR)
c = Config.get(Config.RESEARCHER_CITY)
s = Config.get(Config.RESEARCHER_STATE)
ct = Config.get(Config.RESEARCHER_COUNTRY)
p = Config.get(Config.RESEARCHER_POSTAL)
ph = Config.get(Config.RESEARCHER_PHONE)
e = Config.get(Config.RESEARCHER_EMAIL)
owner = gen.lib.Researcher()
owner.set_name(n)
owner.set_address(a)
owner.set_city(c)
owner.set_state(s)
owner.set_country(ct)
owner.set_postal_code(p)
owner.set_phone(ph)
owner.set_email(e)
return owner