diff --git a/.gitignore b/.gitignore index 1da66317f..badf2ed3c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,5 @@ dist/ # Gramps data/tips.xml -gramps/gen/const.py gramps/plugins/lib/holidays.xml po/.intltool-merge-cache diff --git a/Gramps.py b/Gramps.py index 30ed98abb..c6345fcab 100644 --- a/Gramps.py +++ b/Gramps.py @@ -27,5 +27,7 @@ able to run gramps from the source directory without setting PYTHONPATH From this position, import gramps works great """ +import os +os.environ['GRAMPS_RESOURCES'] = os.path.dirname(os.path.abspath(__file__)) import gramps.grampsapp as app app.main() diff --git a/gramps/gen/const.py.in b/gramps/gen/const.py similarity index 93% rename from gramps/gen/const.py.in rename to gramps/gen/const.py index 05498ce95..855e25272 100644 --- a/gramps/gen/const.py.in +++ b/gramps/gen/const.py @@ -4,6 +4,7 @@ # # Copyright (C) 2000-2006 Donald N. Allingham # Copyright (C) 2012 Doug Blank +# Copyright (C) 2013 John Ralls # # 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 @@ -50,21 +51,7 @@ from .svn_revision import get_svn_revision # #------------------------------------------------------------------------- PROGRAM_NAME = "Gramps" -VERSION = "@VERSIONSTRING@" -if VERSION == "@" + "VERSIONSTRING" + "@": - raise Exception("Please run 'python setup.py build'") -def get_version_tuple(v): - """ Get the numeric-dotted part of version number""" - retval = "" - for c in v: - if c.isdigit() or (c == "." and retval.count(".") <= 1): - retval += c - else: - break - return tuple(map(int, retval.split("."))) -VERSION_TUPLE = get_version_tuple(VERSION) -major_version = "%s.%s" % (VERSION_TUPLE[0], VERSION_TUPLE[1]) - +from gramps.version import VERSION, VERSION_TUPLE, major_version #------------------------------------------------------------------------- # # Standard GRAMPS Websites @@ -135,8 +122,7 @@ if sys.version_info[0] < 3: else: pass -VERSION_DIR = os.path.join( - HOME_DIR, "gramps%s%s" % (VERSION_TUPLE[0], VERSION_TUPLE[1])) +VERSION_DIR = os.path.join(HOME_DIR, "gramps%s" % major_version) CUSTOM_FILTERS = os.path.join(VERSION_DIR, "custom_filters.xml") REPORT_OPTIONS = os.path.join(HOME_DIR, "report_options.xml") @@ -199,10 +185,11 @@ else: # Paths to data files. # #------------------------------------------------------------------------- -LOCALE_DIR = "@LOCALE_DIR@" -DATA_DIR = "@DATA_DIR@" -IMAGE_DIR = "@IMAGE_DIR@" -DOC_DIR = "@DOC_DIR@" +from gramps.gen.utils.resourcepath import ResourcePath +_resources = ResourcePath() +LOCALE_DIR = _resources.locale_dir +DATA_DIR = _resources.data_dir +IMAGE_DIR = _resources.image_dir TIP_DATA = os.path.join(DATA_DIR, "tips.xml") PAPERSIZE = os.path.join(DATA_DIR, "papersize.xml") @@ -211,7 +198,7 @@ ICON = os.path.join(IMAGE_DIR, "gramps.png") LOGO = os.path.join(IMAGE_DIR, "logo.png") SPLASH = os.path.join(IMAGE_DIR, "splash.jpg") -LICENSE_FILE = os.path.join(DOC_DIR, 'COPYING') +LICENSE_FILE = os.path.join(_resources.doc_dir, 'COPYING') #------------------------------------------------------------------------- # # Init Localization @@ -238,9 +225,10 @@ AUTHORS = [ "Donald A. Peterson", "Donald N. Allingham", "David Hampton", - "Martin Hawlisch", + "Martin Hawlisch", "Richard Taylor", - "Tim Waugh", + "Tim Waugh", + "John Ralls" ] AUTHORS_FILE = os.path.join(DATA_DIR, "authors.xml") diff --git a/gramps/gen/utils/resourcepath.py b/gramps/gen/utils/resourcepath.py new file mode 100644 index 000000000..ba457dafe --- /dev/null +++ b/gramps/gen/utils/resourcepath.py @@ -0,0 +1,97 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2013 John Ralls +# +# 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$ + +import sys +import io +import os +import logging +LOG = logging.getLogger("ResourcePath") +_hdlr = logging.StreamHandler() +_hdlr.setFormatter(logging.Formatter(fmt="%(name)s.%(levelname)s: %(message)s")) +LOG.addHandler(_hdlr) + +class ResourcePath(object): + """ + ResourcePath is a singleton, meaning that only one of them is ever + created. At startup it finds the paths to Gramps's resource files and + caches them for future use. + + It should be called only by const.py; other code should retrieve the + paths from there. + """ + instance = None + def __new__(cls): + if not cls.instance: + cls.instance = super(ResourcePath, cls).__new__(cls) + cls.instance.initialized = False + + return cls.instance + + def __init__(self): + if self.initialized: + return + + resource_file = os.path.join(os.path.abspath(os.path.dirname(__file__)), + 'resource-path') + installed = os.path.exists(resource_file) + if installed: + test_path = os.path.join("gramps", "authors.xml") + else: + test_path = os.path.join("data", "authors.xml") + resource_path = None + if ('GRAMPS_RESOURCES' in os.environ and + os.path.exists(os.path.join(os.environ['GRAMPS_RESOURCES'], + test_path))): + resource_path = os.environ['GRAMPS_RESOURCES'] + elif installed: + try: + with io.open(resource_file, encoding='utf-8', + errors='strict') as fp: + resource_path = fp.readline() + except UnicodeError as err: + LOG.exception("Encoding error while parsing resource path", err) + sys.exit(1) + except IOError as err: + LOG.exception("Failed to open resource file", err) + sys.exit(1) + if not os.path.exists(os.path.join(resource_path, test_path)): + LOG.error("Resource Path %s is invalid", resource_path) + sys.exit(1) + else: + LOG.error("Unable to determine resource path") + sys.exit(1) + + if installed: + self.locale_dir = os.path.join(resource_path, 'locale') + self.data_dir = os.path.join(resource_path, 'gramps') + self.image_dir = os.path.join(resource_path, 'gramps', 'images') + self.doc_dir = os.path.join(resource_path, 'doc', 'gramps') + + else: + self.locale_dir = os.path.join(resource_path, 'build', 'mo') + self.image_dir = os.path.join(resource_path, 'images') + self.data_dir = os.path.join(resource_path, 'data') + self.doc_dir = os.path.join(resource_path, 'build', 'data') + + self.initialized = True + + diff --git a/mac/gramps.launcher b/mac/gramps.launcher index 6739e7573..767d1405d 100755 --- a/mac/gramps.launcher +++ b/mac/gramps.launcher @@ -36,6 +36,7 @@ export PYTHONHOME="$bundle_res" export GRAMPSDIR="$bundle_lib/python$PYVER/site-packages/gramps" export GRAMPSI18N="$bundle_data"/locale +export GRAMPS_RESOURCES="$bundle_data" export GRAMPSHOME="$HOME/Library/Application Support" # Strip out the argument added by the OS. diff --git a/setup.py b/setup.py index 037f9bd1b..79a273f43 100644 --- a/setup.py +++ b/setup.py @@ -46,8 +46,9 @@ import subprocess if sys.version_info[0] < 3: import commands from stat import ST_MODE +import io +from gramps.version import VERSION -VERSION = '4.1.0' ALL_LINGUAS = ('bg', 'ca', 'cs', 'da', 'de', 'el', 'en_GB', 'es', 'fi', 'fr', 'he', 'hr', 'hu', 'it', 'ja', 'lt', 'nb', 'nl', 'nn', 'pl', 'pt_BR', 'pt_PT', 'ru', 'sk', 'sl', 'sq', 'sv', 'uk', 'vi', 'zh_CN') @@ -158,11 +159,10 @@ def build_man(build_cmd): os.remove(newfile) if filename: - f_in = open(newfile, 'rb') - f_out = gzip.open(man_file_gz, 'wb') - f_out.writelines(f_in) - f_out.close() - f_in.close() + #Binary io, so open is OK + with open(newfile, 'rb') as f_in,\ + gzip.open(man_file_gz, 'wb') as f_out: + f_out.writelines(f_in) os.remove(newfile) filename = False @@ -230,47 +230,6 @@ def merge(in_file, out_file, option, po_dir='po', cache=True): out_file) raise SystemExit(msg) -def write_const_py(command): - ''' - Write the const.py file. - ''' - const_py_in = os.path.join('gramps', 'gen', 'const.py.in') - const_py = os.path.join('gramps', 'gen', 'const.py') - if hasattr(command, 'install_data'): - #during install - share_dir = os.path.join(command.install_data, 'share') - locale_dir = os.path.join(share_dir, 'locale') - data_dir = os.path.join(share_dir, 'gramps') - image_dir = os.path.join(share_dir, 'gramps', 'icons', 'hicolor') - doc_dir = os.path.join(share_dir, 'doc', 'gramps') - if sys.platform == 'win32': - (share_dir, locale_dir, data_dir, image_dir, doc_dir) = \ - [path.replace('\\', '\\\\') for path in - (share_dir, locale_dir, data_dir, image_dir, doc_dir)] - - else: - #in build - if 'install' in command.distribution.command_obj: - # Prevent overwriting version created during install - return - base_dir = os.path.abspath(os.path.dirname(__file__)) - locale_dir = os.path.abspath(os.path.join(command.build_base, 'mo')) - data_dir = os.path.join(base_dir, 'data') - image_dir = os.path.join(base_dir, 'images') - doc_dir = base_dir - if sys.platform == 'win32': - (locale_dir, data_dir, image_dir, doc_dir) = \ - [path.replace('\\', '\\\\') for path in - (locale_dir, data_dir, image_dir, doc_dir)] - - subst_vars = (('@VERSIONSTRING@', VERSION), - ('@LOCALE_DIR@', locale_dir), - ('@DATA_DIR@', data_dir), - ('@IMAGE_DIR@', image_dir), - ('@DOC_DIR@', doc_dir),) - - substitute_variables(const_py_in, const_py, subst_vars) - def update_posix(command): ''' post-hook to update Linux systems after install @@ -292,12 +251,11 @@ class build(_build): if not sys.platform == 'win32': build_man(self) build_intl(self) - write_const_py(self) _build.run(self) class install(_install): """Custom install command.""" - _install.user_options.append(('enable-packager-mode', None, + _install.user_options.append(('enable-packager-mode', None, 'disable post-installation mime type processing')) _install.boolean_options.append('enable-packager-mode') @@ -306,14 +264,24 @@ class install(_install): self.enable_packager_mode = False def run(self): - write_const_py(self) + resource_file = os.path.join(os.path.dirname(__file__), 'gramps', 'gen', + 'utils', 'resource-path') + with io.open(resource_file, 'w', encoding='utf-8', + errors='strict') as fp: + path = os.path.abspath(os.path.join(self.install_data, 'share')) + if sys.version_info[0] < 3: + path = unicode(path) + fp.write(path) + _install.run(self) if self.enable_packager_mode: log.warn('WARNING: Packager mode enabled. Post-installation ' 'scripts were not run.') else: update_posix(self) - + + os.remove(resource_file) + #------------------------------------------------------------------------- # # Packages @@ -424,6 +392,7 @@ for (dirpath, dirnames, filenames) in os.walk(basedir): package_data_core.append(dirpath[7:] + '/' + dirname + '/*.js') package_data_core.append('plugins/webstuff/images/*.gif') package_data_core.append('plugins/webstuff/images/*.ico') +package_data_core.append('gen/utils/resource-path') package_data_gui = ['gui/glade/*.glade']