Environment variables in mediapath

The mediapath could now be a relative path from database location,
or use variables ($GRAMPSHOME, $GRAMPS_RESOURCES, etc.)
This commit is contained in:
belissent 2015-08-19 16:26:59 +02:00
parent 65ff7340af
commit 5d654d402a
6 changed files with 187 additions and 83 deletions

View File

@ -7,7 +7,7 @@
<researcher>
<resname>Alex Roitman,,,</resname>
</researcher>
<mediapath>/home/pierre/Gramps/master/example/gramps</mediapath>
<mediapath>$GRAMPS_RESOURCES/example/gramps</mediapath>
</header>
<name-formats>
<format number="-1" name="SURNAME, Given (Common)" fmt_str="SURNAME, given (common)" active="1"/>

View File

@ -11,7 +11,7 @@
# 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,
# 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.
@ -85,16 +85,16 @@ APP_VCARD = ["text/x-vcard", "text/x-vcalendar"]
#
#-------------------------------------------------------------------------
if 'GRAMPSHOME' in os.environ:
USER_HOME = get_env_var('GRAMPSHOME')
USER_HOME = get_env_var('GRAMPSHOME')
HOME_DIR = os.path.join(USER_HOME, 'gramps')
elif 'USERPROFILE' in os.environ:
USER_HOME = get_env_var('USERPROFILE')
USER_HOME = get_env_var('USERPROFILE')
if 'APPDATA' in os.environ:
HOME_DIR = os.path.join(get_env_var('APPDATA'), 'gramps')
else:
HOME_DIR = os.path.join(USER_HOME, 'gramps')
else:
USER_HOME = get_env_var('HOME')
USER_HOME = get_env_var('HOME')
HOME_DIR = os.path.join(USER_HOME, '.gramps')
@ -115,9 +115,26 @@ USER_PLUGINS = os.path.join(VERSION_DIR, "plugins")
USER_DIRLIST = (USER_HOME, HOME_DIR, VERSION_DIR, ENV_DIR, TEMP_DIR, THUMB_DIR,
THUMB_NORMAL, THUMB_LARGE, USER_PLUGINS)
# Update environment
# This could be of general use, for example when using os.path.expandvars
os.environ['GRAMPS_VERSION'] = VERSION
os.environ['GRAMPS_VERSION_MAJOR'] = major_version
os.environ['GRAMPS_VERSION_DIR'] = VERSION_DIR
os.environ['GRAMPS_ENV_DIR'] = ENV_DIR
os.environ['GRAMPS_TEMP_DIR'] = TEMP_DIR
os.environ['GRAMPS_THUMB_DIR'] = THUMB_DIR
os.environ['GRAMPS_THUMB_NORMAL'] = THUMB_NORMAL
os.environ['GRAMPS_THUMB_LARGE'] = THUMB_LARGE
os.environ['GRAMPS_USER_PLUGINS'] = USER_PLUGINS
# Attention: $GRAMPSHOME should NOT be set, because it redefines the HOME_DIR behavior
# This leads to bugs, especially when a test calls GRAMPS again:
# the HOME_DIR is then re-computed with a wrong $GRAMPSHOME
#-------------------------------------------------------------------------
#
# Paths to python modules - assumes that the root directory is one level
# Paths to python modules - assumes that the root directory is one level
# above this one, and that the plugins directory is below the root directory.
#
#-------------------------------------------------------------------------
@ -192,21 +209,21 @@ COMMENTS = _("Gramps\n (Genealogical Research and Analysis "
"is a personal genealogy program.")
AUTHORS = [
"Alexander Roitman",
"Benny Malengier",
"Benny Malengier",
"Brian Matherly",
"Donald A. Peterson",
"Donald N. Allingham",
"David Hampton",
"Donald A. Peterson",
"Donald N. Allingham",
"David Hampton",
"Martin Hawlisch",
"Richard Taylor",
"Richard Taylor",
"Tim Waugh",
"John Ralls"
]
AUTHORS_FILE = os.path.join(DATA_DIR, "authors.xml")
DOCUMENTERS = [
'Alexander Roitman',
'Alexander Roitman',
]
#-------------------------------------------------------------------------
@ -232,14 +249,14 @@ ARABIC_SEMICOLON = "؛"
# (longName, shortName, type , default, flags, descrip , argDescrip)
POPT_TABLE = [
("config", 'c', str, None, 0, "Set config setting(s) and start Gramps", ""),
("open", 'O', str, None, 0, "Open family tree", "FAMILY_TREE"),
("create", 'C', str, None, 0, "Create or Open family tree", "FAMILY_TREE"),
("import", 'i', str, None, 0, "Import file", "FILENAME"),
("open", 'O', str, None, 0, "Open family tree", "FAMILY_TREE"),
("create", 'C', str, None, 0, "Create or Open family tree", "FAMILY_TREE"),
("import", 'i', str, None, 0, "Import file", "FILENAME"),
("export", 'e', str, None, 0, "Export file", "FILENAME"),
("format", 'f', str, None, 0, 'Specify format', "FORMAT"),
("action", 'a', str, None, 0, 'Specify action', "ACTION"),
("options", 'p', str, None, 0, 'Specify options', "OPTIONS_STRING"),
("debug", 'd', str, None, 0, 'Enable debug logs', "LOGGER_NAME"),
("format", 'f', str, None, 0, 'Specify format', "FORMAT"),
("action", 'a', str, None, 0, 'Specify action', "ACTION"),
("options", 'p', str, None, 0, 'Specify options', "OPTIONS_STRING"),
("debug", 'd', str, None, 0, 'Enable debug logs', "LOGGER_NAME"),
("", 'l', None, None, 0, 'List Family Trees', ""),
("", 'L', None, None, 0, 'List Family Tree Details', ""),
("show", 's', None, None, 0, "Show config settings", ""),
@ -248,42 +265,42 @@ POPT_TABLE = [
]
LONGOPTS = [
"action=",
"action=",
"class=",
"config=",
"debug=",
"display=",
"disable-sound",
"disable-crash-dialog",
"disable-sound",
"disable-crash-dialog",
"enable-sound",
"espeaker=",
"export=",
"force-unlock",
"format=",
"gdk-debug=",
"gdk-no-debug=",
"gtk-debug=",
"gtk-no-debug=",
"gtk-module=",
"gdk-debug=",
"gdk-no-debug=",
"gtk-debug=",
"gtk-no-debug=",
"gtk-module=",
"g-fatal-warnings",
"help",
"import=",
"import=",
"load-modules=",
"list"
"list"
"name=",
"oaf-activate-iid=",
"oaf-ior-fd=",
"oaf-activate-iid=",
"oaf-ior-fd=",
"oaf-private",
"open=",
"create=",
"options=",
"screen=",
"show",
"sm-client-id=",
"sm-config-prefix=",
"show",
"sm-client-id=",
"sm-config-prefix=",
"sm-disable",
"sync",
"usage",
"usage",
"version",
"qml",
"yes",

View File

@ -10,7 +10,7 @@
# 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,
# 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.
@ -91,7 +91,7 @@ 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,
fails if _file_ by that name already exists,
or for inadequate permissions to delete dir/files or create dir(s)
"""
@ -121,10 +121,10 @@ def relative_path(original, base):
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)
(base_drive, base) = os.path.splitdrive(base)
(orig_drive, orig_name) = os.path.splitdrive(original)
if base_drive.upper() != orig_drive.upper():
return original
@ -133,7 +133,7 @@ def relative_path(original, base):
# 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
# make sure '/home/person' and 'c:/home/person' both give
# list ['home', 'person']
base_list = [_f for _f in base_list if _f]
target_list = [_f for _f in target_list if _f]
@ -146,14 +146,48 @@ def relative_path(original, base):
rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:]
return os.path.join(*rel_list)
def expanded_vars_path(path):
"""
Expand environment variables in a path
$GRAMPSHOME is set and restored afterwards,
because undefined $GRAMPSHOME has a special meaning (see const.py).
"""
if not 'GRAMPSHOME' in os.environ:
os.environ['GRAMPSHOME'] = USER_HOME
grampshome_added = True
path = os.path.expandvars(path)
if (grampshome_added):
del os.environ['GRAMPSHOME']
return path
def media_path(db):
"""
Given a database, return the mediapath to use as basedir for media
"""
mpath = db.get_mediapath()
return norm_media_path(mpath, db)
def norm_media_path(mpath, db):
"""
Normalize a mediapath:
- Relative mediapath are considered as relative to the database
- Expand variables ($GRAMPSHOME, $GRAMPS_RESOURCES, etc.)
- Convert to absolute path
- Convert slashes and case (on Windows)
"""
# Use home dir if no media_path specified
if mpath is None:
#use home dir
mpath = USER_HOME
mpath = os.path.abspath(USER_HOME)
# Expand environment variables
mpath = expanded_vars_path(mpath)
# Relative mediapath are considered as relative to the database
if not os.path.isabs(mpath):
basepath = db.get_save_path()
if not basepath:
basepath = USER_HOME
mpath = os.path.join(os.path.abspath(basepath), mpath)
# Normalize path
mpath = os.path.normcase(os.path.normpath(os.path.abspath(mpath)))
return mpath
def media_path_full(db, filename):
@ -178,7 +212,7 @@ def search_for(name):
return 1
if os.access(name, os.X_OK) and not os.path.isdir(name):
return 1
else:
else:
for i in os.environ['PATH'].split(':'): #not win()
fname = os.path.join(i, name)
if os.access(fname, os.X_OK) and not os.path.isdir(fname):

View File

@ -0,0 +1,84 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007-2009 B. Malengier
# Copyright (C) 2009 Swoon on bug tracker
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
import os
import shutil
import unittest
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import TEMP_DIR, USER_HOME, USER_PLUGINS
from gramps.gen.constfunc import get_env_var
from gramps.gen.utils.file import media_path, get_empty_tempdir
from gramps.gen.dbstate import DbState
from gramps.version import VERSION
#-------------------------------------------------------------------------
#
# FileTest class
#
#-------------------------------------------------------------------------
class FileTest(unittest.TestCase):
def test_mediapath(self):
# Create database
dbstate = DbState()
db = dbstate.make_database("bsddb")
path = get_empty_tempdir("utils_file_test")
db.write_version(path)
db.load(path)
dbstate.change_database(db)
# Test without db.mediapath set
self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(os.path.abspath(USER_HOME))))
self.assertTrue(os.path.exists(media_path(db)))
# Test with absolute db.mediapath
db.set_mediapath(os.path.abspath(USER_HOME) + "/test_abs")
self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(os.path.abspath(USER_HOME + "/test_abs"))))
# Test with relative db.mediapath
db.set_mediapath("test_rel")
self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(os.path.abspath(TEMP_DIR + "/utils_file_test/test_rel"))))
# Test with environment variable
db.set_mediapath("$GRAMPSHOME/test_var")
self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(os.path.abspath(USER_HOME + "/test_var"))))
db.set_mediapath("/test/$GRAMPS_VERSION/test_var")
self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(os.path.abspath("/test/" + VERSION + "/test_var"))))
db.set_mediapath("${GRAMPS_USER_PLUGINS}/test_var")
self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(os.path.abspath(USER_PLUGINS + "/test_var"))))
#-------------------------------------------------------------------------
#
# main
#
#-------------------------------------------------------------------------
if __name__ == "__main__":
unittest.main()

View File

@ -53,6 +53,7 @@ from gramps.gen.datehandler import get_date_formats
from gramps.gen.display.name import displayer as _nd
from gramps.gen.display.name import NameDisplayError
from gramps.gen.utils.alive import update_constants
from gramps.gen.utils.file import media_path
from gramps.gen.utils.keyword import (get_keywords, get_translation_from_keyword,
get_translations, get_keyword_from_translation)
from gramps.gen.lib import Date, FamilyRelType
@ -1460,9 +1461,7 @@ class GrampsPreferences(ConfigureDialog):
_('_Apply'),
Gtk.ResponseType.OK)
)
mpath = self.dbstate.db.get_mediapath()
if not mpath:
mpath = HOME_DIR
mpath = media_path(self.dbstate.db)
f.set_current_folder(os.path.dirname(mpath))
status = f.run()

View File

@ -62,7 +62,7 @@ from gramps.gen.errors import GrampsImportError
from gramps.gen.utils.id import create_id
from gramps.gen.utils.db import family_name
from gramps.gen.utils.unknown import make_unknown, create_explanation_note
from gramps.gen.utils.file import create_checksum
from gramps.gen.utils.file import create_checksum, media_path, norm_media_path
from gramps.gen.datehandler import parser, set_date
from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
@ -165,35 +165,6 @@ def importData(database, filename, user):
database.readonly = read_only
return info
## TODO - WITH MEDIA PATH, IS THIS STILL NEEDED?
## BETTER LEAVE ALL RELATIVE TO NEW RELATIVE PATH
## save_path is in .gramps/dbbase, no good place !
## # copy all local images into <database>.images directory
## db_dir = os.path.abspath(os.path.dirname(database.get_save_path()))
## db_base = os.path.basename(database.get_save_path())
## img_dir = os.path.join(db_dir, db_base)
## first = not os.path.exists(img_dir)
##
## for m_id in database.get_media_object_handles():
## mobject = database.get_object_from_handle(m_id)
## oldfile = mobject.get_path()
## if oldfile and not os.path.isabs(oldfile):
## if first:
## os.mkdir(img_dir)
## first = 0
## newfile = os.path.join(img_dir, oldfile)
##
## try:
## oldfilename = os.path.join(basefile, oldfile)
## shutil.copyfile(oldfilename, newfile)
## try:
## shutil.copystat(oldfilename, newfile)
## except:
## pass
## mobject.set_path(newfile)
## database.commit_media_object(mobject, None, change)
## except (IOError, OSError), msg:
## ErrorDialog(_('Could not copy file'), str(msg))
#-------------------------------------------------------------------------
#
@ -965,14 +936,13 @@ class GrampsParser(UpdateCallback):
person = self.db.get_person_from_handle(self.home)
self.db.set_default_person_handle(person.handle)
#set media path, this should really do some parsing to convert eg
# windows path to unix ?
# Set media path
# The paths are normalized before being compared.
if self.mediapath:
oldpath = self.db.get_mediapath()
if not oldpath:
if not self.db.get_mediapath():
self.db.set_mediapath(self.mediapath)
elif not oldpath == self.mediapath:
self.user.notify_error(_("Could not change media path"),
elif not media_path(self.db) == norm_media_path(self.mediapath, self.db):
self.user.notify_error(_("Could not change media path"),
_("The opened file has media path %s, which conflicts with"
" the media path of the Family Tree you import into. "
"The original media path has been retained. Copy the "