Migrate code style to Black
This commit is contained in:
@@ -26,4 +26,5 @@ able to run gramps from the source directory without setting PYTHONPATH
|
||||
From this position, import gramps works great
|
||||
"""
|
||||
import gramps.grampsapp as app
|
||||
|
||||
app.main()
|
||||
|
@@ -5,36 +5,40 @@ from os.path import join
|
||||
import sys
|
||||
import site
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
if getattr(sys, "frozen", False):
|
||||
aio = os.path.dirname(sys.executable)
|
||||
sys.path.insert(1, aio)
|
||||
sys.path.insert(1, os.path.join(aio,'lib'))
|
||||
sys.path.insert(1, os.path.join(aio, "lib"))
|
||||
sys.path.insert(1, site.getusersitepackages())
|
||||
environ['PANGOCAIRO_BACKEND'] = 'fontconfig'
|
||||
environ['SSL_CERT_FILE'] = join(aio, 'ssl/certs/ca-bundle.trust.crt')
|
||||
environ['GI_TYPELIB_PATH'] = join(aio, 'lib/girepository-1.0')
|
||||
environ['G_ENABLE_DIAGNOSTIC'] = '0'
|
||||
environ['G_PARAM_DEPRECATED'] = '0'
|
||||
environ['GRAMPS_RESOURCES'] = join(aio, 'share')
|
||||
environ['PATH'] = aio + ';' + aio +'\lib;' + environ['PATH']
|
||||
environ["PANGOCAIRO_BACKEND"] = "fontconfig"
|
||||
environ["SSL_CERT_FILE"] = join(aio, "ssl/certs/ca-bundle.trust.crt")
|
||||
environ["GI_TYPELIB_PATH"] = join(aio, "lib/girepository-1.0")
|
||||
environ["G_ENABLE_DIAGNOSTIC"] = "0"
|
||||
environ["G_PARAM_DEPRECATED"] = "0"
|
||||
environ["GRAMPS_RESOURCES"] = join(aio, "share")
|
||||
environ["PATH"] = aio + ";" + aio + "\lib;" + environ["PATH"]
|
||||
|
||||
|
||||
def close():
|
||||
sys.exit()
|
||||
|
||||
|
||||
import atexit
|
||||
import ctypes
|
||||
|
||||
HANDLE = ctypes.windll.kernel32.CreateMutexW(None, 1, "org.gramps-project.gramps")
|
||||
ERROR = ctypes.GetLastError()
|
||||
if ERROR == 183: # ERROR_ALREADY_EXISTS:
|
||||
print('Gramps is already running!', file=sys.stderr)
|
||||
print("Gramps is already running!", file=sys.stderr)
|
||||
close()
|
||||
|
||||
atexit.register(ctypes.windll.kernel32.CloseHandle, HANDLE)
|
||||
atexit.register(ctypes.windll.kernel32.ReleaseMutex, HANDLE)
|
||||
|
||||
import warnings
|
||||
|
||||
warnings.simplefilter("ignore")
|
||||
|
||||
import gramps.grampsapp as app
|
||||
|
||||
app.run()
|
||||
|
@@ -5,19 +5,20 @@ from os.path import join
|
||||
import sys
|
||||
import site
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
if getattr(sys, "frozen", False):
|
||||
aio = os.path.dirname(sys.executable)
|
||||
sys.path.insert(1, aio)
|
||||
sys.path.insert(1, os.path.join(aio,'lib'))
|
||||
sys.path.insert(1, os.path.join(aio, "lib"))
|
||||
sys.path.insert(1, site.getusersitepackages())
|
||||
environ['LANG'] = 'en'
|
||||
environ['PANGOCAIRO_BACKEND'] = 'fontconfig'
|
||||
environ['SSL_CERT_FILE'] = join(aio, 'ssl/certs/ca-bundle.trust.crt')
|
||||
environ['GI_TYPELIB_PATH'] = join(aio, 'lib/girepository-1.0')
|
||||
environ['G_ENABLE_DIAGNOSTIC'] = '0'
|
||||
environ['G_PARAM_DEPRECATED'] = '0'
|
||||
environ['GRAMPS_RESOURCES'] = join(aio, 'share')
|
||||
environ['PATH'] = aio + ';' + aio +'\lib;' + environ['PATH']
|
||||
environ["LANG"] = "en"
|
||||
environ["PANGOCAIRO_BACKEND"] = "fontconfig"
|
||||
environ["SSL_CERT_FILE"] = join(aio, "ssl/certs/ca-bundle.trust.crt")
|
||||
environ["GI_TYPELIB_PATH"] = join(aio, "lib/girepository-1.0")
|
||||
environ["G_ENABLE_DIAGNOSTIC"] = "0"
|
||||
environ["G_PARAM_DEPRECATED"] = "0"
|
||||
environ["GRAMPS_RESOURCES"] = join(aio, "share")
|
||||
environ["PATH"] = aio + ";" + aio + "\lib;" + environ["PATH"]
|
||||
|
||||
import gramps.grampsapp as app
|
||||
|
||||
app.run()
|
||||
|
@@ -1,31 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
'''
|
||||
"""
|
||||
grampsw.exe
|
||||
'''
|
||||
"""
|
||||
import os
|
||||
from os import environ
|
||||
from os.path import join
|
||||
import sys
|
||||
import site
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
if getattr(sys, "frozen", False):
|
||||
aio = os.path.dirname(sys.executable)
|
||||
sys.path.insert(1, aio)
|
||||
sys.path.insert(1, os.path.join(aio,'lib'))
|
||||
sys.path.insert(1, os.path.join(aio, "lib"))
|
||||
sys.path.insert(1, site.getusersitepackages())
|
||||
environ['SSL_CERT_FILE'] = join(aio, 'ssl/certs/ca-bundle.trust.crt')
|
||||
environ['GI_TYPELIB_PATH'] = join(aio, 'lib/girepository-1.0')
|
||||
environ['G_ENABLE_DIAGNOSTIC'] = '0'
|
||||
environ['G_PARAM_DEPRECATED'] = '0'
|
||||
environ['GRAMPS_RESOURCES'] = join(aio, 'share')
|
||||
environ['PATH'] = aio + ';' + aio +'\lib;' + environ['PATH']
|
||||
environ["SSL_CERT_FILE"] = join(aio, "ssl/certs/ca-bundle.trust.crt")
|
||||
environ["GI_TYPELIB_PATH"] = join(aio, "lib/girepository-1.0")
|
||||
environ["G_ENABLE_DIAGNOSTIC"] = "0"
|
||||
environ["G_PARAM_DEPRECATED"] = "0"
|
||||
environ["GRAMPS_RESOURCES"] = join(aio, "share")
|
||||
environ["PATH"] = aio + ";" + aio + "\lib;" + environ["PATH"]
|
||||
|
||||
import atexit
|
||||
import ctypes
|
||||
|
||||
|
||||
def close():
|
||||
''' Show warning dialog if Gramps is already running'''
|
||||
sys.exit('Gramps is already running!')
|
||||
"""Show warning dialog if Gramps is already running"""
|
||||
sys.exit("Gramps is already running!")
|
||||
|
||||
|
||||
HANDLE = ctypes.windll.kernel32.CreateMutexW(None, 1, "org.gramps-project.gramps")
|
||||
ERROR = ctypes.GetLastError()
|
||||
@@ -36,4 +38,5 @@ atexit.register(ctypes.windll.kernel32.CloseHandle, HANDLE)
|
||||
atexit.register(ctypes.windll.kernel32.ReleaseMutex, HANDLE)
|
||||
|
||||
import gramps.grampsapp as app
|
||||
|
||||
app.main()
|
||||
|
308
aio/setup.py
308
aio/setup.py
@@ -1,7 +1,7 @@
|
||||
'''
|
||||
"""
|
||||
Use with:
|
||||
python3 setup.py build_exe --no-compress -O1
|
||||
'''
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import site
|
||||
@@ -11,141 +11,241 @@ import atexit
|
||||
import shutil
|
||||
import zipfile
|
||||
import cx_Freeze
|
||||
sys.path.insert(0,'dist')
|
||||
|
||||
sys.path.insert(0, "dist")
|
||||
import gramps
|
||||
from gramps.version import VERSION_TUPLE
|
||||
|
||||
try:
|
||||
from gramps.version import VERSION_QUALIFIER
|
||||
except:
|
||||
VERSION_QUALIFIER = ''
|
||||
UPX_ALT_PATH = r'UPX'
|
||||
VERSION_QUALIFIER = ""
|
||||
UPX_ALT_PATH = r"UPX"
|
||||
|
||||
# import logging
|
||||
# logging.basicConfig(level=logging.DEBUG)
|
||||
VQ = {'-alpha1': 10, '-alpha2': 11, '-alpha3': 12,
|
||||
'-beta1': 21, '-beta2': 22, '-beta3': 23,
|
||||
'-rc1': 22, '': 0}
|
||||
VQ = {
|
||||
"-alpha1": 10,
|
||||
"-alpha2": 11,
|
||||
"-alpha3": 12,
|
||||
"-beta1": 21,
|
||||
"-beta2": 22,
|
||||
"-beta3": 23,
|
||||
"-rc1": 22,
|
||||
"": 0,
|
||||
}
|
||||
|
||||
VERSION = ('.'.join(map(str, VERSION_TUPLE)) + '.' +
|
||||
str(VQ.get(VERSION_QUALIFIER, 99)))
|
||||
VERSION = ".".join(map(str, VERSION_TUPLE)) + "." + str(VQ.get(VERSION_QUALIFIER, 99))
|
||||
COPYRIGHT = "Copyright 2020, Gramps developers. GNU General Public License"
|
||||
# Prepare a temporay directory
|
||||
TEMP_DIR = tempfile.TemporaryDirectory()
|
||||
atexit.register(TEMP_DIR.cleanup)
|
||||
BASE_DIR = os.path.split(sys.prefix)[1]
|
||||
SETUP_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
SETUP_FILES = ['setup.py', 'gramps.ico', 'grampsc.ico', 'grampsd.ico',
|
||||
'grampsaioc.py', 'grampsaiocd.py', 'grampsaiow.py']
|
||||
if '32' in BASE_DIR:
|
||||
SETUP_FILES.append(''.join(('grampsaio', '32', '.nsi')))
|
||||
SETUP_FILES = [
|
||||
"setup.py",
|
||||
"gramps.ico",
|
||||
"grampsc.ico",
|
||||
"grampsd.ico",
|
||||
"grampsaioc.py",
|
||||
"grampsaiocd.py",
|
||||
"grampsaiow.py",
|
||||
]
|
||||
if "32" in BASE_DIR:
|
||||
SETUP_FILES.append("".join(("grampsaio", "32", ".nsi")))
|
||||
else:
|
||||
SETUP_FILES.append(''.join(('grampsaio', '64', '.nsi')))
|
||||
SETUP_FILES.append("".join(("grampsaio", "64", ".nsi")))
|
||||
|
||||
INCLUDE_DLL_PATH = os.path.join(sys.exec_prefix, 'bin')
|
||||
INCLUDE_DLL_PATH = os.path.join(sys.exec_prefix, "bin")
|
||||
INCLUDE_FILES = []
|
||||
INCLUDES = ['gi', 'cgi', 'colorsys', 'site']
|
||||
PACKAGES = ['gi', 'cairo', 'xml', 'bsddb3', 'lxml', 'PIL', 'json', 'csv',
|
||||
'sqlite3', 'cProfile', 'networkx', 'psycopg2', 'requests', 'logging'
|
||||
, 'html', 'compileall', 'graphviz', 'pydotplus', 'pygraphviz', 'pydot' ]
|
||||
EXCLUDES = ['tkinter', 'PyQt5', 'PyQt5.QtCore', 'PyQt5.QtGui', 'pyside'
|
||||
'PyQt5.QtWidgets', 'sip', 'lib2to3', 'PIL.ImageQt', 'pip', 'distlib'
|
||||
INCLUDES = ["gi", "cgi", "colorsys", "site"]
|
||||
PACKAGES = [
|
||||
"gi",
|
||||
"cairo",
|
||||
"xml",
|
||||
"bsddb3",
|
||||
"lxml",
|
||||
"PIL",
|
||||
"json",
|
||||
"csv",
|
||||
"sqlite3",
|
||||
"cProfile",
|
||||
"networkx",
|
||||
"psycopg2",
|
||||
"requests",
|
||||
"logging",
|
||||
"html",
|
||||
"compileall",
|
||||
"graphviz",
|
||||
"pydotplus",
|
||||
"pygraphviz",
|
||||
"pydot",
|
||||
]
|
||||
EXCLUDES = [
|
||||
"tkinter",
|
||||
"PyQt5",
|
||||
"PyQt5.QtCore",
|
||||
"PyQt5.QtGui",
|
||||
"pyside" "PyQt5.QtWidgets",
|
||||
"sip",
|
||||
"lib2to3",
|
||||
"PIL.ImageQt",
|
||||
"pip",
|
||||
"distlib",
|
||||
]
|
||||
|
||||
REPLACE_PATHS = [('*', 'AIO/'),
|
||||
( site.getsitepackages()[0]
|
||||
+'cx_freeze-5.0-py3.6-mingw.egg/cx_Freeze', 'cx_Freeze/')
|
||||
REPLACE_PATHS = [
|
||||
("*", "AIO/"),
|
||||
(
|
||||
site.getsitepackages()[0] + "cx_freeze-5.0-py3.6-mingw.egg/cx_Freeze",
|
||||
"cx_Freeze/",
|
||||
),
|
||||
]
|
||||
MISSING_DLL = ['libgtk-3-0.dll', 'libgtkspell3-3-0.dll', 'libgexiv2-2.dll',
|
||||
'libgoocanvas-3.0-9.dll', 'libosmgpsmap-1.0-1.dll',
|
||||
'gswin32c.exe', 'dot.exe', 'libgvplugin_core-6.dll',
|
||||
'libgvplugin_dot_layout-6.dll', 'libgvplugin_gd-6.dll',
|
||||
'libgvplugin_pango-6.dll', 'libgvplugin_rsvg-6.dll',
|
||||
'glib-compile-schemas.exe',
|
||||
'gdk-pixbuf-query-loaders.exe', 'gtk-update-icon-cache-3.0.exe',
|
||||
'fc-cache.exe', 'fc-match.exe', 'gspawn-win64-helper-console.exe',
|
||||
'gspawn-win64-helper.exe', 'libgeocode-glib-0.dll'
|
||||
MISSING_DLL = [
|
||||
"libgtk-3-0.dll",
|
||||
"libgtkspell3-3-0.dll",
|
||||
"libgexiv2-2.dll",
|
||||
"libgoocanvas-3.0-9.dll",
|
||||
"libosmgpsmap-1.0-1.dll",
|
||||
"gswin32c.exe",
|
||||
"dot.exe",
|
||||
"libgvplugin_core-6.dll",
|
||||
"libgvplugin_dot_layout-6.dll",
|
||||
"libgvplugin_gd-6.dll",
|
||||
"libgvplugin_pango-6.dll",
|
||||
"libgvplugin_rsvg-6.dll",
|
||||
"glib-compile-schemas.exe",
|
||||
"gdk-pixbuf-query-loaders.exe",
|
||||
"gtk-update-icon-cache-3.0.exe",
|
||||
"fc-cache.exe",
|
||||
"fc-match.exe",
|
||||
"gspawn-win64-helper-console.exe",
|
||||
"gspawn-win64-helper.exe",
|
||||
"libgeocode-glib-0.dll",
|
||||
]
|
||||
BIN_EXCLUDES = ['Qt5Core.dll', 'gdiplus.dll', 'gdiplus']
|
||||
BIN_EXCLUDES = ["Qt5Core.dll", "gdiplus.dll", "gdiplus"]
|
||||
|
||||
from os.path import dirname, basename
|
||||
import lib2to3
|
||||
lib23_path = dirname(lib2to3.__file__)
|
||||
INCLUDE_FILES.append((lib23_path, 'lib/lib2to3'))
|
||||
import pip
|
||||
libpip_path = dirname(pip.__file__)
|
||||
INCLUDE_FILES.append((libpip_path,'lib/pip'))
|
||||
import distlib
|
||||
libdistlib_path = dirname(distlib.__file__)
|
||||
INCLUDE_FILES.append((libdistlib_path,'lib/distlib'))
|
||||
|
||||
os.makedirs(os.path.join(BASE_DIR, 'var/cache/fontconfig'), exist_ok=True)
|
||||
lib23_path = dirname(lib2to3.__file__)
|
||||
INCLUDE_FILES.append((lib23_path, "lib/lib2to3"))
|
||||
import pip
|
||||
|
||||
libpip_path = dirname(pip.__file__)
|
||||
INCLUDE_FILES.append((libpip_path, "lib/pip"))
|
||||
import distlib
|
||||
|
||||
libdistlib_path = dirname(distlib.__file__)
|
||||
INCLUDE_FILES.append((libdistlib_path, "lib/distlib"))
|
||||
|
||||
os.makedirs(os.path.join(BASE_DIR, "var/cache/fontconfig"), exist_ok=True)
|
||||
for file in SETUP_FILES:
|
||||
INCLUDE_FILES.append((os.path.join(SETUP_DIR, file),
|
||||
os.path.join('src', file)))
|
||||
INCLUDE_FILES.append((os.path.join(SETUP_DIR, file), os.path.join("src", file)))
|
||||
for dll in MISSING_DLL:
|
||||
INCLUDE_FILES.append((os.path.join(INCLUDE_DLL_PATH, dll),
|
||||
os.path.join('lib',dll)))
|
||||
MISSING_LIBS = ['lib/enchant-2', 'lib/gdk-pixbuf-2.0', 'lib/girepository-1.0',
|
||||
'share/enchant', 'share/glib-2.0/schemas',
|
||||
'share/xml/iso-codes', 'etc/gtk-3.0',
|
||||
'etc/ssl/certs', 'etc/ssl/cert.pem', 'etc/fonts', 'lib/gio',
|
||||
'share/icons/gnome',
|
||||
'share/icons/hicolor', 'share/icons/gramps.png',
|
||||
'share/icons/Adwaita/icon-theme.cache',
|
||||
'share/icons/Adwaita/index.theme', 'share/hunspell'
|
||||
INCLUDE_FILES.append(
|
||||
(os.path.join(INCLUDE_DLL_PATH, dll), os.path.join("lib", dll))
|
||||
)
|
||||
MISSING_LIBS = [
|
||||
"lib/enchant-2",
|
||||
"lib/gdk-pixbuf-2.0",
|
||||
"lib/girepository-1.0",
|
||||
"share/enchant",
|
||||
"share/glib-2.0/schemas",
|
||||
"share/xml/iso-codes",
|
||||
"etc/gtk-3.0",
|
||||
"etc/ssl/certs",
|
||||
"etc/ssl/cert.pem",
|
||||
"etc/fonts",
|
||||
"lib/gio",
|
||||
"share/icons/gnome",
|
||||
"share/icons/hicolor",
|
||||
"share/icons/gramps.png",
|
||||
"share/icons/Adwaita/icon-theme.cache",
|
||||
"share/icons/Adwaita/index.theme",
|
||||
"share/hunspell",
|
||||
]
|
||||
ADWAITA = ['8x8', '16x16', '22x22', '24x24', '32x32', '48x48', '64x64',
|
||||
'96x96', 'cursors'
|
||||
ADWAITA = [
|
||||
"8x8",
|
||||
"16x16",
|
||||
"22x22",
|
||||
"24x24",
|
||||
"32x32",
|
||||
"48x48",
|
||||
"64x64",
|
||||
"96x96",
|
||||
"cursors",
|
||||
]
|
||||
for adw in ADWAITA:
|
||||
INCLUDE_FILES.append((os.path.join(sys.prefix, 'share/icons/Adwaita', adw),
|
||||
os.path.join('share/icons/Adwaita', adw)))
|
||||
INCLUDE_FILES.append(
|
||||
(
|
||||
os.path.join(sys.prefix, "share/icons/Adwaita", adw),
|
||||
os.path.join("share/icons/Adwaita", adw),
|
||||
)
|
||||
)
|
||||
for lib in MISSING_LIBS:
|
||||
INCLUDE_FILES.append((os.path.join(sys.prefix, lib), lib))
|
||||
|
||||
INCLUDE_FILES.append('dist/gramps')
|
||||
INCLUDE_FILES.append(('dist/gramps-' + '.'.join(map(str, VERSION_TUPLE)) + '.data/data/share','share'))
|
||||
EXECUTABLES = [cx_Freeze.Executable("grampsaioc.py", base="Console",
|
||||
target_name='gramps.exe',
|
||||
icon='gramps.ico', copyright=COPYRIGHT),
|
||||
cx_Freeze.Executable("grampsaiow.py", base="Win32GUI",
|
||||
target_name='grampsw.exe',
|
||||
icon='gramps.ico', copyright=COPYRIGHT),
|
||||
cx_Freeze.Executable("grampsaiocd.py", base="Console",
|
||||
target_name='grampsd.exe',
|
||||
icon='grampsd.ico', copyright=COPYRIGHT)
|
||||
INCLUDE_FILES.append("dist/gramps")
|
||||
INCLUDE_FILES.append(
|
||||
("dist/gramps-" + ".".join(map(str, VERSION_TUPLE)) + ".data/data/share", "share")
|
||||
)
|
||||
EXECUTABLES = [
|
||||
cx_Freeze.Executable(
|
||||
"grampsaioc.py",
|
||||
base="Console",
|
||||
target_name="gramps.exe",
|
||||
icon="gramps.ico",
|
||||
copyright=COPYRIGHT,
|
||||
),
|
||||
cx_Freeze.Executable(
|
||||
"grampsaiow.py",
|
||||
base="Win32GUI",
|
||||
target_name="grampsw.exe",
|
||||
icon="gramps.ico",
|
||||
copyright=COPYRIGHT,
|
||||
),
|
||||
cx_Freeze.Executable(
|
||||
"grampsaiocd.py",
|
||||
base="Console",
|
||||
target_name="grampsd.exe",
|
||||
icon="grampsd.ico",
|
||||
copyright=COPYRIGHT,
|
||||
),
|
||||
]
|
||||
BUILD_EXE_OPTIONS = {'packages':PACKAGES,
|
||||
'includes':INCLUDES,
|
||||
'excludes':EXCLUDES,
|
||||
'include_files':INCLUDE_FILES,
|
||||
'bin_includes':MISSING_DLL,
|
||||
'zip_include_packages': '*', #ZIP_INCLUDE_PACKAGES,
|
||||
'zip_exclude_packages':EXCLUDES,
|
||||
'bin_excludes':BIN_EXCLUDES,
|
||||
'replace_paths':REPLACE_PATHS,
|
||||
'build_exe':BASE_DIR,
|
||||
BUILD_EXE_OPTIONS = {
|
||||
"packages": PACKAGES,
|
||||
"includes": INCLUDES,
|
||||
"excludes": EXCLUDES,
|
||||
"include_files": INCLUDE_FILES,
|
||||
"bin_includes": MISSING_DLL,
|
||||
"zip_include_packages": "*", # ZIP_INCLUDE_PACKAGES,
|
||||
"zip_exclude_packages": EXCLUDES,
|
||||
"bin_excludes": BIN_EXCLUDES,
|
||||
"replace_paths": REPLACE_PATHS,
|
||||
"build_exe": BASE_DIR,
|
||||
}
|
||||
BDIST_MSI_OPTIONS = { # uuid.uuid5(uuid.NAMESPACE_DNS, 'GrampsAIO64-5-trunk')
|
||||
'upgrade_code': '{fbccc04b-7b2e-56d3-8bb7-94d5f68de822}',
|
||||
"upgrade_code": "{fbccc04b-7b2e-56d3-8bb7-94d5f68de822}",
|
||||
# uuid.uuid5(uuid.NAMESPACE_DNS, 'v5.0.0-alpha1-476-g473d3aa')
|
||||
'product_code': '{48304362-2945-5a10-ad60-241f233be4d2}',
|
||||
'add_to_path': False,
|
||||
"product_code": "{48304362-2945-5a10-ad60-241f233be4d2}",
|
||||
"add_to_path": False,
|
||||
#'initial_target_dir': r'[ProgramFilesFolder]\%s\%s' %
|
||||
# (company_name, product_name),
|
||||
}
|
||||
cx_Freeze.setup(
|
||||
name="GrampsAIO32" if '32' in BASE_DIR else "GrampsAIO64",
|
||||
options={"build_exe": BUILD_EXE_OPTIONS, 'bdist_msi': BDIST_MSI_OPTIONS},
|
||||
name="GrampsAIO32" if "32" in BASE_DIR else "GrampsAIO64",
|
||||
options={"build_exe": BUILD_EXE_OPTIONS, "bdist_msi": BDIST_MSI_OPTIONS},
|
||||
version=VERSION,
|
||||
description="Gramps Genealogy software",
|
||||
long_description=VERSION_QUALIFIER,
|
||||
executables=EXECUTABLES)
|
||||
executables=EXECUTABLES,
|
||||
)
|
||||
|
||||
ZIN = zipfile.ZipFile(os.path.join(BASE_DIR, 'lib/library.zip'), 'r')
|
||||
ZOUT = zipfile.ZipFile(os.path.join(BASE_DIR, 'lib/pythonx.zip'), 'w')
|
||||
ZIN = zipfile.ZipFile(os.path.join(BASE_DIR, "lib/library.zip"), "r")
|
||||
ZOUT = zipfile.ZipFile(os.path.join(BASE_DIR, "lib/pythonx.zip"), "w")
|
||||
for item in ZIN.infolist():
|
||||
if not os.path.dirname(item.filename).startswith('gramps'):
|
||||
if not os.path.dirname(item.filename).startswith("gramps"):
|
||||
# if '/test' in item.filename or 'test/' in item.filename:
|
||||
# print("Zip Excluded:", item.filename)
|
||||
# else:
|
||||
@@ -154,28 +254,30 @@ for item in ZIN.infolist():
|
||||
ZOUT.writestr(item, buffer)
|
||||
ZOUT.close()
|
||||
ZIN.close()
|
||||
shutil.move(os.path.join(BASE_DIR, 'lib/pythonx.zip'),
|
||||
os.path.join(BASE_DIR, 'lib/library.zip'))
|
||||
shutil.move(
|
||||
os.path.join(BASE_DIR, "lib/pythonx.zip"), os.path.join(BASE_DIR, "lib/library.zip")
|
||||
)
|
||||
|
||||
if os.path.isfile(UPX_ALT_PATH):
|
||||
UPX = UPX_ALT_PATH
|
||||
else:
|
||||
WHICH = 'where' if os.name == 'nt' else 'which'
|
||||
WHICH = "where" if os.name == "nt" else "which"
|
||||
try:
|
||||
subprocess.check_call([WHICH, 'UPX'])
|
||||
subprocess.check_call([WHICH, "UPX"])
|
||||
except subprocess.CalledProcessError:
|
||||
UPX = None
|
||||
else:
|
||||
UPX = 'upx'
|
||||
UPX = "upx"
|
||||
if UPX is not None:
|
||||
ARGS = [UPX, '-7', '--no-progress']
|
||||
ARGS.extend(os.path.join(BASE_DIR, filename) for filename in
|
||||
os.listdir(BASE_DIR) if filename == 'name' or
|
||||
os.path.splitext(filename)[1].lower() in
|
||||
('.exe', '.dll', '.pyd', '.so') and
|
||||
os.path.splitext(filename)[0].lower() not in
|
||||
('libgcc_s_dw2-1', 'gramps', 'grampsw', 'grampsd',
|
||||
'libwinpthread-1'))
|
||||
ARGS = [UPX, "-7", "--no-progress"]
|
||||
ARGS.extend(
|
||||
os.path.join(BASE_DIR, filename)
|
||||
for filename in os.listdir(BASE_DIR)
|
||||
if filename == "name"
|
||||
or os.path.splitext(filename)[1].lower() in (".exe", ".dll", ".pyd", ".so")
|
||||
and os.path.splitext(filename)[0].lower()
|
||||
not in ("libgcc_s_dw2-1", "gramps", "grampsw", "grampsd", "libwinpthread-1")
|
||||
)
|
||||
subprocess.call(ARGS)
|
||||
else:
|
||||
print("\nUPX not found")
|
||||
|
@@ -28,29 +28,29 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -61,11 +61,11 @@ release = '4.2.0'
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%B %d, %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('en', 'gramps', u'Gramps Documentation',
|
||||
['Gramps project'], 1)
|
||||
]
|
||||
man_pages = [("en", "gramps", "Gramps Documentation", ["Gramps project"], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -28,44 +28,44 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'cs'
|
||||
master_doc = "cs"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
locale_dirs = './locale'
|
||||
locale_dirs = "./locale"
|
||||
gettext_compact = True
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%B %d, %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('cs', 'gramps', u'Gramps Documentation',
|
||||
[u'.'], 1)
|
||||
]
|
||||
man_pages = [("cs", "gramps", "Gramps Documentation", ["."], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -28,44 +28,44 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'fr'
|
||||
master_doc = "fr"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
locale_dirs = './locale'
|
||||
locale_dirs = "./locale"
|
||||
gettext_compact = True
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%d %B %Y'
|
||||
today_fmt = "%d %B %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('fr', 'gramps', u'Gramps Documentation',
|
||||
['Jerome Rapinat'], 1)
|
||||
]
|
||||
man_pages = [("fr", "gramps", "Gramps Documentation", ["Jerome Rapinat"], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -28,44 +28,44 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'nl'
|
||||
master_doc = "nl"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
locale_dirs = './locale'
|
||||
locale_dirs = "./locale"
|
||||
gettext_compact = True
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%B %d, %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('nl', 'gramps', u'Gramps Documentation',
|
||||
[u'.'], 1)
|
||||
]
|
||||
man_pages = [("nl", "gramps", "Gramps Documentation", ["."], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -28,44 +28,44 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'pl'
|
||||
master_doc = "pl"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
locale_dirs = './locale'
|
||||
locale_dirs = "./locale"
|
||||
gettext_compact = True
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%B %d, %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('pl', 'gramps', u'Gramps Documentation',
|
||||
[u'.'], 1)
|
||||
]
|
||||
man_pages = [("pl", "gramps", "Gramps Documentation", ["."], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -28,44 +28,44 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'pt_BR'
|
||||
master_doc = "pt_BR"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
locale_dirs = './locale'
|
||||
locale_dirs = "./locale"
|
||||
gettext_compact = True
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%B %d, %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('pt_BR', 'gramps', u'Gramps Documentation',
|
||||
[u'.'], 1)
|
||||
]
|
||||
man_pages = [("pt_BR", "gramps", "Gramps Documentation", ["."], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -28,44 +28,44 @@ import sys, os
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'sv'
|
||||
master_doc = "sv"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Gramps'
|
||||
copyright = u'2015, Gramps project'
|
||||
project = "Gramps"
|
||||
copyright = "2015, Gramps project"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.2'
|
||||
version = "4.2"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.2.0'
|
||||
release = "4.2.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
locale_dirs = './locale'
|
||||
locale_dirs = "./locale"
|
||||
gettext_compact = True
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%B %d, %Y"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
@@ -82,7 +82,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -92,7 +92,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "default"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -165,7 +165,7 @@ html_theme = 'default'
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -173,10 +173,8 @@ htmlhelp_basename = 'Grampsdoc'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
@@ -184,8 +182,7 @@ latex_elements = {
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Gramps.tex', u'Gramps Documentation',
|
||||
u'.', 'manual'),
|
||||
("index", "Gramps.tex", "Gramps Documentation", ".", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -213,10 +210,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('sv', 'gramps', u'Gramps Documentation',
|
||||
[u'.'], 1)
|
||||
]
|
||||
man_pages = [("sv", "gramps", "Gramps Documentation", ["."], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -228,9 +222,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Gramps', u'Gramps Documentation',
|
||||
u'.', 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
".",
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -42,23 +42,24 @@ try:
|
||||
except:
|
||||
DOCUTILS = False
|
||||
|
||||
LANGUAGES = ['sv', 'nl', 'pl', 'cs', 'pt_BR', 'fr']
|
||||
VERSION = '5.0.0'
|
||||
DATE = ''
|
||||
LANGUAGES = ["sv", "nl", "pl", "cs", "pt_BR", "fr"]
|
||||
VERSION = "5.0.0"
|
||||
DATE = ""
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXBUILD = 'sphinx-build'
|
||||
SPHINXBUILD = "sphinx-build"
|
||||
|
||||
if sys.platform == 'win32':
|
||||
pythonCmd = os.path.join(sys.prefix, 'bin', 'python.exe')
|
||||
sphinxCmd = os.path.join(sys.prefix, 'bin', 'sphinx-build.exe')
|
||||
elif sys.platform in ['linux2', 'darwin', 'cygwin']:
|
||||
pythonCmd = os.path.join(sys.prefix, 'bin', 'python')
|
||||
if sys.platform == "win32":
|
||||
pythonCmd = os.path.join(sys.prefix, "bin", "python.exe")
|
||||
sphinxCmd = os.path.join(sys.prefix, "bin", "sphinx-build.exe")
|
||||
elif sys.platform in ["linux2", "darwin", "cygwin"]:
|
||||
pythonCmd = os.path.join(sys.prefix, "bin", "python")
|
||||
sphinxCmd = SPHINXBUILD
|
||||
else:
|
||||
print("Update Man ERROR: unknown system, don't know sphinx, ... commands")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def tests():
|
||||
"""
|
||||
Testing installed programs.
|
||||
@@ -67,18 +68,19 @@ def tests():
|
||||
"""
|
||||
try:
|
||||
print("\n=================='python'=============================\n")
|
||||
os.system('''%(program)s -V''' % {'program': pythonCmd})
|
||||
os.system("""%(program)s -V""" % {"program": pythonCmd})
|
||||
except:
|
||||
print ('Please, install python')
|
||||
print("Please, install python")
|
||||
|
||||
try:
|
||||
print("\n=================='Sphinx-build'=============================\n")
|
||||
os.system('''%(program)s''' % {'program': sphinxCmd})
|
||||
os.system("""%(program)s""" % {"program": sphinxCmd})
|
||||
except:
|
||||
print ('Please, install sphinx')
|
||||
print("Please, install sphinx")
|
||||
|
||||
if not DOCUTILS:
|
||||
print('\nNo docutils support, cannot use -m/--man and -o/--odt arguments.')
|
||||
print("\nNo docutils support, cannot use -m/--man and -o/--odt arguments.")
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
@@ -87,25 +89,45 @@ def main():
|
||||
"""
|
||||
|
||||
parser = ArgumentParser(
|
||||
description='This program aims to handle documentation'
|
||||
' and related translated versions.',
|
||||
description="This program aims to handle documentation"
|
||||
" and related translated versions.",
|
||||
)
|
||||
|
||||
parser.add_argument("-t", "--test",
|
||||
action="store_true", dest="test", default=True,
|
||||
help="test if 'python' and 'sphinx' are properly installed")
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--test",
|
||||
action="store_true",
|
||||
dest="test",
|
||||
default=True,
|
||||
help="test if 'python' and 'sphinx' are properly installed",
|
||||
)
|
||||
|
||||
parser.add_argument("-b", "--build",
|
||||
action="store_true", dest="build", default=False,
|
||||
help="build man documentation (via sphinx-build)")
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--build",
|
||||
action="store_true",
|
||||
dest="build",
|
||||
default=False,
|
||||
help="build man documentation (via sphinx-build)",
|
||||
)
|
||||
|
||||
parser.add_argument("-m", "--man",
|
||||
action="store_true", dest="man", default=False,
|
||||
help="build man documentation (via docutils)")
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
"--man",
|
||||
action="store_true",
|
||||
dest="man",
|
||||
default=False,
|
||||
help="build man documentation (via docutils)",
|
||||
)
|
||||
|
||||
parser.add_argument("-o", "--odt",
|
||||
action="store_true", dest="odt", default=False,
|
||||
help="build odt documentation (via docutils)")
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--odt",
|
||||
action="store_true",
|
||||
dest="odt",
|
||||
default=False,
|
||||
help="build odt documentation (via docutils)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -121,6 +143,7 @@ def main():
|
||||
if args.odt and DOCUTILS:
|
||||
odt()
|
||||
|
||||
|
||||
def build():
|
||||
"""
|
||||
Build documentation.
|
||||
@@ -128,28 +151,39 @@ def build():
|
||||
|
||||
# testing stage
|
||||
|
||||
os.system('''%(program)s -b html . _build/html''' % {'program': sphinxCmd})
|
||||
os.system('''%(program)s -b htmlhelp . _build/htmlhelp''' % {'program': sphinxCmd})
|
||||
os.system("""%(program)s -b html . _build/html""" % {"program": sphinxCmd})
|
||||
os.system("""%(program)s -b htmlhelp . _build/htmlhelp""" % {"program": sphinxCmd})
|
||||
if DOCUTILS:
|
||||
os.system('''%(program)s -b man . .''' % {'program': sphinxCmd})
|
||||
os.system('''%(program)s -b text . _build/text''' % {'program': sphinxCmd})
|
||||
os.system('''%(program)s -b changes . _build/changes''' % {'program': sphinxCmd})
|
||||
os.system("""%(program)s -b man . .""" % {"program": sphinxCmd})
|
||||
os.system("""%(program)s -b text . _build/text""" % {"program": sphinxCmd})
|
||||
os.system("""%(program)s -b changes . _build/changes""" % {"program": sphinxCmd})
|
||||
# os.system('''%(program)s -b linkcheck . _build/linkcheck''' % {'program': sphinxCmd})
|
||||
os.system('''%(program)s -b gettext . _build/gettext''' % {'program': sphinxCmd})
|
||||
os.system("""%(program)s -b gettext . _build/gettext""" % {"program": sphinxCmd})
|
||||
|
||||
for lang in LANGUAGES:
|
||||
os.system('''%(program)s -b html -D language="%(lang)s" master_doc="%(lang)s" %(lang)s %(lang)s'''
|
||||
% {'lang': lang, 'program': sphinxCmd})
|
||||
os.system('''%(program)s -b htmlhelp -D language="%(lang)s" master_doc="%(lang)s" %(lang)s %(lang)s'''
|
||||
% {'lang': lang, 'program': sphinxCmd})
|
||||
os.system(
|
||||
"""%(program)s -b html -D language="%(lang)s" master_doc="%(lang)s" %(lang)s %(lang)s"""
|
||||
% {"lang": lang, "program": sphinxCmd}
|
||||
)
|
||||
os.system(
|
||||
"""%(program)s -b htmlhelp -D language="%(lang)s" master_doc="%(lang)s" %(lang)s %(lang)s"""
|
||||
% {"lang": lang, "program": sphinxCmd}
|
||||
)
|
||||
if DOCUTILS:
|
||||
os.system('''%(program)s -b man %(lang)s %(lang)s'''
|
||||
% {'lang': lang, 'program': sphinxCmd})
|
||||
os.system('''%(program)s -b text -D language="%(lang)s" master_doc="%(lang)s" %(lang)s %(lang)s'''
|
||||
% {'lang': lang, 'program': sphinxCmd})
|
||||
os.system(
|
||||
"""%(program)s -b man %(lang)s %(lang)s"""
|
||||
% {"lang": lang, "program": sphinxCmd}
|
||||
)
|
||||
os.system(
|
||||
"""%(program)s -b text -D language="%(lang)s" master_doc="%(lang)s" %(lang)s %(lang)s"""
|
||||
% {"lang": lang, "program": sphinxCmd}
|
||||
)
|
||||
# for update/migration
|
||||
os.system('''%(program)s -b gettext -D language="%(lang)s" master_doc="%(lang)s" . _build/gettext/%(lang)s'''
|
||||
% {'lang': lang, 'program': sphinxCmd})
|
||||
os.system(
|
||||
"""%(program)s -b gettext -D language="%(lang)s" master_doc="%(lang)s" . _build/gettext/%(lang)s"""
|
||||
% {"lang": lang, "program": sphinxCmd}
|
||||
)
|
||||
|
||||
|
||||
def man():
|
||||
"""
|
||||
@@ -159,11 +193,14 @@ def man():
|
||||
from docutils.writers import manpage
|
||||
"""
|
||||
|
||||
os.system('''rst2man en.rst gramps.1''')
|
||||
os.system("""rst2man en.rst gramps.1""")
|
||||
|
||||
for lang in LANGUAGES:
|
||||
os.system('''rst2man %(lang)s/%(lang)s.rst -l %(lang)s %(lang)s/gramps.1'''
|
||||
% {'lang': lang})
|
||||
os.system(
|
||||
"""rst2man %(lang)s/%(lang)s.rst -l %(lang)s %(lang)s/gramps.1"""
|
||||
% {"lang": lang}
|
||||
)
|
||||
|
||||
|
||||
def odt():
|
||||
"""
|
||||
@@ -173,11 +210,14 @@ def odt():
|
||||
from docutils.writers.odf_odt import Writer, Reader
|
||||
"""
|
||||
|
||||
os.system('''rst2odt en.rst gramps.odt''')
|
||||
os.system("""rst2odt en.rst gramps.odt""")
|
||||
|
||||
for lang in LANGUAGES:
|
||||
os.system('''rst2odt %(lang)s/%(lang)s.rst -l %(lang)s %(lang)s/gramps.odt'''
|
||||
% {'lang': lang})
|
||||
os.system(
|
||||
"""rst2odt %(lang)s/%(lang)s.rst -l %(lang)s %(lang)s/gramps.odt"""
|
||||
% {"lang": lang}
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
63
docs/conf.py
63
docs/conf.py
@@ -34,40 +34,40 @@ sys.path.append(os.path.abspath(os.pardir))
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.viewcode',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinx.ext.viewcode",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = 'Gramps'
|
||||
copyright = '2001-2019, The Gramps Project'
|
||||
author = 'Donald N. Allingham'
|
||||
project = "Gramps"
|
||||
copyright = "2001-2019, The Gramps Project"
|
||||
author = "Donald N. Allingham"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '5.1.0'
|
||||
version = "5.1.0"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '5.1.0'
|
||||
release = "5.1.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -84,7 +84,7 @@ language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
@@ -102,7 +102,7 @@ exclude_patterns = ['_build']
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
@@ -118,7 +118,7 @@ todo_include_todos = True
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes. default: alabaster
|
||||
html_theme = 'classic'
|
||||
html_theme = "classic"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -211,20 +211,17 @@ html_static_path = []
|
||||
# html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Grampsdoc'
|
||||
htmlhelp_basename = "Grampsdoc"
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
}
|
||||
@@ -233,8 +230,13 @@ latex_elements = {
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('master_doc', 'Gramps.tex', 'Gramps Documentation',
|
||||
'The Gramps Project', 'manual'),
|
||||
(
|
||||
"master_doc",
|
||||
"Gramps.tex",
|
||||
"Gramps Documentation",
|
||||
"The Gramps Project",
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -262,10 +264,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'gramps', 'Gramps Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
man_pages = [(master_doc, "gramps", "Gramps Documentation", [author], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -277,9 +276,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'Gramps', 'Gramps Documentation',
|
||||
author, 'Gramps', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
master_doc,
|
||||
"Gramps",
|
||||
"Gramps Documentation",
|
||||
author,
|
||||
"Gramps",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@@ -37,18 +37,19 @@ import sys
|
||||
from argparse import ArgumentParser
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXBUILD = 'sphinx-build'
|
||||
SPHINXBUILD = "sphinx-build"
|
||||
|
||||
if sys.platform == 'win32':
|
||||
pythonCmd = os.path.join(sys.prefix, 'bin', 'python.exe')
|
||||
sphinxCmd = os.path.join(sys.prefix, 'bin', 'sphinx-build.exe')
|
||||
elif sys.platform in ['linux', 'linux2', 'darwin', 'cygwin']:
|
||||
pythonCmd = os.path.join(sys.prefix, 'bin', 'python')
|
||||
if sys.platform == "win32":
|
||||
pythonCmd = os.path.join(sys.prefix, "bin", "python.exe")
|
||||
sphinxCmd = os.path.join(sys.prefix, "bin", "sphinx-build.exe")
|
||||
elif sys.platform in ["linux", "linux2", "darwin", "cygwin"]:
|
||||
pythonCmd = os.path.join(sys.prefix, "bin", "python")
|
||||
sphinxCmd = SPHINXBUILD
|
||||
else:
|
||||
print("Update Docs ERROR: unknown system, don't know sphinx, ... commands")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def tests():
|
||||
"""
|
||||
Testing installed programs.
|
||||
@@ -57,15 +58,16 @@ def tests():
|
||||
"""
|
||||
try:
|
||||
print("\n=================='python'=============================\n")
|
||||
os.system('''%(program)s -V''' % {'program': pythonCmd})
|
||||
os.system("""%(program)s -V""" % {"program": pythonCmd})
|
||||
except:
|
||||
print ('Please, install python')
|
||||
print("Please, install python")
|
||||
|
||||
try:
|
||||
print("\n=================='sphinx-build'=============================\n")
|
||||
os.system('''%(program)s''' % {'program': sphinxCmd})
|
||||
os.system("""%(program)s""" % {"program": sphinxCmd})
|
||||
except:
|
||||
print ('Please, install sphinx')
|
||||
print("Please, install sphinx")
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
@@ -74,17 +76,26 @@ def main():
|
||||
"""
|
||||
|
||||
parser = ArgumentParser(
|
||||
description='This program aims to handle manual'
|
||||
' and translated version.',
|
||||
description="This program aims to handle manual" " and translated version.",
|
||||
)
|
||||
|
||||
parser.add_argument("-t", "--test",
|
||||
action="store_true", dest="test", default=True,
|
||||
help="test if 'python' and 'sphinx' are properly installed")
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--test",
|
||||
action="store_true",
|
||||
dest="test",
|
||||
default=True,
|
||||
help="test if 'python' and 'sphinx' are properly installed",
|
||||
)
|
||||
|
||||
parser.add_argument("-b", "--build",
|
||||
action="store_true", dest="build", default=True,
|
||||
help="build documentation")
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--build",
|
||||
action="store_true",
|
||||
dest="build",
|
||||
default=True,
|
||||
help="build documentation",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -94,6 +105,7 @@ def main():
|
||||
if args.build:
|
||||
build()
|
||||
|
||||
|
||||
def build():
|
||||
"""
|
||||
Build documentation.
|
||||
@@ -101,10 +113,11 @@ def build():
|
||||
|
||||
# testing stage
|
||||
|
||||
os.system('''%(program)s -b html . _build/html''' % {'program': sphinxCmd})
|
||||
os.system("""%(program)s -b html . _build/html""" % {"program": sphinxCmd})
|
||||
# os.system('''%(program)s -b changes . _build/changes''' % {'program': sphinxCmd})
|
||||
# os.system('''%(program)s -b linkcheck . _build/linkcheck''' % {'program': sphinxCmd})
|
||||
# os.system('''%(program)s -b devhelp . _build/devhelp''' % {'program': sphinxCmd})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -52,9 +52,11 @@ from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.plug.report import CATEGORY_BOOK, CATEGORY_CODE, BookList
|
||||
from .plug import cl_report, cl_book
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.config import config
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# private functions
|
||||
@@ -110,11 +112,11 @@ def _split_options(options_str):
|
||||
name += char
|
||||
else:
|
||||
# Parsing the value of the option
|
||||
if value == "" and char == '[':
|
||||
if value == "" and char == "[":
|
||||
# print char, "This character begins a list"
|
||||
in_list = True
|
||||
value += char
|
||||
elif in_list == True and char == ']':
|
||||
elif in_list == True and char == "]":
|
||||
# print char, "This character ends the list"
|
||||
in_list = False
|
||||
value += char
|
||||
@@ -145,6 +147,7 @@ def _split_options(options_str):
|
||||
|
||||
return options_str_dict
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ArgHandler
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -155,8 +158,7 @@ class ArgHandler:
|
||||
actions requested working on a :class:`.DbState`.
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, parser, sessionmanager,
|
||||
errorfunc=None, gui=False):
|
||||
def __init__(self, dbstate, parser, sessionmanager, errorfunc=None, gui=False):
|
||||
self.dbstate = dbstate
|
||||
self.smgr = sessionmanager
|
||||
self.errorfunc = errorfunc
|
||||
@@ -205,9 +207,9 @@ class ArgHandler:
|
||||
"""
|
||||
Check the lists with open, exports, imports, and actions options.
|
||||
"""
|
||||
for (value, family_tree_format) in importlist:
|
||||
for value, family_tree_format in importlist:
|
||||
self.__handle_import_option(value, family_tree_format)
|
||||
for (value, family_tree_format) in exportlist:
|
||||
for value, family_tree_format in exportlist:
|
||||
self.__handle_export_option(value, family_tree_format)
|
||||
|
||||
def __handle_open_option(self, value, create):
|
||||
@@ -226,22 +228,29 @@ class ArgHandler:
|
||||
if not self.check_db(db_path, self.force_unlock):
|
||||
sys.exit(1)
|
||||
if create:
|
||||
self.__error(_("Error: Family Tree '%s' already exists.\n"
|
||||
self.__error(
|
||||
_(
|
||||
"Error: Family Tree '%s' already exists.\n"
|
||||
"The '-C' option cannot be used."
|
||||
) % value)
|
||||
)
|
||||
% value
|
||||
)
|
||||
sys.exit(1)
|
||||
return db_path
|
||||
elif create:
|
||||
# create the tree here, and continue
|
||||
dbid = config.get('database.backend')
|
||||
db_path, title = self.dbman.create_new_db_cli(title=value,
|
||||
dbid=dbid)
|
||||
dbid = config.get("database.backend")
|
||||
db_path, title = self.dbman.create_new_db_cli(title=value, dbid=dbid)
|
||||
return db_path
|
||||
else:
|
||||
self.__error(_('Error: Input Family Tree "%s" does not exist.\n'
|
||||
self.__error(
|
||||
_(
|
||||
'Error: Input Family Tree "%s" does not exist.\n'
|
||||
"If GEDCOM, Gramps-xml or grdb, use the -i option "
|
||||
"to import into a Family Tree instead."
|
||||
) % value)
|
||||
)
|
||||
% value
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
def __handle_import_option(self, value, family_tree_format):
|
||||
@@ -251,8 +260,8 @@ class ArgHandler:
|
||||
"""
|
||||
fname = value
|
||||
fullpath = os.path.abspath(os.path.expanduser(fname))
|
||||
if fname != '-' and not os.path.exists(fullpath):
|
||||
self.__error(_('Error: Import file %s not found.') % fname)
|
||||
if fname != "-" and not os.path.exists(fullpath):
|
||||
self.__error(_("Error: Import file %s not found.") % fname)
|
||||
sys.exit(1)
|
||||
|
||||
if family_tree_format is None:
|
||||
@@ -270,10 +279,13 @@ class ArgHandler:
|
||||
if plugin_found:
|
||||
self.imports.append((fname, family_tree_format))
|
||||
else:
|
||||
self.__error(_('Error: Unrecognized type: "%(format)s" for '
|
||||
'import file: %(filename)s'
|
||||
) % {'format' : family_tree_format,
|
||||
'filename' : fname})
|
||||
self.__error(
|
||||
_(
|
||||
'Error: Unrecognized type: "%(format)s" for '
|
||||
"import file: %(filename)s"
|
||||
)
|
||||
% {"format": family_tree_format, "filename": fname}
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
def __handle_export_option(self, value, family_tree_format):
|
||||
@@ -285,20 +297,27 @@ class ArgHandler:
|
||||
if self.gui:
|
||||
return
|
||||
fname = value
|
||||
if fname == '-':
|
||||
fullpath = '-'
|
||||
if fname == "-":
|
||||
fullpath = "-"
|
||||
else:
|
||||
fullpath = os.path.abspath(os.path.expanduser(fname))
|
||||
if os.path.exists(fullpath):
|
||||
message = _("WARNING: Output file already exists!\n"
|
||||
message = (
|
||||
_(
|
||||
"WARNING: Output file already exists!\n"
|
||||
"WARNING: It will be overwritten:\n %s"
|
||||
) % fullpath
|
||||
accepted = self.user.prompt(_('OK to overwrite?'), message,
|
||||
_('yes'), _('no'),
|
||||
default_label=_('yes'))
|
||||
)
|
||||
% fullpath
|
||||
)
|
||||
accepted = self.user.prompt(
|
||||
_("OK to overwrite?"),
|
||||
message,
|
||||
_("yes"),
|
||||
_("no"),
|
||||
default_label=_("yes"),
|
||||
)
|
||||
if accepted:
|
||||
self.__error(_("Will overwrite the existing file: %s"
|
||||
) % fullpath)
|
||||
self.__error(_("Will overwrite the existing file: %s") % fullpath)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -317,8 +336,7 @@ class ArgHandler:
|
||||
if plugin_found:
|
||||
self.exports.append((fullpath, family_tree_format))
|
||||
else:
|
||||
self.__error(_("ERROR: Unrecognized format for export file %s"
|
||||
) % fname)
|
||||
self.__error(_("ERROR: Unrecognized format for export file %s") % fname)
|
||||
sys.exit(1)
|
||||
|
||||
def __deduce_db_path(self, db_name_or_path):
|
||||
@@ -368,8 +386,7 @@ class ArgHandler:
|
||||
if not db_path:
|
||||
# Apparently it is not a database. See if it is a file that
|
||||
# can be imported.
|
||||
db_path, title = self.dbman.import_new_db(self.open_gui,
|
||||
self.user)
|
||||
db_path, title = self.dbman.import_new_db(self.open_gui, self.user)
|
||||
|
||||
if db_path:
|
||||
# Test if not locked or problematic
|
||||
@@ -402,17 +419,21 @@ class ArgHandler:
|
||||
"""
|
||||
# Handle the "-l" List Family Trees option.
|
||||
if self.list:
|
||||
print(_('List of known Family Trees in your database path\n'))
|
||||
print(_("List of known Family Trees in your database path\n"))
|
||||
|
||||
for name, dirname in sorted(self.dbman.family_tree_list(),
|
||||
key=lambda pair: pair[0].lower()):
|
||||
if (self.database_names is None
|
||||
or any([(re.match("^" + dbname + "$", name)
|
||||
or dbname == name)
|
||||
for dbname in self.database_names])):
|
||||
print(_('%(full_DB_path)s with name "%(f_t_name)s"'
|
||||
) % {'full_DB_path' : dirname,
|
||||
'f_t_name' : name})
|
||||
for name, dirname in sorted(
|
||||
self.dbman.family_tree_list(), key=lambda pair: pair[0].lower()
|
||||
):
|
||||
if self.database_names is None or any(
|
||||
[
|
||||
(re.match("^" + dbname + "$", name) or dbname == name)
|
||||
for dbname in self.database_names
|
||||
]
|
||||
):
|
||||
print(
|
||||
_('%(full_DB_path)s with name "%(f_t_name)s"')
|
||||
% {"full_DB_path": dirname, "f_t_name": name}
|
||||
)
|
||||
return
|
||||
|
||||
# Handle the "--remove" Family Tree
|
||||
@@ -428,7 +449,7 @@ class ArgHandler:
|
||||
|
||||
# Handle the "-t" List Family Trees, tab delimited option.
|
||||
if self.list_table:
|
||||
print(_('Gramps Family Trees:'))
|
||||
print(_("Gramps Family Trees:"))
|
||||
summary_list = self.dbman.family_tree_summary(self.database_names)
|
||||
if not summary_list:
|
||||
return
|
||||
@@ -439,9 +460,9 @@ class ArgHandler:
|
||||
if key != _("Family Tree"):
|
||||
line_list += [key]
|
||||
print("\t".join(line_list))
|
||||
for summary in sorted(summary_list,
|
||||
key=lambda
|
||||
sum: sum[_("Family Tree")].lower()):
|
||||
for summary in sorted(
|
||||
summary_list, key=lambda sum: sum[_("Family Tree")].lower()
|
||||
):
|
||||
line_list = [(_('"%s"') % summary[_("Family Tree")])]
|
||||
for item in sorted(summary):
|
||||
if item != _("Family Tree"):
|
||||
@@ -453,21 +474,18 @@ class ArgHandler:
|
||||
self.__open_action()
|
||||
self.__import_action()
|
||||
|
||||
for (action, op_string) in self.actions:
|
||||
print(_("Performing action: %s."
|
||||
) % action,
|
||||
file=sys.stderr)
|
||||
for action, op_string in self.actions:
|
||||
print(_("Performing action: %s.") % action, file=sys.stderr)
|
||||
if op_string:
|
||||
print(_("Using options string: %s"
|
||||
) % op_string,
|
||||
file=sys.stderr)
|
||||
print(_("Using options string: %s") % op_string, file=sys.stderr)
|
||||
self.cl_action(action, op_string)
|
||||
|
||||
for expt in self.exports:
|
||||
print(_("Exporting: file %(filename)s, format %(format)s."
|
||||
) % {'filename' : expt[0],
|
||||
'format' : expt[1]},
|
||||
file=sys.stderr)
|
||||
print(
|
||||
_("Exporting: file %(filename)s, format %(format)s.")
|
||||
% {"filename": expt[0], "format": expt[1]},
|
||||
file=sys.stderr,
|
||||
)
|
||||
self.cl_export(expt[0], expt[1])
|
||||
|
||||
if cleanup:
|
||||
@@ -498,19 +516,20 @@ class ArgHandler:
|
||||
if not self.open:
|
||||
# Create empty dir for imported database(s)
|
||||
if self.gui:
|
||||
dbid = config.get('database.backend')
|
||||
self.imp_db_path, title = self.dbman.create_new_db_cli(
|
||||
dbid=dbid)
|
||||
dbid = config.get("database.backend")
|
||||
self.imp_db_path, title = self.dbman.create_new_db_cli(dbid=dbid)
|
||||
else:
|
||||
self.imp_db_path = get_empty_tempdir("import_dbdir")
|
||||
dbid = config.get('database.backend')
|
||||
dbid = config.get("database.backend")
|
||||
newdb = make_database(dbid)
|
||||
versionpath = os.path.join(self.imp_db_path, str(DBBACKEND))
|
||||
with open(versionpath, "w") as version_file:
|
||||
version_file.write(dbid)
|
||||
|
||||
try:
|
||||
self.smgr.open_activate(self.imp_db_path, self.username, self.password)
|
||||
self.smgr.open_activate(
|
||||
self.imp_db_path, self.username, self.password
|
||||
)
|
||||
msg = _("Created empty Family Tree successfully")
|
||||
print(msg, file=sys.stderr)
|
||||
except:
|
||||
@@ -519,9 +538,10 @@ class ArgHandler:
|
||||
sys.exit(1)
|
||||
|
||||
for imp in self.imports:
|
||||
msg = _("Importing: file %(filename)s, format %(format)s."
|
||||
) % {'filename' : imp[0],
|
||||
'format' : imp[1]}
|
||||
msg = _("Importing: file %(filename)s, format %(format)s.") % {
|
||||
"filename": imp[0],
|
||||
"format": imp[1],
|
||||
}
|
||||
print(msg, file=sys.stderr)
|
||||
self.cl_import(imp[0], imp[1])
|
||||
|
||||
@@ -552,8 +572,10 @@ class ArgHandler:
|
||||
if force_unlock:
|
||||
self.dbman.break_lock(dbpath)
|
||||
if self.dbman.is_locked(dbpath):
|
||||
self.__error((_("Database is locked, cannot open it!") + '\n' +
|
||||
_(" Info: %s")) % find_locker_name(dbpath))
|
||||
self.__error(
|
||||
(_("Database is locked, cannot open it!") + "\n" + _(" Info: %s"))
|
||||
% find_locker_name(dbpath)
|
||||
)
|
||||
return False
|
||||
if self.dbman.needs_recovery(dbpath):
|
||||
self.__error(_("Database needs recovery, cannot open it!"))
|
||||
@@ -610,10 +632,9 @@ class ArgHandler:
|
||||
options_str_dict = _split_options(options_str)
|
||||
except:
|
||||
options_str_dict = {}
|
||||
print(_("Ignoring invalid options string."),
|
||||
file=sys.stderr)
|
||||
print(_("Ignoring invalid options string."), file=sys.stderr)
|
||||
|
||||
name = options_str_dict.pop('name', None)
|
||||
name = options_str_dict.pop("name", None)
|
||||
_cl_list = pmgr.get_reg_reports(gui=False)
|
||||
if name:
|
||||
for pdata in _cl_list:
|
||||
@@ -626,43 +647,51 @@ class ArgHandler:
|
||||
report_class = getattr(mod, pdata.reportclass)
|
||||
options_class = getattr(mod, pdata.optionclass)
|
||||
if category in (CATEGORY_BOOK, CATEGORY_CODE):
|
||||
options_class(self.dbstate.db, name, category,
|
||||
options_str_dict)
|
||||
options_class(
|
||||
self.dbstate.db, name, category, options_str_dict
|
||||
)
|
||||
else:
|
||||
cl_report(self.dbstate.db, name, category,
|
||||
report_class, options_class,
|
||||
options_str_dict)
|
||||
cl_report(
|
||||
self.dbstate.db,
|
||||
name,
|
||||
category,
|
||||
report_class,
|
||||
options_class,
|
||||
options_str_dict,
|
||||
)
|
||||
return
|
||||
# name exists, but is not in the list of valid report names
|
||||
msg = _("Unknown report name.")
|
||||
else:
|
||||
msg = _("Report name not given. "
|
||||
msg = _(
|
||||
"Report name not given. "
|
||||
"Please use one of %(donottranslate)s=reportname"
|
||||
) % {'donottranslate' : '[-p|--options] name'}
|
||||
) % {"donottranslate": "[-p|--options] name"}
|
||||
|
||||
print(_("%s\n Available names are:") % msg, file=sys.stderr)
|
||||
for pdata in sorted(_cl_list, key=lambda pdata: pdata.id.lower()):
|
||||
# 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),
|
||||
file=sys.stderr)
|
||||
print(
|
||||
" %s%s- %s"
|
||||
% (pdata.id, " " * (26 - len(pdata.id)), pdata.name),
|
||||
file=sys.stderr,
|
||||
)
|
||||
else:
|
||||
print(" %s\t- %s" % (pdata.id, pdata.name),
|
||||
file=sys.stderr)
|
||||
print(" %s\t- %s" % (pdata.id, pdata.name), file=sys.stderr)
|
||||
|
||||
elif action == "tool":
|
||||
from gramps.gui.plug import tool
|
||||
|
||||
try:
|
||||
options_str_dict = dict([tuple(chunk.split('='))
|
||||
for chunk in options_str.split(',')])
|
||||
options_str_dict = dict(
|
||||
[tuple(chunk.split("=")) for chunk in options_str.split(",")]
|
||||
)
|
||||
except:
|
||||
options_str_dict = {}
|
||||
print(_("Ignoring invalid options string."),
|
||||
file=sys.stderr)
|
||||
print(_("Ignoring invalid options string."), file=sys.stderr)
|
||||
|
||||
name = options_str_dict.pop('name', None)
|
||||
name = options_str_dict.pop("name", None)
|
||||
_cli_tool_list = pmgr.get_reg_tools(gui=False)
|
||||
if name:
|
||||
for pdata in _cli_tool_list:
|
||||
@@ -674,53 +703,59 @@ class ArgHandler:
|
||||
category = pdata.category
|
||||
tool_class = getattr(mod, pdata.toolclass)
|
||||
options_class = getattr(mod, pdata.optionclass)
|
||||
tool.cli_tool(dbstate=self.dbstate,
|
||||
tool.cli_tool(
|
||||
dbstate=self.dbstate,
|
||||
name=name,
|
||||
category=category,
|
||||
tool_class=tool_class,
|
||||
options_class=options_class,
|
||||
options_str_dict=options_str_dict,
|
||||
user=self.user)
|
||||
user=self.user,
|
||||
)
|
||||
return
|
||||
msg = _("Unknown tool name.")
|
||||
else:
|
||||
msg = _("Tool name not given. "
|
||||
msg = _(
|
||||
"Tool name not given. "
|
||||
"Please use one of %(donottranslate)s=toolname."
|
||||
) % {'donottranslate' : '[-p|--options] name'}
|
||||
) % {"donottranslate": "[-p|--options] name"}
|
||||
|
||||
print(_("%s\n Available names are:") % msg, file=sys.stderr)
|
||||
for pdata in sorted(_cli_tool_list,
|
||||
key=lambda pdata: pdata.id.lower()):
|
||||
for pdata in sorted(_cli_tool_list, key=lambda pdata: pdata.id.lower()):
|
||||
# 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),
|
||||
file=sys.stderr)
|
||||
print(
|
||||
" %s%s- %s"
|
||||
% (pdata.id, " " * (26 - len(pdata.id)), pdata.name),
|
||||
file=sys.stderr,
|
||||
)
|
||||
else:
|
||||
print(" %s\t- %s" % (pdata.id, pdata.name),
|
||||
file=sys.stderr)
|
||||
print(" %s\t- %s" % (pdata.id, pdata.name), file=sys.stderr)
|
||||
|
||||
elif action == "book":
|
||||
try:
|
||||
options_str_dict = _split_options(options_str)
|
||||
except:
|
||||
options_str_dict = {}
|
||||
print(_("Ignoring invalid options string."),
|
||||
file=sys.stderr)
|
||||
print(_("Ignoring invalid options string."), file=sys.stderr)
|
||||
|
||||
name = options_str_dict.pop('name', None)
|
||||
book_list = BookList('books.xml', self.dbstate.db)
|
||||
name = options_str_dict.pop("name", None)
|
||||
book_list = BookList("books.xml", self.dbstate.db)
|
||||
if name:
|
||||
if name in book_list.get_book_names():
|
||||
cl_book(self.dbstate.db, name, book_list.get_book(name),
|
||||
options_str_dict)
|
||||
cl_book(
|
||||
self.dbstate.db,
|
||||
name,
|
||||
book_list.get_book(name),
|
||||
options_str_dict,
|
||||
)
|
||||
return
|
||||
msg = _("Unknown book name.")
|
||||
else:
|
||||
msg = _("Book name not given. "
|
||||
msg = _(
|
||||
"Book name not given. "
|
||||
"Please use one of %(donottranslate)s=bookname."
|
||||
) % {'donottranslate' : '[-p|--options] name'}
|
||||
) % {"donottranslate": "[-p|--options] name"}
|
||||
|
||||
print(_("%s\n Available names are:") % msg, file=sys.stderr)
|
||||
for name in sorted(book_list.get_book_names()):
|
||||
|
@@ -47,14 +47,24 @@ from glob import glob
|
||||
# gramps modules
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from gramps.gen.const import (LONGOPTS, SHORTOPTS, USER_PLUGINS, VERSION_DIR,
|
||||
USER_CACHE, USER_CONFIG, USER_DATA, THUMB_DIR,
|
||||
USER_CSS)
|
||||
from gramps.gen.const import (
|
||||
LONGOPTS,
|
||||
SHORTOPTS,
|
||||
USER_PLUGINS,
|
||||
VERSION_DIR,
|
||||
USER_CACHE,
|
||||
USER_CONFIG,
|
||||
USER_DATA,
|
||||
THUMB_DIR,
|
||||
USER_CSS,
|
||||
)
|
||||
from gramps.gen.utils.cast import get_type_converter
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
_HELP = _("""
|
||||
_HELP = _(
|
||||
"""
|
||||
Usage: gramps [OPTION...]
|
||||
--load-modules=MODULE1,MODULE2,... Dynamic modules to load
|
||||
|
||||
@@ -91,9 +101,11 @@ Application options
|
||||
X - Books are cleared, reports and tool settings to default
|
||||
F - filters are cleared
|
||||
E - Everything is set to default or cleared
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
_USAGE = _("""
|
||||
_USAGE = _(
|
||||
"""
|
||||
Example of usage of Gramps command line interface
|
||||
|
||||
1. To import four databases (whose formats can be determined from their names)
|
||||
@@ -136,7 +148,9 @@ gramps
|
||||
|
||||
Note: These examples are for bash shell.
|
||||
Syntax may be different for other shells and for Windows.
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ArgParser
|
||||
@@ -241,14 +255,13 @@ class ArgParser:
|
||||
Any errors are added to self.errors
|
||||
"""
|
||||
try:
|
||||
options, leftargs = getopt.getopt(self.args[1:],
|
||||
SHORTOPTS, LONGOPTS)
|
||||
options, leftargs = getopt.getopt(self.args[1:], SHORTOPTS, LONGOPTS)
|
||||
except getopt.GetoptError as getopt_error:
|
||||
self.errors.append(
|
||||
self.construct_error(
|
||||
"Type gramps --help for an overview of "
|
||||
"commands, or read the manual pages.",
|
||||
error=getopt_error
|
||||
error=getopt_error,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -257,7 +270,7 @@ class ArgParser:
|
||||
# Some args can work on a list of databases:
|
||||
if leftargs:
|
||||
for option, value in options:
|
||||
if option in ['-L', '-l', '-t']:
|
||||
if option in ["-L", "-l", "-t"]:
|
||||
self.database_names = leftargs
|
||||
leftargs = []
|
||||
|
||||
@@ -265,12 +278,10 @@ class ArgParser:
|
||||
# if there were an argument without option,
|
||||
# use it as a file to open and return
|
||||
self.open_gui = leftargs[0]
|
||||
print(_("Trying to open: %s ..."
|
||||
) % leftargs[0],
|
||||
file=sys.stderr)
|
||||
print(_("Trying to open: %s ...") % leftargs[0], file=sys.stderr)
|
||||
# see if force open is on
|
||||
for option, value in options:
|
||||
if option in ('-u', '--force-unlock'):
|
||||
if option in ("-u", "--force-unlock"):
|
||||
self.force_unlock = True
|
||||
break
|
||||
return
|
||||
@@ -279,77 +290,81 @@ class ArgParser:
|
||||
cleandbg = []
|
||||
need_to_quit = False
|
||||
for opt_ix, (option, value) in enumerate(options):
|
||||
if option in ['-O', '--open']:
|
||||
if option in ["-O", "--open"]:
|
||||
self.open = value
|
||||
elif option in ['-C', '--create']:
|
||||
elif option in ["-C", "--create"]:
|
||||
self.create = value
|
||||
elif option in ['-U', '--username']:
|
||||
elif option in ["-U", "--username"]:
|
||||
self.username = value
|
||||
elif option in ['-P', '--password']:
|
||||
elif option in ["-P", "--password"]:
|
||||
self.password = value
|
||||
elif option in ['-i', '--import']:
|
||||
elif option in ["-i", "--import"]:
|
||||
family_tree_format = None
|
||||
if (opt_ix < len(options) - 1
|
||||
and options[opt_ix + 1][0] in ('-f', '--format')):
|
||||
if opt_ix < len(options) - 1 and options[opt_ix + 1][0] in (
|
||||
"-f",
|
||||
"--format",
|
||||
):
|
||||
family_tree_format = options[opt_ix + 1][1]
|
||||
self.imports.append((value, family_tree_format))
|
||||
elif option in ['-r', '--remove']:
|
||||
elif option in ["-r", "--remove"]:
|
||||
self.removes.append(value)
|
||||
elif option in ['-e', '--export']:
|
||||
elif option in ["-e", "--export"]:
|
||||
family_tree_format = None
|
||||
if (opt_ix < len(options) - 1
|
||||
and options[opt_ix + 1][0] in ('-f', '--format')):
|
||||
if opt_ix < len(options) - 1 and options[opt_ix + 1][0] in (
|
||||
"-f",
|
||||
"--format",
|
||||
):
|
||||
family_tree_format = options[opt_ix + 1][1]
|
||||
abs_name = os.path.abspath(os.path.expanduser(value))
|
||||
if not os.path.exists(abs_name):
|
||||
# The file doesn't exists, try to create it.
|
||||
try:
|
||||
open(abs_name, 'w').close()
|
||||
open(abs_name, "w").close()
|
||||
os.unlink(abs_name)
|
||||
except OSError as e:
|
||||
message = _("WARNING: %(strerr)s "
|
||||
message = _(
|
||||
"WARNING: %(strerr)s "
|
||||
"(errno=%(errno)s):\n"
|
||||
"WARNING: %(name)s\n") % {
|
||||
'strerr' : e.strerror,
|
||||
'errno' : e.errno,
|
||||
'name' : e.filename}
|
||||
"WARNING: %(name)s\n"
|
||||
) % {"strerr": e.strerror, "errno": e.errno, "name": e.filename}
|
||||
print(message)
|
||||
sys.exit(1)
|
||||
self.exports.append((value, family_tree_format))
|
||||
elif option in ['-a', '--action']:
|
||||
elif option in ["-a", "--action"]:
|
||||
action = value
|
||||
if action not in ('report', 'tool', 'book'):
|
||||
print(_("Unknown action: %s. Ignoring."
|
||||
) % action,
|
||||
file=sys.stderr)
|
||||
if action not in ("report", "tool", "book"):
|
||||
print(_("Unknown action: %s. Ignoring.") % action, file=sys.stderr)
|
||||
continue
|
||||
options_str = ""
|
||||
if (opt_ix < len(options)-1
|
||||
and options[opt_ix+1][0] in ('-p', '--options')):
|
||||
if opt_ix < len(options) - 1 and options[opt_ix + 1][0] in (
|
||||
"-p",
|
||||
"--options",
|
||||
):
|
||||
options_str = options[opt_ix + 1][1]
|
||||
self.actions.append((action, options_str))
|
||||
elif option in ['-d', '--debug']:
|
||||
print(_('setup debugging'), value, file=sys.stderr)
|
||||
elif option in ["-d", "--debug"]:
|
||||
print(_("setup debugging"), value, file=sys.stderr)
|
||||
logger = logging.getLogger(value)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
cleandbg += [opt_ix]
|
||||
elif option in ['-l']:
|
||||
elif option in ["-l"]:
|
||||
self.list = True
|
||||
elif option in ['-L']:
|
||||
elif option in ["-L"]:
|
||||
self.list_more = True
|
||||
elif option in ['-t']:
|
||||
elif option in ["-t"]:
|
||||
self.list_table = True
|
||||
elif option in ['-s', '--show']:
|
||||
elif option in ["-s", "--show"]:
|
||||
from gramps.gen.config import config
|
||||
print(_("Gramps config settings from %s:"
|
||||
) % config.filename)
|
||||
|
||||
print(_("Gramps config settings from %s:") % config.filename)
|
||||
for sect, settings in config.data.items():
|
||||
for settings_index, setting in settings.items():
|
||||
print("%s.%s=%s" % (sect, settings_index, repr(value)))
|
||||
print()
|
||||
sys.exit(0)
|
||||
elif option in ['-c', '--config']:
|
||||
elif option in ["-c", "--config"]:
|
||||
from gramps.gen.config import config
|
||||
|
||||
cfg_name = value
|
||||
set_value = False
|
||||
if cfg_name:
|
||||
@@ -358,11 +373,11 @@ class ArgParser:
|
||||
set_value = True
|
||||
if config.has_default(cfg_name):
|
||||
setting_value = config.get(cfg_name)
|
||||
print(_("Current Gramps config setting: "
|
||||
"%(name)s:%(value)s"
|
||||
) % {'name' : cfg_name,
|
||||
'value' : repr(setting_value)},
|
||||
file=sys.stderr)
|
||||
print(
|
||||
_("Current Gramps config setting: " "%(name)s:%(value)s")
|
||||
% {"name": cfg_name, "value": repr(setting_value)},
|
||||
file=sys.stderr,
|
||||
)
|
||||
if set_value:
|
||||
# does a user want the default config value?
|
||||
if new_value in ("DEFAULT", _("DEFAULT")):
|
||||
@@ -372,64 +387,74 @@ class ArgParser:
|
||||
new_value = converter(new_value)
|
||||
config.set(cfg_name, new_value)
|
||||
# Translators: indent "New" to match "Current"
|
||||
print(_(" New Gramps config setting: "
|
||||
print(
|
||||
_(
|
||||
" New Gramps config setting: "
|
||||
"%(name)s:%(value)s"
|
||||
) % {'name' : cfg_name,
|
||||
'value' : repr(config.get(cfg_name))},
|
||||
file=sys.stderr)
|
||||
)
|
||||
% {
|
||||
"name": cfg_name,
|
||||
"value": repr(config.get(cfg_name)),
|
||||
},
|
||||
file=sys.stderr,
|
||||
)
|
||||
else:
|
||||
need_to_quit = True
|
||||
else:
|
||||
print(_("Gramps: no such config setting: '%s'"
|
||||
) % cfg_name,
|
||||
file=sys.stderr)
|
||||
print(
|
||||
_("Gramps: no such config setting: '%s'") % cfg_name,
|
||||
file=sys.stderr,
|
||||
)
|
||||
need_to_quit = True
|
||||
cleandbg += [opt_ix]
|
||||
elif option in ['-h', '-?', '--help']:
|
||||
elif option in ["-h", "-?", "--help"]:
|
||||
self.help = True
|
||||
elif option in ['-u', '--force-unlock']:
|
||||
elif option in ["-u", "--force-unlock"]:
|
||||
self.force_unlock = True
|
||||
elif option in ['--usage']:
|
||||
elif option in ["--usage"]:
|
||||
self.usage = True
|
||||
elif option in ['-y', '--yes']:
|
||||
elif option in ["-y", "--yes"]:
|
||||
self.auto_accept = True
|
||||
elif option in ['-q', '--quiet']:
|
||||
elif option in ["-q", "--quiet"]:
|
||||
self.quiet = True
|
||||
elif option in ['-S', '--safe']:
|
||||
elif option in ["-S", "--safe"]:
|
||||
cleandbg += [opt_ix]
|
||||
elif option in ['-D', '--default']:
|
||||
elif option in ["-D", "--default"]:
|
||||
|
||||
def rmtree(path):
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
if 'E' in value or 'A' in value: # clear addons
|
||||
if "E" in value or "A" in value: # clear addons
|
||||
rmtree(USER_PLUGINS)
|
||||
if 'E' in value or 'P' in value: # clear ini preferences
|
||||
if "E" in value or "P" in value: # clear ini preferences
|
||||
for fil in glob(os.path.join(VERSION_DIR, "*.*")):
|
||||
if "custom_filters.xml" in fil:
|
||||
continue
|
||||
os.remove(fil)
|
||||
# create gramps.ini so config won't load the one from an
|
||||
# older version of Gramps.
|
||||
with open(os.path.join(VERSION_DIR, 'gramps.ini'), 'w'):
|
||||
with open(os.path.join(VERSION_DIR, "gramps.ini"), "w"):
|
||||
pass
|
||||
if 'E' in value or 'F' in value: # clear filters
|
||||
if "E" in value or "F" in value: # clear filters
|
||||
fil = os.path.join(VERSION_DIR, "custom_filters.xml")
|
||||
if os.path.isfile(fil):
|
||||
os.remove(fil)
|
||||
if 'E' in value or 'X' in value: # clear xml reports/tools
|
||||
if "E" in value or "X" in value: # clear xml reports/tools
|
||||
for fil in glob(os.path.join(USER_DATA, "*.xml")):
|
||||
os.remove(fil)
|
||||
if 'E' in value or 'Z' in value: # clear upgrade zips
|
||||
if "E" in value or "Z" in value: # clear upgrade zips
|
||||
for fil in glob(os.path.join(USER_DATA, "*.zip")):
|
||||
os.remove(fil)
|
||||
if 'E' in value: # Everything else
|
||||
if "E" in value: # Everything else
|
||||
rmtree(THUMB_DIR)
|
||||
rmtree(USER_CSS)
|
||||
rmtree(os.path.join(USER_CACHE, "maps"))
|
||||
for fil in (glob(os.path.join(USER_CACHE, "*"))
|
||||
for fil in (
|
||||
glob(os.path.join(USER_CACHE, "*"))
|
||||
+ glob(os.path.join(USER_CONFIG, "*"))
|
||||
+ glob(os.path.join(USER_DATA, "*"))):
|
||||
+ glob(os.path.join(USER_DATA, "*"))
|
||||
):
|
||||
if os.path.isfile(fil):
|
||||
os.remove(fil)
|
||||
sys.exit(0) # Done with Default
|
||||
@@ -439,14 +464,13 @@ class ArgParser:
|
||||
for ind in cleandbg:
|
||||
del options[ind]
|
||||
|
||||
if (len(options) > 0
|
||||
if (
|
||||
len(options) > 0
|
||||
and self.open is None
|
||||
and self.imports == []
|
||||
and self.removes == []
|
||||
and not (self.list
|
||||
or self.list_more
|
||||
or self.list_table
|
||||
or self.help)):
|
||||
and not (self.list or self.list_more or self.list_table or self.help)
|
||||
):
|
||||
self.errors.append(
|
||||
self.construct_error(
|
||||
"To use in the command-line mode, supply at "
|
||||
@@ -469,10 +493,9 @@ class ArgParser:
|
||||
translated_message = _(error_message + suggestion_message) % cli_args
|
||||
|
||||
if error:
|
||||
translated_message = str(error) + '\n' + translated_message
|
||||
|
||||
return _('Error parsing the arguments'), translated_message
|
||||
translated_message = str(error) + "\n" + translated_message
|
||||
|
||||
return _("Error parsing the arguments"), translated_message
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Determine the need for GUI
|
||||
|
@@ -51,6 +51,7 @@ from gramps.gen.constfunc import win
|
||||
from gramps.gen.db.dbconst import DBLOGNAME, DBBACKEND
|
||||
from gramps.gen.db.utils import make_database, get_dbid_from_path
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -69,7 +70,8 @@ _LOG = logging.getLogger(DBLOGNAME)
|
||||
DEFAULT_TITLE = _("Family Tree")
|
||||
NAME_FILE = "name.txt"
|
||||
META_NAME = "meta_data.db"
|
||||
UNAVAILABLE = _('Unavailable')
|
||||
UNAVAILABLE = _("Unavailable")
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
@@ -80,11 +82,13 @@ def _errordialog(title, errormessage):
|
||||
"""
|
||||
Show the error. A title for the error and an errormessage
|
||||
"""
|
||||
print(_('ERROR: %(title)s \n %(message)s') % {
|
||||
'title': title,
|
||||
'message': errormessage})
|
||||
print(
|
||||
_("ERROR: %(title)s \n %(message)s")
|
||||
% {"title": title, "message": errormessage}
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# CLIDbManager
|
||||
@@ -95,6 +99,7 @@ class CLIDbManager:
|
||||
Database manager without GTK functionality, allows users to create and
|
||||
open databases
|
||||
"""
|
||||
|
||||
IND_NAME = 0
|
||||
IND_PATH = 1
|
||||
IND_PATH_NAMEFILE = 2
|
||||
@@ -116,6 +121,7 @@ class CLIDbManager:
|
||||
}
|
||||
|
||||
ERROR = _errordialog
|
||||
|
||||
def __init__(self, dbstate):
|
||||
self.dbstate = dbstate
|
||||
self.msg = None
|
||||
@@ -166,12 +172,15 @@ class CLIDbManager:
|
||||
retval = {_("Unavailable"): str(msg)[:74] + "..."}
|
||||
else:
|
||||
retval = {_("Unavailable"): "locked"}
|
||||
retval.update({_("Family Tree"): name,
|
||||
retval.update(
|
||||
{
|
||||
_("Family Tree"): name,
|
||||
_("Path"): dirpath,
|
||||
_("Database"): self.get_backend_name_from_dbid(dbid),
|
||||
_("Last accessed"): time_val(dirpath)[1],
|
||||
_("Locked?"): self.is_locked(dirpath),
|
||||
})
|
||||
}
|
||||
)
|
||||
return retval
|
||||
|
||||
def get_backend_name_from_dbid(self, dbid):
|
||||
@@ -185,22 +194,34 @@ class CLIDbManager:
|
||||
"""
|
||||
Prints a detailed list of the known family trees.
|
||||
"""
|
||||
print(_('Gramps Family Trees:'))
|
||||
print(_("Gramps Family Trees:"))
|
||||
for item in self.current_names:
|
||||
(name, dirpath, path_name, last,
|
||||
tval, enable, stock_id, backend_type) = item
|
||||
if (database_names is None or
|
||||
any([(re.match("^" + dbname + "$", name) or
|
||||
dbname == name)
|
||||
for dbname in database_names])):
|
||||
(
|
||||
name,
|
||||
dirpath,
|
||||
path_name,
|
||||
last,
|
||||
tval,
|
||||
enable,
|
||||
stock_id,
|
||||
backend_type,
|
||||
) = item
|
||||
if database_names is None or any(
|
||||
[
|
||||
(re.match("^" + dbname + "$", name) or dbname == name)
|
||||
for dbname in database_names
|
||||
]
|
||||
):
|
||||
summary = self.get_dbdir_summary(dirpath, name)
|
||||
print(_('Family Tree "%s":') % summary[_("Family Tree")])
|
||||
for item in sorted(summary):
|
||||
if item != "Family Tree":
|
||||
# Translators: needed for French, ignore otherwise
|
||||
print(' ' + _("%(str1)s: %(str2)s"
|
||||
) % {'str1' : item,
|
||||
'str2' : summary[item]})
|
||||
print(
|
||||
" "
|
||||
+ _("%(str1)s: %(str2)s")
|
||||
% {"str1": item, "str2": summary[item]}
|
||||
)
|
||||
|
||||
def family_tree_summary(self, database_names=None):
|
||||
"""
|
||||
@@ -209,12 +230,22 @@ class CLIDbManager:
|
||||
# make the default directory if it does not exist
|
||||
summary_list = []
|
||||
for item in self.current_names:
|
||||
(name, dirpath, path_name, last,
|
||||
tval, enable, stock_id, backend_type) = item
|
||||
if (database_names is None or
|
||||
any([(re.match("^" + dbname + "$", name) or
|
||||
dbname == name)
|
||||
for dbname in database_names])):
|
||||
(
|
||||
name,
|
||||
dirpath,
|
||||
path_name,
|
||||
last,
|
||||
tval,
|
||||
enable,
|
||||
stock_id,
|
||||
backend_type,
|
||||
) = item
|
||||
if database_names is None or any(
|
||||
[
|
||||
(re.match("^" + dbname + "$", name) or dbname == name)
|
||||
for dbname in database_names
|
||||
]
|
||||
):
|
||||
retval = self.get_dbdir_summary(dirpath, name)
|
||||
summary_list.append(retval)
|
||||
return summary_list
|
||||
@@ -224,7 +255,7 @@ class CLIDbManager:
|
||||
Get the list of current names in the database dir
|
||||
"""
|
||||
# make the default directory if it does not exist
|
||||
dbdir = os.path.expanduser(config.get('database.path'))
|
||||
dbdir = os.path.expanduser(config.get("database.path"))
|
||||
db_ok = make_dbdir(dbdir)
|
||||
|
||||
self.current_names = []
|
||||
@@ -234,19 +265,29 @@ class CLIDbManager:
|
||||
path_name = os.path.join(dirpath, NAME_FILE)
|
||||
backend_type = get_dbid_from_path(dirpath)
|
||||
if os.path.isfile(path_name):
|
||||
with open(path_name, 'r', encoding='utf8') as file:
|
||||
with open(path_name, "r", encoding="utf8") as file:
|
||||
name = file.readline().strip()
|
||||
|
||||
(tval, last) = time_val(dirpath)
|
||||
(enable, stock_id) = self.icon_values(
|
||||
dirpath, self.active, self.dbstate.is_open())
|
||||
dirpath, self.active, self.dbstate.is_open()
|
||||
)
|
||||
|
||||
if stock_id == 'gramps-lock':
|
||||
if stock_id == "gramps-lock":
|
||||
last = find_locker_name(dirpath)
|
||||
|
||||
self.current_names.append(
|
||||
(name, os.path.join(dbdir, dpath), path_name,
|
||||
last, tval, enable, stock_id, backend_type))
|
||||
(
|
||||
name,
|
||||
os.path.join(dbdir, dpath),
|
||||
path_name,
|
||||
last,
|
||||
tval,
|
||||
enable,
|
||||
stock_id,
|
||||
backend_type,
|
||||
)
|
||||
)
|
||||
|
||||
self.current_names.sort()
|
||||
|
||||
@@ -271,13 +312,13 @@ class CLIDbManager:
|
||||
"""
|
||||
Do needed things to start import visually, eg busy cursor
|
||||
"""
|
||||
print(_('Starting Import, %s') % msg)
|
||||
print(_("Starting Import, %s") % msg)
|
||||
|
||||
def __end_cursor(self):
|
||||
"""
|
||||
Set end of a busy cursor
|
||||
"""
|
||||
print(_('Import finished...'))
|
||||
print(_("Import finished..."))
|
||||
|
||||
def create_new_db_cli(self, title=None, create_db=True, dbid=None):
|
||||
"""
|
||||
@@ -292,22 +333,23 @@ class CLIDbManager:
|
||||
name_list = [name[0] for name in self.current_names]
|
||||
title = find_next_db_name(name_list)
|
||||
|
||||
with open(path_name, "w", encoding='utf8') as name_file:
|
||||
with open(path_name, "w", encoding="utf8") as name_file:
|
||||
name_file.write(title)
|
||||
|
||||
if create_db:
|
||||
if dbid is None:
|
||||
dbid = config.get('database.backend')
|
||||
dbid = config.get("database.backend")
|
||||
newdb = make_database(dbid)
|
||||
|
||||
backend_path = os.path.join(new_path, DBBACKEND)
|
||||
with open(backend_path, "w", encoding='utf8') as backend_file:
|
||||
with open(backend_path, "w", encoding="utf8") as backend_file:
|
||||
backend_file.write(dbid)
|
||||
|
||||
(tval, last) = time_val(new_path)
|
||||
|
||||
self.current_names.append((title, new_path, path_name,
|
||||
last, tval, False, "", dbid))
|
||||
self.current_names.append(
|
||||
(title, new_path, path_name, last, tval, False, "", dbid)
|
||||
)
|
||||
return new_path, title
|
||||
|
||||
def _create_new_db(self, title=None, dbid=None, edit_entry=False):
|
||||
@@ -357,10 +399,8 @@ class CLIDbManager:
|
||||
|
||||
for plugin in pmgr.get_import_plugins():
|
||||
if format == plugin.get_extension():
|
||||
|
||||
dbid = config.get('database.backend')
|
||||
new_path, name = self._create_new_db(name, dbid=dbid,
|
||||
edit_entry=False)
|
||||
dbid = config.get("database.backend")
|
||||
new_path, name = self._create_new_db(name, dbid=dbid, edit_entry=False)
|
||||
|
||||
# Create a new database
|
||||
self.__start_cursor(_("Importing data..."))
|
||||
@@ -406,35 +446,37 @@ class CLIDbManager:
|
||||
Deletes a database folder given a pattenr that matches
|
||||
its proper name.
|
||||
"""
|
||||
dbdir = os.path.expanduser(config.get('database.path'))
|
||||
dbdir = os.path.expanduser(config.get("database.path"))
|
||||
match_list = []
|
||||
for dpath in os.listdir(dbdir):
|
||||
dirpath = os.path.join(dbdir, dpath)
|
||||
path_name = os.path.join(dirpath, NAME_FILE)
|
||||
if os.path.isfile(path_name):
|
||||
with open(path_name, 'r', encoding='utf8') as file:
|
||||
with open(path_name, "r", encoding="utf8") as file:
|
||||
name = file.readline().strip()
|
||||
if re.match("^" + dbname + "$", name) or dbname == name:
|
||||
match_list.append((name, dirpath))
|
||||
if len(match_list) == 0:
|
||||
CLIDbManager.ERROR("Family tree not found",
|
||||
"No matching family tree found: '%s'" % dbname)
|
||||
CLIDbManager.ERROR(
|
||||
"Family tree not found", "No matching family tree found: '%s'" % dbname
|
||||
)
|
||||
# now delete them:
|
||||
for (name, directory) in match_list:
|
||||
for name, directory in match_list:
|
||||
if user is None or user.prompt(
|
||||
_('Remove family tree warning'),
|
||||
_('Are you sure you want to remove '
|
||||
'the family tree named\n"%s"?'
|
||||
) % name,
|
||||
_('yes'), _('no'), default_label=_('no')):
|
||||
_("Remove family tree warning"),
|
||||
_("Are you sure you want to remove " 'the family tree named\n"%s"?')
|
||||
% name,
|
||||
_("yes"),
|
||||
_("no"),
|
||||
default_label=_("no"),
|
||||
):
|
||||
try:
|
||||
for (top, dirs, files) in os.walk(directory):
|
||||
for top, dirs, files in os.walk(directory):
|
||||
for filename in files:
|
||||
os.unlink(os.path.join(top, filename))
|
||||
os.rmdir(directory)
|
||||
except (IOError, OSError) as msg:
|
||||
CLIDbManager.ERROR(_("Could not delete Family Tree"),
|
||||
str(msg))
|
||||
CLIDbManager.ERROR(_("Could not delete Family Tree"), str(msg))
|
||||
|
||||
def rename_database(self, filepath, new_text):
|
||||
"""
|
||||
@@ -442,9 +484,9 @@ class CLIDbManager:
|
||||
Returns old_name, new_name if success, None, None if no success
|
||||
"""
|
||||
try:
|
||||
with open(filepath, "r", encoding='utf8') as name_file:
|
||||
with open(filepath, "r", encoding="utf8") as name_file:
|
||||
old_text = name_file.read()
|
||||
with open(filepath, "w", encoding='utf8') as name_file:
|
||||
with open(filepath, "w", encoding="utf8") as name_file:
|
||||
name_file.write(new_text)
|
||||
except (OSError, IOError) as msg:
|
||||
CLIDbManager.ERROR(_("Could not rename Family Tree"), str(msg))
|
||||
@@ -472,6 +514,7 @@ class CLIDbManager:
|
||||
else:
|
||||
return (False, self.ICON_MAP[self.ICON_NONE])
|
||||
|
||||
|
||||
def make_dbdir(dbdir):
|
||||
"""
|
||||
Create the default database directory, as defined by dbdir
|
||||
@@ -480,13 +523,18 @@ def make_dbdir(dbdir):
|
||||
if not os.path.isdir(dbdir):
|
||||
os.makedirs(dbdir)
|
||||
except (IOError, OSError) as msg:
|
||||
LOG.error(_("\nERROR: Wrong database path in Edit Menu->Preferences.\n"
|
||||
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"),
|
||||
str(msg))
|
||||
"Details: Could not make database directory:\n %s\n\n"
|
||||
),
|
||||
str(msg),
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def find_next_db_name(name_list):
|
||||
"""
|
||||
Scan the name list, looking for names that do not yet exist.
|
||||
@@ -499,6 +547,7 @@ def find_next_db_name(name_list):
|
||||
return title
|
||||
i += 1
|
||||
|
||||
|
||||
def find_next_db_dir():
|
||||
"""
|
||||
Searches the default directory for the first available default
|
||||
@@ -507,12 +556,13 @@ def find_next_db_dir():
|
||||
"""
|
||||
while True:
|
||||
base = "%x" % int(time.time())
|
||||
dbdir = os.path.expanduser(config.get('database.path'))
|
||||
dbdir = os.path.expanduser(config.get("database.path"))
|
||||
new_path = os.path.join(dbdir, base)
|
||||
if not os.path.isdir(new_path):
|
||||
break
|
||||
return new_path
|
||||
|
||||
|
||||
def time_val(dirpath):
|
||||
"""
|
||||
Return the last modified time of the database. We do this by looking
|
||||
@@ -529,12 +579,13 @@ def time_val(dirpath):
|
||||
tval_mod = os.stat(meta)[8]
|
||||
if tval_mod > tval:
|
||||
tval = tval_mod
|
||||
last = time.strftime('%x %X', time.localtime(tval))
|
||||
last = time.strftime("%x %X", time.localtime(tval))
|
||||
else:
|
||||
tval = 0
|
||||
last = _("Never")
|
||||
return (tval, last)
|
||||
|
||||
|
||||
def find_locker_name(dirpath):
|
||||
"""
|
||||
Opens the lock file if it exists, reads the contexts which is "USERNAME"
|
||||
@@ -545,7 +596,7 @@ def find_locker_name(dirpath):
|
||||
"""
|
||||
try:
|
||||
fname = os.path.join(dirpath, "lock")
|
||||
with open(fname, 'r', encoding='utf8') as ifile:
|
||||
with open(fname, "r", encoding="utf8") as ifile:
|
||||
username = ifile.read().strip()
|
||||
# feature request 2356: avoid genitive form
|
||||
last = _("Locked by %s") % username
|
||||
|
@@ -32,6 +32,7 @@ Provides also two small base classes: :class:`CLIDbLoader`, :class:`CLIManager`
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
import os
|
||||
import sys
|
||||
@@ -51,16 +52,19 @@ from gramps.gen.db.dbconst import DBBACKEND
|
||||
from gramps.gen.db.utils import make_database
|
||||
from gramps.gen.errors import DbError
|
||||
from gramps.gen.dbstate import DbState
|
||||
from gramps.gen.db.exceptions import (DbUpgradeRequiredError,
|
||||
from gramps.gen.db.exceptions import (
|
||||
DbUpgradeRequiredError,
|
||||
DbSupportedError,
|
||||
DbVersionError,
|
||||
DbPythonError,
|
||||
DbConnectionError)
|
||||
DbConnectionError,
|
||||
)
|
||||
from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.utils.config import get_researcher
|
||||
from gramps.gen.recentfiles import recent_files
|
||||
from gramps.gen.filters import reload_custom_filters
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# CLI DbLoader class
|
||||
@@ -71,6 +75,7 @@ class CLIDbLoader:
|
||||
Base class for Db loading action inside a :class:`.DbState`. Only the
|
||||
minimum is present needed for CLI handling
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate):
|
||||
self.dbstate = dbstate
|
||||
|
||||
@@ -78,14 +83,14 @@ class CLIDbLoader:
|
||||
"""
|
||||
Issue a warning message. Inherit for GUI action
|
||||
"""
|
||||
print(_('WARNING: %s') % warnmessage, file=sys.stderr)
|
||||
print(_("WARNING: %s") % warnmessage, file=sys.stderr)
|
||||
|
||||
def _errordialog(self, title, errormessage):
|
||||
"""
|
||||
Show the error. A title for the error and an errormessage
|
||||
Inherit for GUI action
|
||||
"""
|
||||
print(_('ERROR: %s') % errormessage, file=sys.stderr)
|
||||
print(_("ERROR: %s") % errormessage, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def _dberrordialog(self, msg):
|
||||
@@ -98,14 +103,18 @@ class CLIDbLoader:
|
||||
.. note:: Inherit for GUI action
|
||||
"""
|
||||
self._errordialog(
|
||||
'',
|
||||
"",
|
||||
_("Low level database corruption detected")
|
||||
+ '\n' +
|
||||
_("Gramps has detected a problem in the underlying "
|
||||
+ "\n"
|
||||
+ _(
|
||||
"Gramps has detected a problem in the underlying "
|
||||
"database. This can sometimes be repaired from "
|
||||
"the Family Tree Manager. Select the database and "
|
||||
'click on the Repair button'
|
||||
) + '\n\n' + str(msg))
|
||||
"click on the Repair button"
|
||||
)
|
||||
+ "\n\n"
|
||||
+ str(msg),
|
||||
)
|
||||
|
||||
def _begin_progress(self):
|
||||
"""
|
||||
@@ -146,13 +155,14 @@ class CLIDbLoader:
|
||||
if os.path.exists(filename):
|
||||
if not os.access(filename, os.W_OK):
|
||||
mode = "r"
|
||||
self._warn(_('Read only database'),
|
||||
_('You do not have write access '
|
||||
'to the selected file.'))
|
||||
self._warn(
|
||||
_("Read only database"),
|
||||
_("You do not have write access " "to the selected file."),
|
||||
)
|
||||
else:
|
||||
mode = "w"
|
||||
else:
|
||||
mode = 'w'
|
||||
mode = "w"
|
||||
|
||||
dbid_path = os.path.join(filename, DBBACKEND)
|
||||
if os.path.isfile(dbid_path):
|
||||
@@ -169,16 +179,26 @@ class CLIDbLoader:
|
||||
self._begin_progress()
|
||||
|
||||
try:
|
||||
self.dbstate.db.load(filename, self._pulse_progress, mode,
|
||||
username=username, password=password)
|
||||
except (DbConnectionError, DbSupportedError, DbUpgradeRequiredError,
|
||||
DbVersionError, DbPythonError, DbConnectionError) as msg:
|
||||
self.dbstate.db.load(
|
||||
filename,
|
||||
self._pulse_progress,
|
||||
mode,
|
||||
username=username,
|
||||
password=password,
|
||||
)
|
||||
except (
|
||||
DbConnectionError,
|
||||
DbSupportedError,
|
||||
DbUpgradeRequiredError,
|
||||
DbVersionError,
|
||||
DbPythonError,
|
||||
DbConnectionError,
|
||||
) as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog(_("Cannot open database"), str(msg))
|
||||
except OSError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog(
|
||||
_("Could not open file: %s") % filename, str(msg))
|
||||
self._errordialog(_("Could not open file: %s") % filename, str(msg))
|
||||
except DbError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._dberrordialog(msg)
|
||||
@@ -187,12 +207,14 @@ class CLIDbLoader:
|
||||
LOG.error("Failed to open database.", exc_info=True)
|
||||
return True
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# CLIManager class
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CLIManager:
|
||||
"""
|
||||
Sessionmanager for Gramps.
|
||||
@@ -201,6 +223,7 @@ class CLIManager:
|
||||
Aim is to manage a dbstate on which to work (load, unload), and interact
|
||||
with the plugin session
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, setloader, user):
|
||||
self.dbstate = dbstate
|
||||
if setloader:
|
||||
@@ -221,7 +244,7 @@ class CLIManager:
|
||||
"""
|
||||
Show the error. A title for the error and an errormessage
|
||||
"""
|
||||
print(_('ERROR: %s') % errormessage, file=sys.stderr)
|
||||
print(_("ERROR: %s") % errormessage, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def _read_recent_file(self, filename, username=None, password=None):
|
||||
@@ -235,26 +258,30 @@ class CLIManager:
|
||||
if not os.path.isdir(filename):
|
||||
self._errordialog(
|
||||
_("Could not load a recent Family Tree."),
|
||||
_("Family Tree does not exist, as it has been deleted."))
|
||||
_("Family Tree does not exist, as it has been deleted."),
|
||||
)
|
||||
return
|
||||
|
||||
if os.path.isfile(os.path.join(filename, "lock")):
|
||||
self._errordialog(
|
||||
_("The database is locked."),
|
||||
_("Use the --force-unlock option if you are sure "
|
||||
"that the database is not in use."))
|
||||
_(
|
||||
"Use the --force-unlock option if you are sure "
|
||||
"that the database is not in use."
|
||||
),
|
||||
)
|
||||
return
|
||||
|
||||
if self.db_loader.read_file(filename, username, password):
|
||||
# Attempt to figure out the database title
|
||||
path = os.path.join(filename, "name.txt")
|
||||
try:
|
||||
with open(path, encoding='utf8') as ifile:
|
||||
with open(path, encoding="utf8") as ifile:
|
||||
title = ifile.readline().strip()
|
||||
except:
|
||||
title = filename
|
||||
|
||||
self._post_load_newdb(filename, 'x-directory/normal', title)
|
||||
self._post_load_newdb(filename, "x-directory/normal", title)
|
||||
|
||||
def _post_load_newdb(self, filename, filetype, title=None):
|
||||
"""
|
||||
@@ -283,20 +310,18 @@ class CLIManager:
|
||||
# If the DB Owner Info is empty and
|
||||
# [default] Researcher is not empty and
|
||||
# database is empty, then copy default researcher to DB owner
|
||||
if (res.is_empty()
|
||||
and not owner.is_empty()
|
||||
and self.dbstate.db.get_total() == 0):
|
||||
if res.is_empty() and not owner.is_empty() and self.dbstate.db.get_total() == 0:
|
||||
self.dbstate.db.set_researcher(owner)
|
||||
|
||||
name_displayer.clear_custom_formats()
|
||||
name_displayer.set_name_format(self.dbstate.db.name_formats)
|
||||
fmt_default = config.get('preferences.name-format')
|
||||
fmt_default = config.get("preferences.name-format")
|
||||
name_displayer.set_default_format(fmt_default)
|
||||
|
||||
self.dbstate.db.enable_signals()
|
||||
self.dbstate.signal_change()
|
||||
|
||||
config.set('paths.recent-file', filename)
|
||||
config.set("paths.recent-file", filename)
|
||||
|
||||
recent_files(filename, name)
|
||||
self.file_loaded = True
|
||||
@@ -310,6 +335,7 @@ class CLIManager:
|
||||
if rescan: # supports updated plugin installs
|
||||
self._pmgr.reload_plugins()
|
||||
|
||||
|
||||
def startcli(errors, argparser):
|
||||
"""
|
||||
Starts a cli session of Gramps.
|
||||
@@ -319,17 +345,16 @@ def startcli(errors, argparser):
|
||||
"""
|
||||
if errors:
|
||||
# already errors encountered. Show first one on terminal and exit
|
||||
errmsg = _('Error encountered: %s') % errors[0][0]
|
||||
errmsg = _("Error encountered: %s") % errors[0][0]
|
||||
print(errmsg, file=sys.stderr)
|
||||
errmsg = _(' Details: %s') % errors[0][1]
|
||||
errmsg = _(" Details: %s") % errors[0][1]
|
||||
print(errmsg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if argparser.errors:
|
||||
errmsg = _('Error encountered in argument parsing: %s'
|
||||
) % argparser.errors[0][0]
|
||||
errmsg = _("Error encountered in argument parsing: %s") % argparser.errors[0][0]
|
||||
print(errmsg, file=sys.stderr)
|
||||
errmsg = _(' Details: %s') % argparser.errors[0][1]
|
||||
errmsg = _(" Details: %s") % argparser.errors[0][1]
|
||||
print(errmsg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -338,6 +363,7 @@ def startcli(errors, argparser):
|
||||
|
||||
# we need a manager for the CLI session
|
||||
from .user import User
|
||||
|
||||
user = User(auto_accept=argparser.auto_accept, quiet=argparser.quiet)
|
||||
climanager = CLIManager(dbstate, True, user)
|
||||
|
||||
@@ -346,6 +372,7 @@ def startcli(errors, argparser):
|
||||
reload_custom_filters()
|
||||
# handle the arguments
|
||||
from .arghandler import ArgHandler
|
||||
|
||||
handler = ArgHandler(dbstate, argparser, climanager)
|
||||
# create a manager to manage the database
|
||||
|
||||
|
@@ -38,6 +38,7 @@ import os
|
||||
import sys
|
||||
|
||||
import logging
|
||||
|
||||
LOG = logging.getLogger(".")
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -46,27 +47,51 @@ LOG = logging.getLogger(".")
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.plug.docgen import (StyleSheet, StyleSheetList, PaperStyle,
|
||||
PAPER_PORTRAIT, PAPER_LANDSCAPE, graphdoc,
|
||||
treedoc)
|
||||
from gramps.gen.plug.menu import (FamilyOption, PersonOption, NoteOption,
|
||||
MediaOption, PersonListOption, NumberOption,
|
||||
BooleanOption, DestinationOption, Option,
|
||||
TextOption, EnumeratedListOption,
|
||||
StringOption)
|
||||
from gramps.gen.plug.docgen import (
|
||||
StyleSheet,
|
||||
StyleSheetList,
|
||||
PaperStyle,
|
||||
PAPER_PORTRAIT,
|
||||
PAPER_LANDSCAPE,
|
||||
graphdoc,
|
||||
treedoc,
|
||||
)
|
||||
from gramps.gen.plug.menu import (
|
||||
FamilyOption,
|
||||
PersonOption,
|
||||
NoteOption,
|
||||
MediaOption,
|
||||
PersonListOption,
|
||||
NumberOption,
|
||||
BooleanOption,
|
||||
DestinationOption,
|
||||
Option,
|
||||
TextOption,
|
||||
EnumeratedListOption,
|
||||
StringOption,
|
||||
)
|
||||
from gramps.gen.display.name import displayer as name_displayer
|
||||
from gramps.gen.errors import ReportError, FilterError
|
||||
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
||||
CATEGORY_GRAPHVIZ, CATEGORY_TREE,
|
||||
CATEGORY_CODE, ReportOptions, append_styles)
|
||||
from gramps.gen.plug.report import (
|
||||
CATEGORY_TEXT,
|
||||
CATEGORY_DRAW,
|
||||
CATEGORY_BOOK,
|
||||
CATEGORY_GRAPHVIZ,
|
||||
CATEGORY_TREE,
|
||||
CATEGORY_CODE,
|
||||
ReportOptions,
|
||||
append_styles,
|
||||
)
|
||||
from gramps.gen.plug.report._paper import paper_sizes
|
||||
from gramps.gen.const import USER_HOME, DOCGEN_OPTIONS
|
||||
from gramps.gen.dbstate import DbState
|
||||
from ..grampscli import CLIManager
|
||||
from ..user import User
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Private Functions
|
||||
@@ -80,8 +105,9 @@ def _convert_str_to_match_type(str_val, type_val):
|
||||
ret_type = type(type_val)
|
||||
|
||||
if isinstance(type_val, str):
|
||||
if ((str_val.startswith("'") and str_val.endswith("'"))
|
||||
or (str_val.startswith('"') and str_val.endswith('"'))):
|
||||
if (str_val.startswith("'") and str_val.endswith("'")) or (
|
||||
str_val.startswith('"') and str_val.endswith('"')
|
||||
):
|
||||
# Remove enclosing quotes
|
||||
return str(str_val[1:-1])
|
||||
else:
|
||||
@@ -141,6 +167,7 @@ def _convert_str_to_match_type(str_val, type_val):
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def _validate_options(options, dbase):
|
||||
"""
|
||||
Validate all options by making sure that their values are consistent with
|
||||
@@ -168,8 +195,7 @@ def _validate_options(options, dbase):
|
||||
phandle = None
|
||||
person = dbase.get_person_from_handle(phandle)
|
||||
if not person:
|
||||
print(_("ERROR: Please specify a person"),
|
||||
file=sys.stderr)
|
||||
print(_("ERROR: Please specify a person"), file=sys.stderr)
|
||||
if person:
|
||||
option.set_value(person.get_gramps_id())
|
||||
|
||||
@@ -195,6 +221,7 @@ def _validate_options(options, dbase):
|
||||
else:
|
||||
print(_("ERROR: Please specify a family"), file=sys.stderr)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Command-line report
|
||||
@@ -205,9 +232,9 @@ class CommandLineReport:
|
||||
Provide a way to generate report from the command line.
|
||||
"""
|
||||
|
||||
def __init__(self, database, name, category, option_class, options_str_dict,
|
||||
noopt=False):
|
||||
|
||||
def __init__(
|
||||
self, database, name, category, option_class, options_str_dict, noopt=False
|
||||
):
|
||||
pmgr = BasePluginManager.get_instance()
|
||||
self.__textdoc_plugins = []
|
||||
self.__drawdoc_plugins = []
|
||||
@@ -217,9 +244,11 @@ class CommandLineReport:
|
||||
self.__textdoc_plugins.append(plugin)
|
||||
if plugin.get_draw_support() and plugin.get_extension():
|
||||
self.__drawdoc_plugins.append(plugin)
|
||||
if (plugin.get_extension()
|
||||
if (
|
||||
plugin.get_extension()
|
||||
and plugin.get_text_support()
|
||||
and plugin.get_draw_support()):
|
||||
and plugin.get_draw_support()
|
||||
):
|
||||
self.__bookdoc_plugins.append(plugin)
|
||||
|
||||
self.database = database
|
||||
@@ -249,8 +278,9 @@ class CommandLineReport:
|
||||
self.__gvoptions.add_menu_options(menu)
|
||||
for name in menu.get_all_option_names():
|
||||
if name not in self.option_class.options_dict:
|
||||
self.option_class.options_dict[
|
||||
name] = menu.get_option_by_name(name).get_value()
|
||||
self.option_class.options_dict[name] = menu.get_option_by_name(
|
||||
name
|
||||
).get_value()
|
||||
if category == CATEGORY_TREE:
|
||||
# Need to include Genealogy Tree options
|
||||
self.__toptions = treedoc.TreeOptions()
|
||||
@@ -258,11 +288,12 @@ class CommandLineReport:
|
||||
self.__toptions.add_menu_options(menu)
|
||||
for name in menu.get_all_option_names():
|
||||
if name not in self.option_class.options_dict:
|
||||
self.option_class.options_dict[
|
||||
name] = menu.get_option_by_name(name).get_value()
|
||||
self.option_class.options_dict[name] = menu.get_option_by_name(
|
||||
name
|
||||
).get_value()
|
||||
self.option_class.load_previous_values()
|
||||
_validate_options(self.option_class, database)
|
||||
self.show = options_str_dict.pop('show', None)
|
||||
self.show = options_str_dict.pop("show", None)
|
||||
|
||||
self.options_str_dict = options_str_dict
|
||||
self.init_standard_options(noopt)
|
||||
@@ -276,76 +307,76 @@ class CommandLineReport:
|
||||
Initialize the options that are hard-coded into the report system.
|
||||
"""
|
||||
self.options_dict = {
|
||||
'of' : self.option_class.handler.module_name,
|
||||
'off' : self.option_class.handler.get_format_name(),
|
||||
'style' :
|
||||
self.option_class.handler.get_default_stylesheet_name(),
|
||||
'papers' : self.option_class.handler.get_paper_name(),
|
||||
'papero' : self.option_class.handler.get_orientation(),
|
||||
'paperml' : self.option_class.handler.get_margins()[0],
|
||||
'papermr' : self.option_class.handler.get_margins()[1],
|
||||
'papermt' : self.option_class.handler.get_margins()[2],
|
||||
'papermb' : self.option_class.handler.get_margins()[3],
|
||||
'css' : self.option_class.handler.get_css_filename(),
|
||||
"of": self.option_class.handler.module_name,
|
||||
"off": self.option_class.handler.get_format_name(),
|
||||
"style": self.option_class.handler.get_default_stylesheet_name(),
|
||||
"papers": self.option_class.handler.get_paper_name(),
|
||||
"papero": self.option_class.handler.get_orientation(),
|
||||
"paperml": self.option_class.handler.get_margins()[0],
|
||||
"papermr": self.option_class.handler.get_margins()[1],
|
||||
"papermt": self.option_class.handler.get_margins()[2],
|
||||
"papermb": self.option_class.handler.get_margins()[3],
|
||||
"css": self.option_class.handler.get_css_filename(),
|
||||
}
|
||||
|
||||
self.options_help = {
|
||||
'of' : [_("=filename"),
|
||||
_("Output file name. MANDATORY"), ""],
|
||||
'off' : [_("=format"), _("Output file format."), []],
|
||||
'style' : [_("=name"), _("Style name."), ""],
|
||||
'papers' : [_("=name"), _("Paper size name."), ""],
|
||||
'papero' : [_("=number"), _("Paper orientation number."), ""],
|
||||
'paperml' : [_("=number"),
|
||||
_("Left paper margin"), _("Size in cm")],
|
||||
'papermr' : [_("=number"),
|
||||
_("Right paper margin"), _("Size in cm")],
|
||||
'papermt' : [_("=number"),
|
||||
_("Top paper margin"), _("Size in cm")],
|
||||
'papermb' : [_("=number"),
|
||||
_("Bottom paper margin"), _("Size in cm")],
|
||||
'css' : [_("=css filename"),
|
||||
_("CSS filename to use, html format only"), ""],
|
||||
"of": [_("=filename"), _("Output file name. MANDATORY"), ""],
|
||||
"off": [_("=format"), _("Output file format."), []],
|
||||
"style": [_("=name"), _("Style name."), ""],
|
||||
"papers": [_("=name"), _("Paper size name."), ""],
|
||||
"papero": [_("=number"), _("Paper orientation number."), ""],
|
||||
"paperml": [_("=number"), _("Left paper margin"), _("Size in cm")],
|
||||
"papermr": [_("=number"), _("Right paper margin"), _("Size in cm")],
|
||||
"papermt": [_("=number"), _("Top paper margin"), _("Size in cm")],
|
||||
"papermb": [_("=number"), _("Bottom paper margin"), _("Size in cm")],
|
||||
"css": [_("=css filename"), _("CSS filename to use, html format only"), ""],
|
||||
}
|
||||
|
||||
if noopt:
|
||||
return
|
||||
|
||||
self.options_help['of'][2] = os.path.join(USER_HOME,
|
||||
"whatever_name")
|
||||
self.options_help["of"][2] = os.path.join(USER_HOME, "whatever_name")
|
||||
|
||||
if self.category == CATEGORY_TEXT:
|
||||
for plugin in self.__textdoc_plugins:
|
||||
self.options_help['off'][2].append(
|
||||
plugin.get_extension() + "\t" + plugin.get_description())
|
||||
self.options_help["off"][2].append(
|
||||
plugin.get_extension() + "\t" + plugin.get_description()
|
||||
)
|
||||
elif self.category == CATEGORY_DRAW:
|
||||
for plugin in self.__drawdoc_plugins:
|
||||
self.options_help['off'][2].append(
|
||||
plugin.get_extension() + "\t" + plugin.get_description())
|
||||
self.options_help["off"][2].append(
|
||||
plugin.get_extension() + "\t" + plugin.get_description()
|
||||
)
|
||||
elif self.category == CATEGORY_BOOK:
|
||||
for plugin in self.__bookdoc_plugins:
|
||||
self.options_help['off'][2].append(
|
||||
plugin.get_extension() + "\t" + plugin.get_description())
|
||||
self.options_help["off"][2].append(
|
||||
plugin.get_extension() + "\t" + plugin.get_description()
|
||||
)
|
||||
elif self.category == CATEGORY_GRAPHVIZ:
|
||||
for graph_format in graphdoc.FORMATS:
|
||||
self.options_help['off'][2].append(
|
||||
graph_format["type"] + "\t" + graph_format["descr"])
|
||||
self.options_help["off"][2].append(
|
||||
graph_format["type"] + "\t" + graph_format["descr"]
|
||||
)
|
||||
elif self.category == CATEGORY_TREE:
|
||||
for tree_format in treedoc.FORMATS:
|
||||
self.options_help['off'][2].append(
|
||||
tree_format["type"] + "\t" + tree_format["descr"])
|
||||
self.options_help["off"][2].append(
|
||||
tree_format["type"] + "\t" + tree_format["descr"]
|
||||
)
|
||||
else:
|
||||
self.options_help['off'][2] = "NA"
|
||||
self.options_help["off"][2] = "NA"
|
||||
|
||||
self.options_help['papers'][2] = [
|
||||
paper.get_name() for paper in paper_sizes
|
||||
if paper.get_name() != 'Custom Size']
|
||||
self.options_help["papers"][2] = [
|
||||
paper.get_name()
|
||||
for paper in paper_sizes
|
||||
if paper.get_name() != "Custom Size"
|
||||
]
|
||||
|
||||
self.options_help['papero'][2] = ["%d\tPortrait" % PAPER_PORTRAIT,
|
||||
"%d\tLandscape" % PAPER_LANDSCAPE]
|
||||
self.options_help["papero"][2] = [
|
||||
"%d\tPortrait" % PAPER_PORTRAIT,
|
||||
"%d\tLandscape" % PAPER_LANDSCAPE,
|
||||
]
|
||||
|
||||
self.options_help['css'][2] = os.path.join(USER_HOME,
|
||||
"whatever_name.css")
|
||||
self.options_help["css"][2] = os.path.join(USER_HOME, "whatever_name.css")
|
||||
|
||||
if self.category in (CATEGORY_TEXT, CATEGORY_DRAW):
|
||||
default_style = StyleSheet()
|
||||
@@ -355,7 +386,7 @@ class CommandLineReport:
|
||||
style_file = self.option_class.handler.get_stylesheet_savefile()
|
||||
self.style_list = StyleSheetList(style_file, default_style)
|
||||
|
||||
self.options_help['style'][2] = self.style_list.get_style_names()
|
||||
self.options_help["style"][2] = self.style_list.get_style_names()
|
||||
|
||||
def init_report_options(self):
|
||||
"""
|
||||
@@ -365,10 +396,9 @@ class CommandLineReport:
|
||||
if self.category == CATEGORY_BOOK: # a Book Report has no "menu"
|
||||
for key in self.option_class.options_dict:
|
||||
self.options_dict[key] = self.option_class.options_dict[key]
|
||||
self.options_help[
|
||||
key] = self.option_class.options_help[key][:3]
|
||||
self.options_help[key] = self.option_class.options_help[key][:3]
|
||||
# a Book Report can't have HTML output so "css" is meaningless
|
||||
self.options_dict.pop('css')
|
||||
self.options_dict.pop("css")
|
||||
|
||||
if not hasattr(self.option_class, "menu"):
|
||||
return
|
||||
@@ -393,9 +423,10 @@ class CommandLineReport:
|
||||
id_list = []
|
||||
for person_handle in self.database.get_person_handles(True):
|
||||
person = self.database.get_person_from_handle(person_handle)
|
||||
id_list.append("%s\t%s"
|
||||
% (person.get_gramps_id(),
|
||||
name_displayer.display(person)))
|
||||
id_list.append(
|
||||
"%s\t%s"
|
||||
% (person.get_gramps_id(), name_displayer.display(person))
|
||||
)
|
||||
self.options_help[name].append(id_list)
|
||||
elif isinstance(option, FamilyOption):
|
||||
id_list = []
|
||||
@@ -413,9 +444,11 @@ class CommandLineReport:
|
||||
if father:
|
||||
fname = name_displayer.display(father)
|
||||
# Translators: needed for French, Hebrew and Arabic
|
||||
text = _("%(id)s:\t%(father)s, %(mother)s"
|
||||
) % {'id': family.get_gramps_id(),
|
||||
'father': fname, 'mother': mname}
|
||||
text = _("%(id)s:\t%(father)s, %(mother)s") % {
|
||||
"id": family.get_gramps_id(),
|
||||
"father": fname,
|
||||
"mother": mname,
|
||||
}
|
||||
id_list.append(text)
|
||||
self.options_help[name].append(id_list)
|
||||
elif isinstance(option, NoteOption):
|
||||
@@ -443,13 +476,14 @@ class CommandLineReport:
|
||||
elif isinstance(option, TextOption):
|
||||
self.options_help[name].append(
|
||||
"A list of text values. Each entry in the list "
|
||||
"represents one line of text.")
|
||||
"represents one line of text."
|
||||
)
|
||||
elif isinstance(option, EnumeratedListOption):
|
||||
ilist = []
|
||||
for (value, description) in option.get_items():
|
||||
tabs = '\t'
|
||||
for value, description in option.get_items():
|
||||
tabs = "\t"
|
||||
try:
|
||||
tabs = '\t\t' if len(value) < 10 else '\t'
|
||||
tabs = "\t\t" if len(value) < 10 else "\t"
|
||||
except TypeError: # Value is a number, use just one tab.
|
||||
pass
|
||||
val = "%s%s%s" % (value, tabs, description)
|
||||
@@ -459,13 +493,19 @@ class CommandLineReport:
|
||||
self.options_help[name].append(option.get_help())
|
||||
else:
|
||||
print(_("Unknown option: %s") % option, file=sys.stderr)
|
||||
print(_(" Valid options are:") +
|
||||
_(", ").join(list(self.options_dict.keys())), # Arabic OK
|
||||
file=sys.stderr)
|
||||
print(_(" Use '%(donottranslate)s' to see description "
|
||||
print(
|
||||
_(" Valid options are:")
|
||||
+ _(", ").join(list(self.options_dict.keys())), # Arabic OK
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
_(
|
||||
" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values"
|
||||
) % {'donottranslate' : "show=option"},
|
||||
file=sys.stderr)
|
||||
)
|
||||
% {"donottranslate": "show=option"},
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
def parse_options(self):
|
||||
"""
|
||||
@@ -477,9 +517,9 @@ class CommandLineReport:
|
||||
menu = self.option_class.menu
|
||||
menu_opt_names = menu.get_all_option_names()
|
||||
|
||||
_format_str = self.options_str_dict.pop('off', None)
|
||||
_format_str = self.options_str_dict.pop("off", None)
|
||||
if _format_str:
|
||||
self.options_dict['off'] = _format_str
|
||||
self.options_dict["off"] = _format_str
|
||||
|
||||
self.css_filename = None
|
||||
_chosen_format = None
|
||||
@@ -488,13 +528,13 @@ class CommandLineReport:
|
||||
if self.category in [CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK]:
|
||||
if self.category == CATEGORY_TEXT:
|
||||
plugins = self.__textdoc_plugins
|
||||
self.css_filename = self.options_dict['css']
|
||||
self.css_filename = self.options_dict["css"]
|
||||
elif self.category == CATEGORY_DRAW:
|
||||
plugins = self.__drawdoc_plugins
|
||||
elif self.category == CATEGORY_BOOK:
|
||||
plugins = self.__bookdoc_plugins
|
||||
for plugin in plugins:
|
||||
if plugin.get_extension() == self.options_dict['off']:
|
||||
if plugin.get_extension() == self.options_dict["off"]:
|
||||
self.format = plugin.get_basedoc()
|
||||
self.doc_option_class = plugin.get_doc_option_class()
|
||||
if self.format is None:
|
||||
@@ -505,7 +545,7 @@ class CommandLineReport:
|
||||
_chosen_format = plugin.get_extension()
|
||||
elif self.category == CATEGORY_GRAPHVIZ:
|
||||
for graph_format in graphdoc.FORMATS:
|
||||
if graph_format['type'] == self.options_dict['off']:
|
||||
if graph_format["type"] == self.options_dict["off"]:
|
||||
if not self.format: # choose the first one, not the last
|
||||
self.format = graph_format["class"]
|
||||
if self.format is None:
|
||||
@@ -514,7 +554,7 @@ class CommandLineReport:
|
||||
_chosen_format = graphdoc.FORMATS[0]["type"]
|
||||
elif self.category == CATEGORY_TREE:
|
||||
for tree_format in treedoc.FORMATS:
|
||||
if tree_format['type'] == self.options_dict['off']:
|
||||
if tree_format["type"] == self.options_dict["off"]:
|
||||
if not self.format: # choose the first one, not the last
|
||||
self.format = tree_format["class"]
|
||||
if self.format is None:
|
||||
@@ -524,24 +564,33 @@ class CommandLineReport:
|
||||
else:
|
||||
self.format = None
|
||||
if _chosen_format and _format_str:
|
||||
print(_("Ignoring '%(notranslate1)s=%(notranslate2)s' "
|
||||
print(
|
||||
_(
|
||||
"Ignoring '%(notranslate1)s=%(notranslate2)s' "
|
||||
"and using '%(notranslate1)s=%(notranslate3)s'."
|
||||
) % {'notranslate1' : "off",
|
||||
'notranslate2' : self.options_dict['off'],
|
||||
'notranslate3' : _chosen_format},
|
||||
file=sys.stderr)
|
||||
print(_("Use '%(notranslate)s' to see valid values."
|
||||
) % {'notranslate' : "show=off"}, file=sys.stderr)
|
||||
)
|
||||
% {
|
||||
"notranslate1": "off",
|
||||
"notranslate2": self.options_dict["off"],
|
||||
"notranslate3": _chosen_format,
|
||||
},
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
_("Use '%(notranslate)s' to see valid values.")
|
||||
% {"notranslate": "show=off"},
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
self.do_doc_options()
|
||||
|
||||
for opt in self.options_str_dict:
|
||||
if opt in self.options_dict:
|
||||
self.options_dict[opt] = _convert_str_to_match_type(
|
||||
self.options_str_dict[opt], self.options_dict[opt])
|
||||
self.options_str_dict[opt], self.options_dict[opt]
|
||||
)
|
||||
|
||||
self.option_class.handler.options_dict[
|
||||
opt] = self.options_dict[opt]
|
||||
self.option_class.handler.options_dict[opt] = self.options_dict[opt]
|
||||
|
||||
if menu and opt in menu_opt_names:
|
||||
option = menu.get_option_by_name(opt)
|
||||
@@ -549,28 +598,34 @@ class CommandLineReport:
|
||||
|
||||
else:
|
||||
print(_("Ignoring unknown option: %s") % opt, file=sys.stderr)
|
||||
print(_(" Valid options are:"),
|
||||
print(
|
||||
_(" Valid options are:"),
|
||||
_(", ").join(list(self.options_dict.keys())), # Arabic OK
|
||||
file=sys.stderr)
|
||||
print(_(" Use '%(donottranslate)s' to see description "
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
_(
|
||||
" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values"
|
||||
) % {'donottranslate' : "show=option"},
|
||||
file=sys.stderr)
|
||||
)
|
||||
% {"donottranslate": "show=option"},
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
self.option_class.handler.output = self.options_dict['of']
|
||||
self.option_class.handler.output = self.options_dict["of"]
|
||||
|
||||
self.paper = paper_sizes[0] # make sure one exists
|
||||
for paper in paper_sizes:
|
||||
if paper.get_name() == self.options_dict['papers']:
|
||||
if paper.get_name() == self.options_dict["papers"]:
|
||||
self.paper = paper
|
||||
self.option_class.handler.set_paper(self.paper)
|
||||
|
||||
self.orien = self.options_dict['papero']
|
||||
self.orien = self.options_dict["papero"]
|
||||
|
||||
self.marginl = self.options_dict['paperml']
|
||||
self.marginr = self.options_dict['papermr']
|
||||
self.margint = self.options_dict['papermt']
|
||||
self.marginb = self.options_dict['papermb']
|
||||
self.marginl = self.options_dict["paperml"]
|
||||
self.marginr = self.options_dict["papermr"]
|
||||
self.margint = self.options_dict["papermt"]
|
||||
self.marginb = self.options_dict["papermb"]
|
||||
|
||||
if self.category in (CATEGORY_TEXT, CATEGORY_DRAW):
|
||||
default_style = StyleSheet()
|
||||
@@ -593,8 +648,7 @@ class CommandLineReport:
|
||||
return # this docgen type has no options
|
||||
try:
|
||||
if issubclass(self.doc_option_class, object):
|
||||
self.doc_options = self.doc_option_class(self.raw_name,
|
||||
self.database)
|
||||
self.doc_options = self.doc_option_class(self.raw_name, self.database)
|
||||
doc_options_dict = self.doc_options.options_dict
|
||||
except TypeError:
|
||||
self.doc_options = self.doc_option_class
|
||||
@@ -605,7 +659,8 @@ class CommandLineReport:
|
||||
docgen_opt = docgen_menu.get_option(DOCGEN_OPTIONS, oname)
|
||||
if oname in self.options_str_dict and oname in doc_options_dict:
|
||||
doc_options_dict[oname] = _convert_str_to_match_type(
|
||||
self.options_str_dict[oname], doc_options_dict[oname])
|
||||
self.options_str_dict[oname], doc_options_dict[oname]
|
||||
)
|
||||
self.options_str_dict.pop(oname)
|
||||
if oname in doc_options_dict:
|
||||
docgen_opt.set_value(doc_options_dict[oname])
|
||||
@@ -620,26 +675,29 @@ class CommandLineReport:
|
||||
"""
|
||||
if not self.show:
|
||||
return
|
||||
elif self.show == 'all':
|
||||
elif self.show == "all":
|
||||
print(_(" Available options:"))
|
||||
for key in sorted(self.options_dict.keys()):
|
||||
if key in self.options_help:
|
||||
opt = self.options_help[key]
|
||||
# Make the output nicer to read, assume a tab has 8 spaces
|
||||
tabs = '\t\t' if len(key) < 10 else '\t'
|
||||
tabs = "\t\t" if len(key) < 10 else "\t"
|
||||
optmsg = " %s%s%s (%s)" % (key, tabs, opt[1], opt[0])
|
||||
else:
|
||||
optmsg = " %s%s%s" % (key, tabs,
|
||||
_('(no help available)'))
|
||||
optmsg = " %s%s%s" % (key, tabs, _("(no help available)"))
|
||||
print(optmsg)
|
||||
print(_(" Use '%(donottranslate)s' to see description "
|
||||
print(
|
||||
_(
|
||||
" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values"
|
||||
) % {'donottranslate' : "show=option"})
|
||||
)
|
||||
% {"donottranslate": "show=option"}
|
||||
)
|
||||
elif self.show in self.options_help:
|
||||
opt = self.options_help[self.show]
|
||||
tabs = '\t\t' if len(self.show) < 10 else '\t'
|
||||
tabs = "\t\t" if len(self.show) < 10 else "\t"
|
||||
print(_(" Available values are:"))
|
||||
print(' %s%s%s (%s)' % (self.show, tabs, opt[1], opt[0]))
|
||||
print(" %s%s%s (%s)" % (self.show, tabs, opt[1], opt[0]))
|
||||
vals = opt[2]
|
||||
if isinstance(vals, (list, tuple)):
|
||||
for val in vals:
|
||||
@@ -649,26 +707,28 @@ class CommandLineReport:
|
||||
|
||||
else:
|
||||
# there was a show option given, but the option is invalid
|
||||
print(_("option '%(optionname)s' not valid. "
|
||||
print(
|
||||
_(
|
||||
"option '%(optionname)s' not valid. "
|
||||
"Use '%(donottranslate)s' to see all valid options."
|
||||
) % {'optionname' : self.show,
|
||||
'donottranslate' : "show=all"},
|
||||
file=sys.stderr)
|
||||
)
|
||||
% {"optionname": self.show, "donottranslate": "show=all"},
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Command-line report generic task
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
def cl_report(database, name, category, report_class, options_class,
|
||||
options_str_dict):
|
||||
def cl_report(database, name, category, report_class, options_class, options_str_dict):
|
||||
"""
|
||||
function to actually run the selected report
|
||||
"""
|
||||
|
||||
err_msg = _("Failed to write report. ")
|
||||
clr = CommandLineReport(database, name, category, options_class,
|
||||
options_str_dict)
|
||||
clr = CommandLineReport(database, name, category, options_class, options_str_dict)
|
||||
|
||||
# Exit here if show option was given
|
||||
if clr.show:
|
||||
@@ -680,21 +740,43 @@ def cl_report(database, name, category, report_class, options_class,
|
||||
if clr.doc_options:
|
||||
clr.option_class.handler.doc = clr.format(
|
||||
clr.selected_style,
|
||||
PaperStyle(clr.paper, clr.orien, clr.marginl,
|
||||
clr.marginr, clr.margint, clr.marginb),
|
||||
clr.doc_options)
|
||||
PaperStyle(
|
||||
clr.paper,
|
||||
clr.orien,
|
||||
clr.marginl,
|
||||
clr.marginr,
|
||||
clr.margint,
|
||||
clr.marginb,
|
||||
),
|
||||
clr.doc_options,
|
||||
)
|
||||
else:
|
||||
clr.option_class.handler.doc = clr.format(
|
||||
clr.selected_style,
|
||||
PaperStyle(clr.paper, clr.orien, clr.marginl,
|
||||
clr.marginr, clr.margint, clr.marginb))
|
||||
PaperStyle(
|
||||
clr.paper,
|
||||
clr.orien,
|
||||
clr.marginl,
|
||||
clr.marginr,
|
||||
clr.margint,
|
||||
clr.marginb,
|
||||
),
|
||||
)
|
||||
elif category in [CATEGORY_GRAPHVIZ, CATEGORY_TREE]:
|
||||
clr.option_class.handler.doc = clr.format(
|
||||
clr.option_class,
|
||||
PaperStyle(clr.paper, clr.orien, clr.marginl,
|
||||
clr.marginr, clr.margint, clr.marginb))
|
||||
if (clr.css_filename is not None
|
||||
and hasattr(clr.option_class.handler.doc, 'set_css_filename')):
|
||||
PaperStyle(
|
||||
clr.paper,
|
||||
clr.orien,
|
||||
clr.marginl,
|
||||
clr.marginr,
|
||||
clr.margint,
|
||||
clr.marginb,
|
||||
),
|
||||
)
|
||||
if clr.css_filename is not None and hasattr(
|
||||
clr.option_class.handler.doc, "set_css_filename"
|
||||
):
|
||||
clr.option_class.handler.doc.set_css_filename(clr.css_filename)
|
||||
my_report = report_class(database, clr.option_class, User())
|
||||
my_report.doc.init()
|
||||
@@ -720,6 +802,7 @@ def cl_report(database, name, category, report_class, options_class,
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def run_report(db, name, **options_str_dict):
|
||||
"""
|
||||
Given a database, run a given report.
|
||||
@@ -757,15 +840,15 @@ def run_report(db, name, **options_str_dict):
|
||||
report_class = getattr(mod, pdata.reportclass)
|
||||
options_class = getattr(mod, pdata.optionclass)
|
||||
if category in (CATEGORY_BOOK, CATEGORY_CODE):
|
||||
options_class(db, name, category,
|
||||
options_str_dict)
|
||||
options_class(db, name, category, options_str_dict)
|
||||
else:
|
||||
clr = cl_report(db, name, category,
|
||||
report_class, options_class,
|
||||
options_str_dict)
|
||||
clr = cl_report(
|
||||
db, name, category, report_class, options_class, options_str_dict
|
||||
)
|
||||
return clr
|
||||
return clr
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Function to write books from command line
|
||||
@@ -777,22 +860,25 @@ def cl_book(database, name, book, options_str_dict):
|
||||
which in turn runs whatever reports the book has in it
|
||||
"""
|
||||
|
||||
clr = CommandLineReport(database, name, CATEGORY_BOOK,
|
||||
ReportOptions, options_str_dict)
|
||||
clr = CommandLineReport(
|
||||
database, name, CATEGORY_BOOK, ReportOptions, options_str_dict
|
||||
)
|
||||
|
||||
# Exit here if show option was given
|
||||
if clr.show:
|
||||
return
|
||||
|
||||
# write report
|
||||
doc = clr.format(None,
|
||||
PaperStyle(clr.paper, clr.orien, clr.marginl,
|
||||
clr.marginr, clr.margint, clr.marginb))
|
||||
doc = clr.format(
|
||||
None,
|
||||
PaperStyle(
|
||||
clr.paper, clr.orien, clr.marginl, clr.marginr, clr.margint, clr.marginb
|
||||
),
|
||||
)
|
||||
user = User()
|
||||
rptlist = []
|
||||
selected_style = StyleSheet()
|
||||
for item in book.get_item_list():
|
||||
|
||||
# The option values were loaded magically by the book parser.
|
||||
# But they still need to be applied to the menu options.
|
||||
opt_dict = item.option_class.options_dict
|
||||
@@ -804,9 +890,10 @@ def cl_book(database, name, book, options_str_dict):
|
||||
|
||||
item.option_class.set_document(doc)
|
||||
report_class = item.get_write_item()
|
||||
obj = (write_book_item(database,
|
||||
report_class, item.option_class, user),
|
||||
item.get_translated_name())
|
||||
obj = (
|
||||
write_book_item(database, report_class, item.option_class, user),
|
||||
item.get_translated_name(),
|
||||
)
|
||||
if obj:
|
||||
append_styles(selected_style, item)
|
||||
rptlist.append(obj)
|
||||
@@ -817,7 +904,7 @@ def cl_book(database, name, book, options_str_dict):
|
||||
newpage = 0
|
||||
err_msg = _("Failed to make '%s' report.")
|
||||
try:
|
||||
for (rpt, name) in rptlist:
|
||||
for rpt, name in rptlist:
|
||||
if newpage:
|
||||
doc.page_break()
|
||||
newpage = 1
|
||||
@@ -831,6 +918,7 @@ def cl_book(database, name, book, options_str_dict):
|
||||
if msg2:
|
||||
print(msg2, file=sys.stderr)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Generic task function for book
|
||||
|
@@ -25,6 +25,7 @@ import unittest
|
||||
from unittest.mock import Mock
|
||||
from ..argparser import ArgParser
|
||||
|
||||
|
||||
class TestArgParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pass
|
||||
@@ -37,44 +38,43 @@ class TestArgParser(unittest.TestCase):
|
||||
return (str(ap.errors).find("option " + option) >= 0, ap)
|
||||
|
||||
def test_wrong_argument_triggers_option_error(self):
|
||||
bad,ap = self.triggers_option_error('--I-am-a-wrong-argument')
|
||||
bad, ap = self.triggers_option_error("--I-am-a-wrong-argument")
|
||||
assert bad, ap.__dict__
|
||||
|
||||
def test_y_shortopt_sets_auto_accept(self):
|
||||
bad, ap = self.triggers_option_error('-y')
|
||||
bad, ap = self.triggers_option_error("-y")
|
||||
|
||||
self.assertFalse(bad)
|
||||
|
||||
expected_errors = [(
|
||||
'Error parsing the arguments',
|
||||
'Error parsing the arguments: [ -y ] \n' +
|
||||
'To use in the command-line mode, supply at least one input file to process.'
|
||||
)]
|
||||
self.assertEqual(
|
||||
expected_errors,
|
||||
ap.errors
|
||||
expected_errors = [
|
||||
(
|
||||
"Error parsing the arguments",
|
||||
"Error parsing the arguments: [ -y ] \n"
|
||||
+ "To use in the command-line mode, supply at least one input file to process.",
|
||||
)
|
||||
]
|
||||
self.assertEqual(expected_errors, ap.errors)
|
||||
|
||||
self.assertTrue(ap.auto_accept)
|
||||
|
||||
def test_yes_longopt_sets_auto_accept(self):
|
||||
bad,ap = self.triggers_option_error('--yes')
|
||||
bad, ap = self.triggers_option_error("--yes")
|
||||
assert not bad, ap.errors
|
||||
assert ap.auto_accept
|
||||
|
||||
def test_q_shortopt_sets_quiet(self):
|
||||
bad,ap = self.triggers_option_error('-q')
|
||||
bad, ap = self.triggers_option_error("-q")
|
||||
assert not bad, ap.errors
|
||||
assert ap.quiet
|
||||
|
||||
def test_quiet_longopt_sets_quiet(self):
|
||||
bad,ap = self.triggers_option_error('--quiet')
|
||||
bad, ap = self.triggers_option_error("--quiet")
|
||||
assert not bad, ap.errors
|
||||
assert ap.quiet
|
||||
|
||||
def test_quiet_exists_by_default(self):
|
||||
ap = self.create_parser()
|
||||
assert hasattr(ap,'quiet')
|
||||
assert hasattr(ap, "quiet")
|
||||
|
||||
def test_auto_accept_unset_by_default(self):
|
||||
ap = self.create_parser()
|
||||
@@ -83,20 +83,20 @@ class TestArgParser(unittest.TestCase):
|
||||
def test_exception(self):
|
||||
argument_parser = self.create_parser("-O")
|
||||
|
||||
expected_errors = [(
|
||||
'Error parsing the arguments',
|
||||
'option -O requires argument\n'
|
||||
'Error parsing the arguments: [ -O ] \n'
|
||||
'Type gramps --help for an overview of commands, or read the manual pages.'
|
||||
)]
|
||||
self.assertEqual(
|
||||
expected_errors,
|
||||
argument_parser.errors
|
||||
expected_errors = [
|
||||
(
|
||||
"Error parsing the arguments",
|
||||
"option -O requires argument\n"
|
||||
"Error parsing the arguments: [ -O ] \n"
|
||||
"Type gramps --help for an overview of commands, or read the manual pages.",
|
||||
)
|
||||
]
|
||||
self.assertEqual(expected_errors, argument_parser.errors)
|
||||
|
||||
def test_option_with_multiple_arguments(self):
|
||||
argument_parser = self.create_parser('-l', 'family_tree_name')
|
||||
self.assertEqual(argument_parser.database_names, ['family_tree_name'])
|
||||
argument_parser = self.create_parser("-l", "family_tree_name")
|
||||
self.assertEqual(argument_parser.database_names, ["family_tree_name"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -44,8 +44,8 @@ ddir = os.path.dirname(__file__)
|
||||
min1r = os.path.join(ddir, "min1r.ged")
|
||||
out_ged = os.path.join(ddir, "test_out.ged")
|
||||
example_copy = os.path.join(ddir, "copy.gramps")
|
||||
example = os.path.join(ddir, "..", "..", "..",
|
||||
"example", "gramps", "data.gramps")
|
||||
example = os.path.join(ddir, "..", "..", "..", "example", "gramps", "data.gramps")
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -70,8 +70,7 @@ class Test(unittest.TestCase):
|
||||
def test1_setup_works(self):
|
||||
self.assertTrue(os.path.exists(ddir), "data dir %r exists" % ddir)
|
||||
self.assertTrue(os.path.exists(min1r), "data file %r exists" % min1r)
|
||||
self.assertFalse(os.path.exists(out_ged),
|
||||
"NO out file %r yet" % out_ged)
|
||||
self.assertFalse(os.path.exists(out_ged), "NO out file %r yet" % out_ged)
|
||||
|
||||
# This tests the fix for bug #1331-1334
|
||||
# read trivial gedcom input, write gedcom output
|
||||
@@ -79,13 +78,11 @@ class Test(unittest.TestCase):
|
||||
ifile = min1r
|
||||
ofile = out_ged
|
||||
gcmd = [sys.executable, "Gramps.py", "-i", ifile, "-e", ofile]
|
||||
process = subprocess.Popen(gcmd,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
process = subprocess.Popen(
|
||||
gcmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
result_str, err_str = process.communicate()
|
||||
self.assertEqual(process.returncode, 0,
|
||||
"executed CLI command %r" % gcmd)
|
||||
self.assertEqual(process.returncode, 0, "executed CLI command %r" % gcmd)
|
||||
# simple validation o output
|
||||
self.assertTrue(os.path.isfile(ofile), "output file created")
|
||||
with open(ofile) as f:
|
||||
@@ -98,13 +95,11 @@ class Test(unittest.TestCase):
|
||||
ifile = min1r
|
||||
ofile = out_ged
|
||||
gcmd = [sys.executable, "-m", "gramps", "-i", ifile, "-e", ofile]
|
||||
process = subprocess.Popen(gcmd,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
process = subprocess.Popen(
|
||||
gcmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
result_str, err_str = process.communicate()
|
||||
self.assertEqual(process.returncode, 0,
|
||||
"executed CLI command %r" % gcmd)
|
||||
self.assertEqual(process.returncode, 0, "executed CLI command %r" % gcmd)
|
||||
# simple validation o output
|
||||
self.assertTrue(os.path.isfile(ofile), "output file created")
|
||||
with open(ofile) as f:
|
||||
@@ -114,39 +109,47 @@ class Test(unittest.TestCase):
|
||||
|
||||
|
||||
class UnicodeTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
from gramps.cli.clidbman import CLIDbManager
|
||||
from gramps.gen.config import set as setconfig, get as getconfig
|
||||
from gramps.gen.dbstate import DbState
|
||||
self.newpath = os.path.join(os.path.dirname(__file__),
|
||||
'\u0393\u03c1\u03b1\u03bc\u03c3\u03c0')
|
||||
self.newtitle = 'Gr\u00e4mps T\u00e9st'
|
||||
|
||||
self.newpath = os.path.join(
|
||||
os.path.dirname(__file__), "\u0393\u03c1\u03b1\u03bc\u03c3\u03c0"
|
||||
)
|
||||
self.newtitle = "Gr\u00e4mps T\u00e9st"
|
||||
os.makedirs(self.newpath)
|
||||
self.old_path = getconfig('database.path')
|
||||
setconfig('database.path', self.newpath)
|
||||
self.old_path = getconfig("database.path")
|
||||
setconfig("database.path", self.newpath)
|
||||
self.cli = CLIDbManager(DbState())
|
||||
|
||||
def tearDown(self):
|
||||
from gramps.gen.config import set as setconfig
|
||||
for (dirpath, dirnames, filenames) in os.walk(self.newpath, False):
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(self.newpath, False):
|
||||
for afile in filenames:
|
||||
os.remove(os.path.join(dirpath, afile))
|
||||
for adir in dirnames:
|
||||
os.rmdir(os.path.join(dirpath, adir))
|
||||
os.rmdir(self.newpath)
|
||||
setconfig('database.path', self.old_path)
|
||||
setconfig("database.path", self.old_path)
|
||||
|
||||
# Test that clidbman will open files in a path containing
|
||||
# arbitrary Unicode characters.
|
||||
def test4_arbitrary_uncode_path(self):
|
||||
(dbpath, title) = self.cli.create_new_db_cli(self.newtitle)
|
||||
|
||||
self.assertEqual(self.newpath, os.path.dirname(dbpath),
|
||||
"Compare paths %s and %s" % (repr(self.newpath),
|
||||
repr(dbpath)))
|
||||
self.assertEqual(self.newtitle, title, "Compare titles %s and %s" %
|
||||
(repr(self.newtitle), repr(title)))
|
||||
self.assertEqual(
|
||||
self.newpath,
|
||||
os.path.dirname(dbpath),
|
||||
"Compare paths %s and %s" % (repr(self.newpath), repr(dbpath)),
|
||||
)
|
||||
self.assertEqual(
|
||||
self.newtitle,
|
||||
title,
|
||||
"Compare titles %s and %s" % (repr(self.newtitle), repr(title)),
|
||||
)
|
||||
|
||||
|
||||
class CLITest(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
@@ -167,6 +170,7 @@ class CLITest(unittest.TestCase):
|
||||
def test1b_cli(self):
|
||||
self.call("-O", "Test: test1_cli", "--export", example_copy)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
|
@@ -26,12 +26,14 @@ from unittest.mock import Mock, patch
|
||||
from .. import user
|
||||
import sys
|
||||
|
||||
|
||||
class TestUser:
|
||||
TITLE = "Testing prompt"
|
||||
MSG = "Choices are hard. Nevertheless, please choose!"
|
||||
ACCEPT = "To be"
|
||||
REJECT = "Not to be"
|
||||
|
||||
|
||||
class TestUser_prompt(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.real_user = user.User()
|
||||
@@ -40,10 +42,10 @@ class TestUser_prompt(unittest.TestCase):
|
||||
self.user._input = Mock(spec=input)
|
||||
|
||||
def test_default_fileout_has_write(self):
|
||||
assert hasattr(self.real_user._fileout, 'write')
|
||||
assert hasattr(self.real_user._fileout, "write")
|
||||
|
||||
def test_default_input(self):
|
||||
assert self.real_user._input.__name__.endswith('input')
|
||||
assert self.real_user._input.__name__.endswith("input")
|
||||
|
||||
def test_prompt_returns_True_if_ACCEPT_entered(self):
|
||||
self.user._input.configure_mock(return_value=TestUser.ACCEPT)
|
||||
@@ -59,9 +61,14 @@ class TestUser_prompt(unittest.TestCase):
|
||||
), "False expected!"
|
||||
self.user._input.assert_called_once_with()
|
||||
|
||||
def assert_prompt_contains_text(self, text,
|
||||
title=TestUser.TITLE, msg=TestUser.MSG,
|
||||
accept=TestUser.ACCEPT, reject=TestUser.REJECT):
|
||||
def assert_prompt_contains_text(
|
||||
self,
|
||||
text,
|
||||
title=TestUser.TITLE,
|
||||
msg=TestUser.MSG,
|
||||
accept=TestUser.ACCEPT,
|
||||
reject=TestUser.REJECT,
|
||||
):
|
||||
self.user._input.configure_mock(return_value=TestUser.REJECT)
|
||||
self.user.prompt(title, msg, accept, reject)
|
||||
for call in self.user._fileout.method_calls:
|
||||
@@ -69,9 +76,12 @@ class TestUser_prompt(unittest.TestCase):
|
||||
for a in args:
|
||||
if a.find(text) >= 0:
|
||||
return
|
||||
self.assertTrue(False,
|
||||
self.assertTrue(
|
||||
False,
|
||||
"'{}' never printed in prompt: {}".format(
|
||||
text, self.user._fileout.method_calls))
|
||||
text, self.user._fileout.method_calls
|
||||
),
|
||||
)
|
||||
|
||||
def test_prompt_contains_title_text(self):
|
||||
self.assert_prompt_contains_text(TestUser.TITLE)
|
||||
@@ -101,13 +111,14 @@ class TestUser_prompt(unittest.TestCase):
|
||||
|
||||
def test_EOFError_in_prompt_caught_as_False(self):
|
||||
self.user._input.configure_mock(
|
||||
side_effect = EOFError,
|
||||
return_value = TestUser.REJECT)
|
||||
side_effect=EOFError, return_value=TestUser.REJECT
|
||||
)
|
||||
assert not self.user.prompt(
|
||||
TestUser.TITLE, TestUser.MSG, TestUser.ACCEPT, TestUser.REJECT
|
||||
), "False expected!"
|
||||
self.user._input.assert_called_once_with()
|
||||
|
||||
|
||||
class TestUser_quiet(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.user = user.User(quiet=True)
|
||||
@@ -120,11 +131,12 @@ class TestUser_quiet(unittest.TestCase):
|
||||
self.user.end_progress()
|
||||
|
||||
def tearDown(self):
|
||||
assert len(self.user._fileout.method_calls
|
||||
) == 0, list(self.user._fileout.method_calls)
|
||||
assert len(self.user._fileout.method_calls) == 0, list(
|
||||
self.user._fileout.method_calls
|
||||
)
|
||||
|
||||
|
||||
class TestUser_progress(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.user = user.User()
|
||||
self.user._fileout = Mock(spec=sys.stderr)
|
||||
@@ -136,18 +148,18 @@ class TestUser_progress(unittest.TestCase):
|
||||
self.user._fileout.reset_mock()
|
||||
self.assertTrue(
|
||||
len(self.user._fileout.method_calls) == 0,
|
||||
list(self.user._fileout.method_calls))
|
||||
list(self.user._fileout.method_calls),
|
||||
)
|
||||
|
||||
with self.user.progress("Foo", "Bar", 0) as step:
|
||||
for i in range(10):
|
||||
step()
|
||||
|
||||
# Output using `with' differs from one with `progress_...'
|
||||
self.assertEqual(self.expected_output,
|
||||
list(self.user._fileout.method_calls))
|
||||
self.assertEqual(self.expected_output, list(self.user._fileout.method_calls))
|
||||
|
||||
def test_ends_progress_upon_exception_in_with(self):
|
||||
with patch('gramps.cli.user.User.end_progress') as MockEP:
|
||||
with patch("gramps.cli.user.User.end_progress") as MockEP:
|
||||
try:
|
||||
with self.user.progress("Foo", "Bar", 0) as step:
|
||||
raise Exception()
|
||||
@@ -161,5 +173,6 @@ class TestUser_progress(unittest.TestCase):
|
||||
self.user.step_progress()
|
||||
self.user.end_progress()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -28,6 +28,7 @@ The User class provides basic interaction with the user.
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.const import URL_BUGHOME
|
||||
from gramps.gen import user
|
||||
@@ -37,7 +38,8 @@ from gramps.gen import user
|
||||
# Private Constants
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
_SPINNER = ['|', '/', '-', '\\']
|
||||
_SPINNER = ["|", "/", "-", "\\"]
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
@@ -49,9 +51,16 @@ class User(user.UserBase):
|
||||
This class provides a means to interact with the user via CLI.
|
||||
It implements the interface in :class:`.gen.user.UserBase`
|
||||
"""
|
||||
def __init__(self, callback=None, error=None,
|
||||
auto_accept=False, quiet=False,
|
||||
uistate=None, dbstate=None):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
callback=None,
|
||||
error=None,
|
||||
auto_accept=False,
|
||||
quiet=False,
|
||||
uistate=None,
|
||||
dbstate=None,
|
||||
):
|
||||
"""
|
||||
Init.
|
||||
|
||||
@@ -59,8 +68,8 @@ class User(user.UserBase):
|
||||
:type error: function(title, error)
|
||||
"""
|
||||
user.UserBase.__init__(self, callback, error, uistate, dbstate)
|
||||
self.steps = 0;
|
||||
self.current_step = 0;
|
||||
self.steps = 0
|
||||
self.current_step = 0
|
||||
self._input = input
|
||||
|
||||
def yes(*args, **kwargs):
|
||||
@@ -69,8 +78,9 @@ class User(user.UserBase):
|
||||
if auto_accept:
|
||||
self.prompt = yes
|
||||
if quiet:
|
||||
self.begin_progress = self.end_progress = self.step_progress = \
|
||||
self._default_callback = yes
|
||||
self.begin_progress = (
|
||||
self.end_progress
|
||||
) = self.step_progress = self._default_callback = yes
|
||||
|
||||
def begin_progress(self, title, message, steps):
|
||||
"""
|
||||
@@ -88,7 +98,7 @@ class User(user.UserBase):
|
||||
"""
|
||||
self._fileout.write(message)
|
||||
self.steps = steps
|
||||
self.current_step = 0;
|
||||
self.current_step = 0
|
||||
if self.steps == 0:
|
||||
self._fileout.write(_SPINNER[self.current_step])
|
||||
else:
|
||||
@@ -112,8 +122,15 @@ class User(user.UserBase):
|
||||
"""
|
||||
self._fileout.write("\r100%\n")
|
||||
|
||||
def prompt(self, title, message, accept_label, reject_label,
|
||||
parent=None, default_label=None):
|
||||
def prompt(
|
||||
self,
|
||||
title,
|
||||
message,
|
||||
accept_label,
|
||||
reject_label,
|
||||
parent=None,
|
||||
default_label=None,
|
||||
):
|
||||
"""
|
||||
Prompt the user with a message to select an alternative.
|
||||
|
||||
@@ -142,10 +159,8 @@ class User(user.UserBase):
|
||||
reject_text = "[%s]" % reject_text
|
||||
default = False
|
||||
text = "{t}\n{m} ({y}/{n}): ".format(
|
||||
t = title,
|
||||
m = message,
|
||||
y = accept_text,
|
||||
n = reject_text)
|
||||
t=title, m=message, y=accept_text, n=reject_text
|
||||
)
|
||||
print(text, file=self._fileout) # TODO: python 3.3 add flush=True
|
||||
try:
|
||||
reply = self._input()
|
||||
@@ -198,10 +213,15 @@ class User(user.UserBase):
|
||||
"""
|
||||
self.notify_error(
|
||||
_("Low level database corruption detected"),
|
||||
_("Gramps has detected a problem in the underlying "
|
||||
_(
|
||||
"Gramps has detected a problem in the underlying "
|
||||
"database. This can sometimes be repaired from "
|
||||
"the Family Tree Manager. Select the database and "
|
||||
'click on the Repair button') + '\n\n' + error)
|
||||
"click on the Repair button"
|
||||
)
|
||||
+ "\n\n"
|
||||
+ error,
|
||||
)
|
||||
|
||||
def notify_db_repair(self, error):
|
||||
"""
|
||||
@@ -214,14 +234,18 @@ class User(user.UserBase):
|
||||
These exact strings are also in gui/dialog.py -- keep them in sync
|
||||
"""
|
||||
self.notify_error(
|
||||
_('Error detected in database'),
|
||||
_('Gramps has detected an error in the database. This can '
|
||||
_("Error detected in database"),
|
||||
_(
|
||||
"Gramps has detected an error in the database. This can "
|
||||
'usually be resolved by running the "Check and Repair Database" '
|
||||
'tool.\n\nIf this problem continues to exist after running this '
|
||||
'tool, please file a bug report at '
|
||||
'%(gramps_bugtracker_url)s\n\n'
|
||||
) % {'gramps_bugtracker_url' : URL_BUGHOME}
|
||||
+ error + '\n\n')
|
||||
"tool.\n\nIf this problem continues to exist after running this "
|
||||
"tool, please file a bug report at "
|
||||
"%(gramps_bugtracker_url)s\n\n"
|
||||
)
|
||||
% {"gramps_bugtracker_url": URL_BUGHOME}
|
||||
+ error
|
||||
+ "\n\n",
|
||||
)
|
||||
|
||||
def info(self, msg1, infotext, parent=None, monospaced=False):
|
||||
"""
|
||||
|
@@ -23,5 +23,16 @@ The gen module provides packages that are common to all gramps
|
||||
interfaces (gui, cli and web).
|
||||
"""
|
||||
|
||||
__all__ = ["datehandler", "db", "display", "filters", "lib", "merge",
|
||||
"mime", "plug", "proxy", "simple", "utils"]
|
||||
__all__ = [
|
||||
"datehandler",
|
||||
"db",
|
||||
"display",
|
||||
"filters",
|
||||
"lib",
|
||||
"merge",
|
||||
"mime",
|
||||
"plug",
|
||||
"proxy",
|
||||
"simple",
|
||||
"utils",
|
||||
]
|
||||
|
@@ -44,12 +44,15 @@ import logging
|
||||
from .const import USER_CONFIG, USER_DATA, USER_HOME, VERSION_DIR
|
||||
from .utils.configmanager import ConfigManager
|
||||
from .const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
# _T_ is a gramps-defined keyword -- see po/update_po.py and po/genpot.sh
|
||||
def _T_(value, context=''): # enable deferred translations
|
||||
def _T_(value, context=""): # enable deferred translations
|
||||
return "%s\x04%s" % (context, value) if context else value
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
@@ -57,6 +60,7 @@ def _T_(value, context=''): # enable deferred translations
|
||||
# ---------------------------------------------------------------
|
||||
INIFILE = os.path.join(VERSION_DIR, "gramps.ini")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
#
|
||||
# Module functions
|
||||
@@ -66,38 +70,47 @@ def register(key, value):
|
||||
"""Module shortcut to register key, value"""
|
||||
return CONFIGMAN.register(key, value)
|
||||
|
||||
|
||||
def get(key):
|
||||
"""Module shortcut to get value from key"""
|
||||
return CONFIGMAN.get(key)
|
||||
|
||||
|
||||
def get_default(key):
|
||||
"""Module shortcut to get default from key"""
|
||||
return CONFIGMAN.get_default(key)
|
||||
|
||||
|
||||
def has_default(key):
|
||||
"""Module shortcut to get see if there is a default for key"""
|
||||
return CONFIGMAN.has_default(key)
|
||||
|
||||
|
||||
def get_sections():
|
||||
"""Module shortcut to get all section names of settings"""
|
||||
return CONFIGMAN.get_sections()
|
||||
|
||||
|
||||
def get_section_settings(section):
|
||||
"""Module shortcut to get all settings of a section"""
|
||||
return CONFIGMAN.get_section_settings(section)
|
||||
|
||||
|
||||
def set(key, value):
|
||||
"""Module shortcut to set value from key"""
|
||||
return CONFIGMAN.set(key, value)
|
||||
|
||||
|
||||
def is_set(key):
|
||||
"""Module shortcut to set value from key"""
|
||||
return CONFIGMAN.is_set(key)
|
||||
|
||||
|
||||
def save(filename=None):
|
||||
"""Module shortcut to save config file"""
|
||||
return CONFIGMAN.save(filename)
|
||||
|
||||
|
||||
def connect(key, func):
|
||||
"""
|
||||
Module shortcut to connect a key to a callback func.
|
||||
@@ -105,22 +118,27 @@ def connect(key, func):
|
||||
"""
|
||||
return CONFIGMAN.connect(key, func)
|
||||
|
||||
|
||||
def disconnect(callback_id):
|
||||
"""Module shortcut to remove callback by ID number"""
|
||||
return CONFIGMAN.disconnect(callback_id)
|
||||
|
||||
|
||||
def reset(key=None):
|
||||
"""Module shortcut to reset some or all config data"""
|
||||
return CONFIGMAN.reset(key)
|
||||
|
||||
|
||||
def load(filename=None, oldstyle=False):
|
||||
"""Module shortcut to load an INI file into config data"""
|
||||
return CONFIGMAN.load(filename, oldstyle)
|
||||
|
||||
|
||||
def emit(key):
|
||||
"""Module shortcut to call all callbacks associated with key"""
|
||||
return CONFIGMAN.emit(key)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
#
|
||||
# Register the system-wide settings in a singleton config manager
|
||||
@@ -129,224 +147,248 @@ def emit(key):
|
||||
|
||||
CONFIGMAN = ConfigManager(INIFILE, "plugins")
|
||||
|
||||
register('behavior.addmedia-image-dir', '')
|
||||
register('behavior.addmedia-relative-path', False)
|
||||
register('behavior.autoload', False)
|
||||
register('behavior.avg-generation-gap', 20)
|
||||
register('behavior.check-for-addon-updates', 0)
|
||||
register('behavior.check-for-addon-update-types', ["new"])
|
||||
register('behavior.last-check-for-addon-updates', "1970/01/01")
|
||||
register('behavior.previously-seen-addon-updates', [])
|
||||
register('behavior.do-not-show-previously-seen-addon-updates', True)
|
||||
register('behavior.date-about-range', 50)
|
||||
register('behavior.date-after-range', 50)
|
||||
register('behavior.date-before-range', 50)
|
||||
register('behavior.generation-depth', 15)
|
||||
register('behavior.max-age-prob-alive', 110)
|
||||
register('behavior.max-sib-age-diff', 20)
|
||||
register('behavior.min-generation-years', 13)
|
||||
register('behavior.owner-warn', False)
|
||||
register('behavior.immediate-warn', False)
|
||||
register('behavior.pop-plugin-status', False)
|
||||
register('behavior.recent-export-type', 3)
|
||||
register('behavior.runcheck', False)
|
||||
register('behavior.spellcheck', False)
|
||||
register('behavior.startup', 0)
|
||||
register('behavior.surname-guessing', 0)
|
||||
register('behavior.translator-needed', True)
|
||||
register('behavior.use-tips', False)
|
||||
register('behavior.welcome', 100)
|
||||
register('behavior.web-search-url', 'http://google.com/#&q=%(text)s')
|
||||
register('behavior.addons-url', 'https://raw.githubusercontent.com/gramps-project/addons/master/gramps52')
|
||||
register('behavior.addons-projects',
|
||||
[['Gramps', 'https://raw.githubusercontent.com/gramps-project/addons/master/gramps52', True]])
|
||||
register('behavior.addons-allow-install', False)
|
||||
register("behavior.addmedia-image-dir", "")
|
||||
register("behavior.addmedia-relative-path", False)
|
||||
register("behavior.autoload", False)
|
||||
register("behavior.avg-generation-gap", 20)
|
||||
register("behavior.check-for-addon-updates", 0)
|
||||
register("behavior.check-for-addon-update-types", ["new"])
|
||||
register("behavior.last-check-for-addon-updates", "1970/01/01")
|
||||
register("behavior.previously-seen-addon-updates", [])
|
||||
register("behavior.do-not-show-previously-seen-addon-updates", True)
|
||||
register("behavior.date-about-range", 50)
|
||||
register("behavior.date-after-range", 50)
|
||||
register("behavior.date-before-range", 50)
|
||||
register("behavior.generation-depth", 15)
|
||||
register("behavior.max-age-prob-alive", 110)
|
||||
register("behavior.max-sib-age-diff", 20)
|
||||
register("behavior.min-generation-years", 13)
|
||||
register("behavior.owner-warn", False)
|
||||
register("behavior.immediate-warn", False)
|
||||
register("behavior.pop-plugin-status", False)
|
||||
register("behavior.recent-export-type", 3)
|
||||
register("behavior.runcheck", False)
|
||||
register("behavior.spellcheck", False)
|
||||
register("behavior.startup", 0)
|
||||
register("behavior.surname-guessing", 0)
|
||||
register("behavior.translator-needed", True)
|
||||
register("behavior.use-tips", False)
|
||||
register("behavior.welcome", 100)
|
||||
register("behavior.web-search-url", "http://google.com/#&q=%(text)s")
|
||||
register(
|
||||
"behavior.addons-url",
|
||||
"https://raw.githubusercontent.com/gramps-project/addons/master/gramps52",
|
||||
)
|
||||
register(
|
||||
"behavior.addons-projects",
|
||||
[
|
||||
[
|
||||
"Gramps",
|
||||
"https://raw.githubusercontent.com/gramps-project/addons/master/gramps52",
|
||||
True,
|
||||
]
|
||||
],
|
||||
)
|
||||
register("behavior.addons-allow-install", False)
|
||||
|
||||
register('csv.dialect', 'excel')
|
||||
register('csv.delimiter', ',')
|
||||
register("csv.dialect", "excel")
|
||||
register("csv.delimiter", ",")
|
||||
|
||||
register('database.backend', 'sqlite')
|
||||
register('database.compress-backup', True)
|
||||
register('database.backup-path', USER_HOME)
|
||||
register('database.backup-on-exit', True)
|
||||
register('database.autobackup', 0)
|
||||
register('database.path', os.path.join(USER_DATA, 'grampsdb'))
|
||||
register('database.host', '')
|
||||
register('database.port', '')
|
||||
register("database.backend", "sqlite")
|
||||
register("database.compress-backup", True)
|
||||
register("database.backup-path", USER_HOME)
|
||||
register("database.backup-on-exit", True)
|
||||
register("database.autobackup", 0)
|
||||
register("database.path", os.path.join(USER_DATA, "grampsdb"))
|
||||
register("database.host", "")
|
||||
register("database.port", "")
|
||||
|
||||
register('export.proxy-order',
|
||||
[["privacy", 0],
|
||||
["living", 0],
|
||||
["person", 0],
|
||||
["note", 0],
|
||||
["reference", 0]]
|
||||
register(
|
||||
"export.proxy-order",
|
||||
[["privacy", 0], ["living", 0], ["person", 0], ["note", 0], ["reference", 0]],
|
||||
)
|
||||
|
||||
register('geography.center-lon', 0.0)
|
||||
register('geography.lock', False)
|
||||
register('geography.center-lat', 0.0)
|
||||
register('geography.map_service', 1)
|
||||
register('geography.zoom', 0)
|
||||
register('geography.zoom_when_center', 12)
|
||||
register('geography.show_cross', False)
|
||||
register('geography.path', "")
|
||||
register('geography.use-keypad', True)
|
||||
register('geography.personal-map', "")
|
||||
register("geography.center-lon", 0.0)
|
||||
register("geography.lock", False)
|
||||
register("geography.center-lat", 0.0)
|
||||
register("geography.map_service", 1)
|
||||
register("geography.zoom", 0)
|
||||
register("geography.zoom_when_center", 12)
|
||||
register("geography.show_cross", False)
|
||||
register("geography.path", "")
|
||||
register("geography.use-keypad", True)
|
||||
register("geography.personal-map", "")
|
||||
|
||||
# note that other calls to "register" are done in realtime (when
|
||||
# needed), for instance to four 'interface.clipboard' variables --
|
||||
# so do a recursive grep for "setup_configs" to see all the (base) names
|
||||
register('interface.dont-ask', False)
|
||||
register('interface.view-categories',
|
||||
["Dashboard", "People", "Relationships", "Families",
|
||||
"Ancestry", "Events", "Places", "Geography", "Sources",
|
||||
"Citations", "Repositories", "Media", "Notes"])
|
||||
register('interface.filter', False)
|
||||
register('interface.fullscreen', False)
|
||||
register('interface.grampletbar-close', False)
|
||||
register('interface.ignore-gexiv2', False)
|
||||
register('interface.ignore-pil', False)
|
||||
register('interface.ignore-osmgpsmap', False)
|
||||
register('interface.main-window-height', 500)
|
||||
register('interface.main-window-horiz-position', 15)
|
||||
register('interface.main-window-vert-position', 10)
|
||||
register('interface.main-window-width', 775)
|
||||
register('interface.mapservice', 'OpenStreetMap')
|
||||
register('interface.open-with-default-viewer', False)
|
||||
register('interface.pedview-layout', 0)
|
||||
register('interface.pedview-show-images', True)
|
||||
register('interface.pedview-show-marriage', False)
|
||||
register('interface.pedview-tree-size', 5)
|
||||
register('interface.pedview-tree-direction', 2)
|
||||
register('interface.pedview-show-unknown-people', False)
|
||||
register('interface.place-name-height', 100)
|
||||
register('interface.place-name-width', 450)
|
||||
register('interface.sidebar-text', True)
|
||||
register('interface.size-checked', False)
|
||||
register('interface.statusbar', 1)
|
||||
register('interface.toolbar-on', True)
|
||||
register('interface.toolbar-text', False)
|
||||
register('interface.hide-lds', False)
|
||||
register('interface.toolbar-clipboard', True)
|
||||
register('interface.toolbar-addons', True)
|
||||
register('interface.toolbar-preference', True)
|
||||
register('interface.toolbar-reports', True)
|
||||
register('interface.toolbar-tools', True)
|
||||
register('interface.view', True)
|
||||
register('interface.surname-box-height', 150)
|
||||
register('interface.treemodel-cache-size', 1000)
|
||||
register("interface.dont-ask", False)
|
||||
register(
|
||||
"interface.view-categories",
|
||||
[
|
||||
"Dashboard",
|
||||
"People",
|
||||
"Relationships",
|
||||
"Families",
|
||||
"Ancestry",
|
||||
"Events",
|
||||
"Places",
|
||||
"Geography",
|
||||
"Sources",
|
||||
"Citations",
|
||||
"Repositories",
|
||||
"Media",
|
||||
"Notes",
|
||||
],
|
||||
)
|
||||
register("interface.filter", False)
|
||||
register("interface.fullscreen", False)
|
||||
register("interface.grampletbar-close", False)
|
||||
register("interface.ignore-gexiv2", False)
|
||||
register("interface.ignore-pil", False)
|
||||
register("interface.ignore-osmgpsmap", False)
|
||||
register("interface.main-window-height", 500)
|
||||
register("interface.main-window-horiz-position", 15)
|
||||
register("interface.main-window-vert-position", 10)
|
||||
register("interface.main-window-width", 775)
|
||||
register("interface.mapservice", "OpenStreetMap")
|
||||
register("interface.open-with-default-viewer", False)
|
||||
register("interface.pedview-layout", 0)
|
||||
register("interface.pedview-show-images", True)
|
||||
register("interface.pedview-show-marriage", False)
|
||||
register("interface.pedview-tree-size", 5)
|
||||
register("interface.pedview-tree-direction", 2)
|
||||
register("interface.pedview-show-unknown-people", False)
|
||||
register("interface.place-name-height", 100)
|
||||
register("interface.place-name-width", 450)
|
||||
register("interface.sidebar-text", True)
|
||||
register("interface.size-checked", False)
|
||||
register("interface.statusbar", 1)
|
||||
register("interface.toolbar-on", True)
|
||||
register("interface.toolbar-text", False)
|
||||
register("interface.hide-lds", False)
|
||||
register("interface.toolbar-clipboard", True)
|
||||
register("interface.toolbar-addons", True)
|
||||
register("interface.toolbar-preference", True)
|
||||
register("interface.toolbar-reports", True)
|
||||
register("interface.toolbar-tools", True)
|
||||
register("interface.view", True)
|
||||
register("interface.surname-box-height", 150)
|
||||
register("interface.treemodel-cache-size", 1000)
|
||||
|
||||
register('paths.recent-export-dir', USER_HOME)
|
||||
register('paths.recent-file', '')
|
||||
register('paths.recent-import-dir', USER_HOME)
|
||||
register('paths.report-directory', USER_HOME)
|
||||
register('paths.website-directory', USER_HOME)
|
||||
register('paths.website-cms-uri', '')
|
||||
register('paths.website-cal-uri', '')
|
||||
register('paths.website-extra-page-uri', '')
|
||||
register('paths.website-extra-page-name', '')
|
||||
register('paths.quick-backup-directory', USER_HOME)
|
||||
register('paths.quick-backup-filename',
|
||||
"%(filename)s_%(year)d-%(month)02d-%(day)02d.%(extension)s")
|
||||
register("paths.recent-export-dir", USER_HOME)
|
||||
register("paths.recent-file", "")
|
||||
register("paths.recent-import-dir", USER_HOME)
|
||||
register("paths.report-directory", USER_HOME)
|
||||
register("paths.website-directory", USER_HOME)
|
||||
register("paths.website-cms-uri", "")
|
||||
register("paths.website-cal-uri", "")
|
||||
register("paths.website-extra-page-uri", "")
|
||||
register("paths.website-extra-page-name", "")
|
||||
register("paths.quick-backup-directory", USER_HOME)
|
||||
register(
|
||||
"paths.quick-backup-filename",
|
||||
"%(filename)s_%(year)d-%(month)02d-%(day)02d.%(extension)s",
|
||||
)
|
||||
|
||||
register('preferences.quick-backup-include-mode', False)
|
||||
register('preferences.date-format', 0)
|
||||
register('preferences.calendar-format-report', 0)
|
||||
register('preferences.calendar-format-input', 0)
|
||||
register('preferences.february-29', 0) # 0: 02/28; 1: 03/01; 2: only the 02/29
|
||||
register('preferences.cprefix', 'C%04d')
|
||||
register('preferences.default-source', False)
|
||||
register('preferences.tag-on-import', False)
|
||||
register('preferences.tag-on-import-format', _("Imported %Y/%m/%d %H:%M:%S"))
|
||||
register('preferences.eprefix', 'E%04d')
|
||||
register('preferences.family-warn', True)
|
||||
register('preferences.fprefix', 'F%04d')
|
||||
register('preferences.hide-ep-msg', False)
|
||||
register('preferences.invalid-date-format', "<b>%s</b>")
|
||||
register('preferences.iprefix', 'I%04d')
|
||||
register('preferences.name-format', 1)
|
||||
register('preferences.place-format', 0)
|
||||
register('preferences.place-auto', True)
|
||||
register('preferences.coord-format', 0)
|
||||
register('preferences.patronimic-surname', False)
|
||||
register('preferences.no-given-text', "[%s]" % _("Missing Given Name"))
|
||||
register('preferences.no-record-text', "[%s]" % _("Missing Record"))
|
||||
register('preferences.no-surname-text', "[%s]" % _("Missing Surname"))
|
||||
register('preferences.nprefix', 'N%04d')
|
||||
register('preferences.online-maps', False)
|
||||
register('preferences.oprefix', 'O%04d')
|
||||
register('preferences.paper-metric', 0)
|
||||
register('preferences.paper-preference', 'Letter')
|
||||
register('preferences.pprefix', 'P%04d')
|
||||
register('preferences.private-given-text', "%s" % _T_("[Living]"))
|
||||
register('preferences.private-record-text', "[%s]" % _("Private Record"))
|
||||
register('preferences.private-surname-text', "%s" % _T_("[Living]"))
|
||||
register('preferences.rprefix', 'R%04d')
|
||||
register('preferences.sprefix', 'S%04d')
|
||||
register('preferences.use-last-view', False)
|
||||
register('preferences.last-view', '')
|
||||
register('preferences.last-views', [])
|
||||
register('preferences.family-relation-type', 3) # UNKNOWN
|
||||
register('preferences.age-display-precision', 1)
|
||||
register('preferences.age-after-death', True)
|
||||
register('preferences.cite-plugin', 'cite-default')
|
||||
register("preferences.quick-backup-include-mode", False)
|
||||
register("preferences.date-format", 0)
|
||||
register("preferences.calendar-format-report", 0)
|
||||
register("preferences.calendar-format-input", 0)
|
||||
register("preferences.february-29", 0) # 0: 02/28; 1: 03/01; 2: only the 02/29
|
||||
register("preferences.cprefix", "C%04d")
|
||||
register("preferences.default-source", False)
|
||||
register("preferences.tag-on-import", False)
|
||||
register("preferences.tag-on-import-format", _("Imported %Y/%m/%d %H:%M:%S"))
|
||||
register("preferences.eprefix", "E%04d")
|
||||
register("preferences.family-warn", True)
|
||||
register("preferences.fprefix", "F%04d")
|
||||
register("preferences.hide-ep-msg", False)
|
||||
register("preferences.invalid-date-format", "<b>%s</b>")
|
||||
register("preferences.iprefix", "I%04d")
|
||||
register("preferences.name-format", 1)
|
||||
register("preferences.place-format", 0)
|
||||
register("preferences.place-auto", True)
|
||||
register("preferences.coord-format", 0)
|
||||
register("preferences.patronimic-surname", False)
|
||||
register("preferences.no-given-text", "[%s]" % _("Missing Given Name"))
|
||||
register("preferences.no-record-text", "[%s]" % _("Missing Record"))
|
||||
register("preferences.no-surname-text", "[%s]" % _("Missing Surname"))
|
||||
register("preferences.nprefix", "N%04d")
|
||||
register("preferences.online-maps", False)
|
||||
register("preferences.oprefix", "O%04d")
|
||||
register("preferences.paper-metric", 0)
|
||||
register("preferences.paper-preference", "Letter")
|
||||
register("preferences.pprefix", "P%04d")
|
||||
register("preferences.private-given-text", "%s" % _T_("[Living]"))
|
||||
register("preferences.private-record-text", "[%s]" % _("Private Record"))
|
||||
register("preferences.private-surname-text", "%s" % _T_("[Living]"))
|
||||
register("preferences.rprefix", "R%04d")
|
||||
register("preferences.sprefix", "S%04d")
|
||||
register("preferences.use-last-view", False)
|
||||
register("preferences.last-view", "")
|
||||
register("preferences.last-views", [])
|
||||
register("preferences.family-relation-type", 3) # UNKNOWN
|
||||
register("preferences.age-display-precision", 1)
|
||||
register("preferences.age-after-death", True)
|
||||
register("preferences.cite-plugin", "cite-default")
|
||||
|
||||
register('colors.scheme', 0)
|
||||
register('colors.male-alive', ['#b8cee6', '#1f344a'])
|
||||
register('colors.male-dead', ['#b8cee6', '#2d3039'])
|
||||
register('colors.female-alive', ['#feccf0', '#62242D'])
|
||||
register('colors.female-dead', ['#feccf0', '#3a292b'])
|
||||
register('colors.other-alive', ['#94ef9e', '#285b27'])
|
||||
register('colors.other-dead', ['#94ef9e', '#062304'])
|
||||
register('colors.unknown-alive', ['#f3dbb6', '#75507B'])
|
||||
register('colors.unknown-dead', ['#f3dbb6', '#35103b'])
|
||||
register('colors.family', ['#eeeeee', '#454545'])
|
||||
register('colors.family-married', ['#eeeeee', '#454545'])
|
||||
register('colors.family-unmarried', ['#eeeeee', '#454545'])
|
||||
register('colors.family-civil-union', ['#eeeeee', '#454545'])
|
||||
register('colors.family-unknown', ['#eeeeee', '#454545'])
|
||||
register('colors.family-divorced', ['#ffdede', '#5c3636'])
|
||||
register('colors.home-person', ['#bbe68a', '#304918'])
|
||||
register('colors.border-male-alive', ['#1f4986', '#171d26'])
|
||||
register('colors.border-male-dead', ['#000000', '#000000'])
|
||||
register('colors.border-female-alive', ['#861f69', '#261111'])
|
||||
register('colors.border-female-dead', ['#000000', '#000000'])
|
||||
register('colors.border-other-alive', ['#2a5f16', '#26a269'])
|
||||
register('colors.border-other-dead', ['#000000', '#000000'])
|
||||
register('colors.border-unknown-alive', ['#8e5801', '#8e5801'])
|
||||
register('colors.border-unknown-dead', ['#000000', '#000000'])
|
||||
register('colors.border-family', ['#cccccc', '#252525'])
|
||||
register('colors.border-family-divorced', ['#ff7373', '#720b0b'])
|
||||
register("colors.scheme", 0)
|
||||
register("colors.male-alive", ["#b8cee6", "#1f344a"])
|
||||
register("colors.male-dead", ["#b8cee6", "#2d3039"])
|
||||
register("colors.female-alive", ["#feccf0", "#62242D"])
|
||||
register("colors.female-dead", ["#feccf0", "#3a292b"])
|
||||
register("colors.other-alive", ["#94ef9e", "#285b27"])
|
||||
register("colors.other-dead", ["#94ef9e", "#062304"])
|
||||
register("colors.unknown-alive", ["#f3dbb6", "#75507B"])
|
||||
register("colors.unknown-dead", ["#f3dbb6", "#35103b"])
|
||||
register("colors.family", ["#eeeeee", "#454545"])
|
||||
register("colors.family-married", ["#eeeeee", "#454545"])
|
||||
register("colors.family-unmarried", ["#eeeeee", "#454545"])
|
||||
register("colors.family-civil-union", ["#eeeeee", "#454545"])
|
||||
register("colors.family-unknown", ["#eeeeee", "#454545"])
|
||||
register("colors.family-divorced", ["#ffdede", "#5c3636"])
|
||||
register("colors.home-person", ["#bbe68a", "#304918"])
|
||||
register("colors.border-male-alive", ["#1f4986", "#171d26"])
|
||||
register("colors.border-male-dead", ["#000000", "#000000"])
|
||||
register("colors.border-female-alive", ["#861f69", "#261111"])
|
||||
register("colors.border-female-dead", ["#000000", "#000000"])
|
||||
register("colors.border-other-alive", ["#2a5f16", "#26a269"])
|
||||
register("colors.border-other-dead", ["#000000", "#000000"])
|
||||
register("colors.border-unknown-alive", ["#8e5801", "#8e5801"])
|
||||
register("colors.border-unknown-dead", ["#000000", "#000000"])
|
||||
register("colors.border-family", ["#cccccc", "#252525"])
|
||||
register("colors.border-family-divorced", ["#ff7373", "#720b0b"])
|
||||
|
||||
register('researcher.researcher-addr', '')
|
||||
register('researcher.researcher-locality', '')
|
||||
register('researcher.researcher-city', '')
|
||||
register('researcher.researcher-country', '')
|
||||
register('researcher.researcher-email', '')
|
||||
register('researcher.researcher-name', '')
|
||||
register('researcher.researcher-phone', '')
|
||||
register('researcher.researcher-postal', '')
|
||||
register('researcher.researcher-state', '')
|
||||
register("researcher.researcher-addr", "")
|
||||
register("researcher.researcher-locality", "")
|
||||
register("researcher.researcher-city", "")
|
||||
register("researcher.researcher-country", "")
|
||||
register("researcher.researcher-email", "")
|
||||
register("researcher.researcher-name", "")
|
||||
register("researcher.researcher-phone", "")
|
||||
register("researcher.researcher-postal", "")
|
||||
register("researcher.researcher-state", "")
|
||||
|
||||
register('plugin.hiddenplugins', [])
|
||||
register('plugin.addonplugins', [])
|
||||
register("plugin.hiddenplugins", [])
|
||||
register("plugin.addonplugins", [])
|
||||
|
||||
register('utf8.in-use', False)
|
||||
register('utf8.selected-font', '')
|
||||
register('utf8.death-symbol', 2)
|
||||
register('utf8.birth-symbol', "*")
|
||||
register('utf8.baptism-symbol', "~")
|
||||
register('utf8.marriage-symbol', "oo")
|
||||
register('utf8.engaged-symbol', "o")
|
||||
register('utf8.divorce-symbol', "o|o")
|
||||
register('utf8.partner-symbol', "o-o")
|
||||
register('utf8.dead-symbol', "✝")
|
||||
register('utf8.buried-symbol', "[]")
|
||||
register('utf8.cremated-symbol', "⚱")
|
||||
register('utf8.killed-symbol', "x")
|
||||
register("utf8.in-use", False)
|
||||
register("utf8.selected-font", "")
|
||||
register("utf8.death-symbol", 2)
|
||||
register("utf8.birth-symbol", "*")
|
||||
register("utf8.baptism-symbol", "~")
|
||||
register("utf8.marriage-symbol", "oo")
|
||||
register("utf8.engaged-symbol", "o")
|
||||
register("utf8.divorce-symbol", "o|o")
|
||||
register("utf8.partner-symbol", "o-o")
|
||||
register("utf8.dead-symbol", "✝")
|
||||
register("utf8.buried-symbol", "[]")
|
||||
register("utf8.cremated-symbol", "⚱")
|
||||
register("utf8.killed-symbol", "x")
|
||||
|
||||
if __debug__: # enable a simple CLI test to see if the datestrings exist
|
||||
register('test.january', _("January", "localized lexeme inflections"))
|
||||
register("test.january", _("January", "localized lexeme inflections"))
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
#
|
||||
@@ -361,14 +403,13 @@ if not os.path.exists(CONFIGMAN.filename):
|
||||
if os.path.exists(os.path.join(USER_CONFIG, "keys.ini")):
|
||||
# read it in old style:
|
||||
logging.warning("Importing old key file 'keys.ini'...")
|
||||
CONFIGMAN.load(os.path.join(USER_CONFIG, "keys.ini"),
|
||||
oldstyle=True)
|
||||
CONFIGMAN.load(os.path.join(USER_CONFIG, "keys.ini"), oldstyle=True)
|
||||
logging.warning("Done importing old key file 'keys.ini'")
|
||||
# other version upgrades here...
|
||||
# check previous version of gramps:
|
||||
fullpath, filename = os.path.split(CONFIGMAN.filename)
|
||||
fullpath, previous = os.path.split(fullpath)
|
||||
match = re.match(r'gramps(\d*)', previous)
|
||||
match = re.match(r"gramps(\d*)", previous)
|
||||
if match:
|
||||
# cycle back looking for previous versions of gramps
|
||||
for i in range(1, 20): # check back 2 gramps versions
|
||||
@@ -380,14 +421,13 @@ if not os.path.exists(CONFIGMAN.filename):
|
||||
# Perhaps addings specific list of versions to check
|
||||
# -----------------------------------------
|
||||
digits = str(int(match.groups()[0]) - i)
|
||||
previous_grampsini = os.path.join(fullpath, "gramps" + digits,
|
||||
filename)
|
||||
previous_grampsini = os.path.join(fullpath, "gramps" + digits, filename)
|
||||
if os.path.exists(previous_grampsini):
|
||||
logging.warning("Importing old config file '%s'...",
|
||||
previous_grampsini)
|
||||
logging.warning("Importing old config file '%s'...", previous_grampsini)
|
||||
CONFIGMAN.load(previous_grampsini)
|
||||
logging.warning("Done importing old config file '%s'",
|
||||
previous_grampsini)
|
||||
logging.warning(
|
||||
"Done importing old config file '%s'", previous_grampsini
|
||||
)
|
||||
break
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
@@ -398,5 +438,5 @@ if not os.path.exists(CONFIGMAN.filename):
|
||||
CONFIGMAN.load()
|
||||
|
||||
config = CONFIGMAN
|
||||
if config.get('database.backend') == 'bsddb':
|
||||
config.set('database.backend', 'sqlite')
|
||||
if config.get("database.backend") == "bsddb":
|
||||
config.set("database.backend", "sqlite")
|
||||
|
@@ -65,10 +65,10 @@ URL_BUGHOME = "http://gramps-project.org/bugs"
|
||||
URL_BUGTRACKER = "http://gramps-project.org/bugs/bug_report_page.php"
|
||||
URL_WIKISTRING = "http://gramps-project.org/wiki/index.php?title="
|
||||
URL_MANUAL_PAGE = "Gramps_%s_Wiki_Manual" % major_version
|
||||
URL_MANUAL_DATA = '%s_-_Entering_and_editing_data:_detailed' % URL_MANUAL_PAGE
|
||||
URL_MANUAL_SECT1 = '%s_-_part_1' % URL_MANUAL_DATA
|
||||
URL_MANUAL_SECT2 = '%s_-_part_2' % URL_MANUAL_DATA
|
||||
URL_MANUAL_SECT3 = '%s_-_part_3' % URL_MANUAL_DATA
|
||||
URL_MANUAL_DATA = "%s_-_Entering_and_editing_data:_detailed" % URL_MANUAL_PAGE
|
||||
URL_MANUAL_SECT1 = "%s_-_part_1" % URL_MANUAL_DATA
|
||||
URL_MANUAL_SECT2 = "%s_-_part_2" % URL_MANUAL_DATA
|
||||
URL_MANUAL_SECT3 = "%s_-_part_3" % URL_MANUAL_DATA
|
||||
WIKI_FAQ = "FAQ"
|
||||
WIKI_KEYBINDINGS = "Gramps_%s_Wiki_Manual_-_Keybindings" % major_version
|
||||
WIKI_EXTRAPLUGINS = "%s_Addons" % major_version
|
||||
@@ -79,7 +79,7 @@ WIKI_EXTRAPLUGINS_RAWDATA = "Plugins%s&action=raw" % major_version
|
||||
# Mime Types
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
APP_FAMTREE = 'x-directory/normal'
|
||||
APP_FAMTREE = "x-directory/normal"
|
||||
APP_GRAMPS = "application/x-gramps"
|
||||
APP_GRAMPS_XML = "application/x-gramps-xml"
|
||||
APP_GEDCOM = "application/x-gedcom"
|
||||
@@ -94,36 +94,35 @@ APP_VCARD = ["text/x-vcard", "text/x-vcalendar"]
|
||||
# Windows apparently uses USERPROFILE
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
if 'GRAMPSHOME' in os.environ:
|
||||
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')
|
||||
if 'APPDATA' in os.environ:
|
||||
HOME_DIR = os.path.join(get_env_var('APPDATA'), 'gramps')
|
||||
if "GRAMPSHOME" in os.environ:
|
||||
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")
|
||||
if "APPDATA" in os.environ:
|
||||
HOME_DIR = os.path.join(get_env_var("APPDATA"), "gramps")
|
||||
else:
|
||||
HOME_DIR = os.path.join(USER_HOME, 'gramps')
|
||||
HOME_DIR = os.path.join(USER_HOME, "gramps")
|
||||
else:
|
||||
USER_HOME = get_env_var('HOME')
|
||||
HOME_DIR = os.path.join(USER_HOME, '.gramps')
|
||||
USER_HOME = get_env_var("HOME")
|
||||
HOME_DIR = os.path.join(USER_HOME, ".gramps")
|
||||
ORIG_HOME_DIR = HOME_DIR
|
||||
if 'SAFEMODE' in os.environ:
|
||||
if 'USERPROFILE' in os.environ:
|
||||
USER_HOME = get_env_var('USERPROFILE')
|
||||
if "SAFEMODE" in os.environ:
|
||||
if "USERPROFILE" in os.environ:
|
||||
USER_HOME = get_env_var("USERPROFILE")
|
||||
else:
|
||||
USER_HOME = get_env_var('HOME')
|
||||
HOME_DIR = get_env_var('SAFEMODE')
|
||||
USER_HOME = get_env_var("HOME")
|
||||
HOME_DIR = get_env_var("SAFEMODE")
|
||||
|
||||
|
||||
if (os.path.exists(HOME_DIR) or 'GRAMPSHOME' in os.environ
|
||||
or 'SAFEMODE' in os.environ):
|
||||
if os.path.exists(HOME_DIR) or "GRAMPSHOME" in os.environ or "SAFEMODE" in os.environ:
|
||||
USER_DATA = HOME_DIR
|
||||
USER_CONFIG = HOME_DIR
|
||||
USER_CACHE = HOME_DIR
|
||||
else:
|
||||
USER_DATA = os.path.join(GLib.get_user_data_dir(), 'gramps')
|
||||
USER_CONFIG = os.path.join(GLib.get_user_config_dir(), 'gramps')
|
||||
USER_CACHE = os.path.join(GLib.get_user_cache_dir(), 'gramps')
|
||||
USER_DATA = os.path.join(GLib.get_user_data_dir(), "gramps")
|
||||
USER_CONFIG = os.path.join(GLib.get_user_config_dir(), "gramps")
|
||||
USER_CACHE = os.path.join(GLib.get_user_cache_dir(), "gramps")
|
||||
|
||||
USER_PICTURES = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES)
|
||||
if not USER_PICTURES:
|
||||
@@ -144,9 +143,19 @@ THUMB_LARGE = os.path.join(THUMB_DIR, "large")
|
||||
USER_PLUGINS = os.path.join(USER_DATA_VERSION, "plugins")
|
||||
USER_CSS = os.path.join(USER_DATA, "css")
|
||||
# dirs checked/made for each Gramps session
|
||||
USER_DIRLIST = (USER_HOME, USER_CACHE, USER_CONFIG, USER_DATA, VERSION_DIR,
|
||||
USER_DATA_VERSION, THUMB_DIR, THUMB_NORMAL, THUMB_LARGE,
|
||||
USER_PLUGINS, USER_CSS)
|
||||
USER_DIRLIST = (
|
||||
USER_HOME,
|
||||
USER_CACHE,
|
||||
USER_CONFIG,
|
||||
USER_DATA,
|
||||
VERSION_DIR,
|
||||
USER_DATA_VERSION,
|
||||
THUMB_DIR,
|
||||
THUMB_NORMAL,
|
||||
THUMB_LARGE,
|
||||
USER_PLUGINS,
|
||||
USER_CSS,
|
||||
)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -158,8 +167,8 @@ USER_DIRLIST = (USER_HOME, USER_CACHE, USER_CONFIG, USER_DATA, VERSION_DIR,
|
||||
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
|
||||
|
||||
sys.path.insert(0, ROOT_DIR)
|
||||
git_revision = get_git_revision(ROOT_DIR).replace('\n', '')
|
||||
if sys.platform == 'win32' and git_revision == "":
|
||||
git_revision = get_git_revision(ROOT_DIR).replace("\n", "")
|
||||
if sys.platform == "win32" and git_revision == "":
|
||||
git_revision = get_git_revision(os.path.split(ROOT_DIR)[1])
|
||||
if DEV_VERSION:
|
||||
VERSION += git_revision
|
||||
@@ -196,7 +205,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(_resources.doc_dir, 'COPYING')
|
||||
LICENSE_FILE = os.path.join(_resources.doc_dir, "COPYING")
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
@@ -230,18 +239,19 @@ ENV = {
|
||||
# -------------------------------------------------------------------------
|
||||
GRAMPS_LOCALE = GrampsLocale(localedir=_resources.locale_dir)
|
||||
_ = GRAMPS_LOCALE.translation.sgettext
|
||||
GTK_GETTEXT_DOMAIN = 'gtk30'
|
||||
GTK_GETTEXT_DOMAIN = "gtk30"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# About box information
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
COPYRIGHT_MSG = "© 2001-2006 Donald N. Allingham\n" \
|
||||
"© 2007-2022 The Gramps Developers"
|
||||
COMMENTS = _("Gramps\n (Genealogical Research and Analysis "
|
||||
COPYRIGHT_MSG = "© 2001-2006 Donald N. Allingham\n" "© 2007-2022 The Gramps Developers"
|
||||
COMMENTS = _(
|
||||
"Gramps\n (Genealogical Research and Analysis "
|
||||
"Management Programming System)\n"
|
||||
"is a personal genealogy program.")
|
||||
"is a personal genealogy program."
|
||||
)
|
||||
AUTHORS = [
|
||||
"Alexander Roitman",
|
||||
"Benny Malengier",
|
||||
@@ -252,13 +262,13 @@ AUTHORS = [
|
||||
"Martin Hawlisch",
|
||||
"Richard Taylor",
|
||||
"Tim Waugh",
|
||||
"John Ralls"
|
||||
"John Ralls",
|
||||
]
|
||||
|
||||
AUTHORS_FILE = os.path.join(DATA_DIR, "authors.xml")
|
||||
|
||||
DOCUMENTERS = [
|
||||
'Alexander Roitman',
|
||||
"Alexander Roitman",
|
||||
]
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -275,8 +285,8 @@ NO_SURNAME = "(%s)" % _("none", "surname")
|
||||
NO_GIVEN = "(%s)" % _("none", "given-name")
|
||||
ARABIC_COMMA = "،"
|
||||
ARABIC_SEMICOLON = "؛"
|
||||
DOCGEN_OPTIONS = 'Docgen Options'
|
||||
COLON = _(':') # Translators: needed for French, ignore otherwise
|
||||
DOCGEN_OPTIONS = "Docgen Options"
|
||||
COLON = _(":") # Translators: needed for French, ignore otherwise
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
@@ -307,8 +317,7 @@ LONGOPTS = [
|
||||
"help",
|
||||
"import=",
|
||||
"load-modules=",
|
||||
"list"
|
||||
"name=",
|
||||
"list" "name=",
|
||||
"oaf-activate-iid=",
|
||||
"oaf-ior-fd=",
|
||||
"oaf-private",
|
||||
@@ -333,7 +342,7 @@ LONGOPTS = [
|
||||
|
||||
SHORTOPTS = "O:U:P:C:i:e:f:a:p:d:c:r:lLthuv?syqSD:"
|
||||
|
||||
GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')
|
||||
GRAMPS_UUID = uuid.UUID("516cd010-5a41-470f-99f8-eb22f1098ad6")
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
@@ -357,7 +366,8 @@ BACKGROUND_GRAD_AGE = 5
|
||||
BACKGROUND_SINGLE_COLOR = 6
|
||||
BACKGROUND_GRAD_PERIOD = 7
|
||||
GENCOLOR = {
|
||||
BACKGROUND_SCHEME1: ((255, 63, 0),
|
||||
BACKGROUND_SCHEME1: (
|
||||
(255, 63, 0),
|
||||
(255, 175, 15),
|
||||
(255, 223, 87),
|
||||
(255, 255, 111),
|
||||
@@ -367,14 +377,19 @@ GENCOLOR = {
|
||||
(231, 23, 255),
|
||||
(231, 23, 121),
|
||||
(210, 170, 124),
|
||||
(189, 153, 112)),
|
||||
BACKGROUND_SCHEME2: ((229, 191, 252),
|
||||
(189, 153, 112),
|
||||
),
|
||||
BACKGROUND_SCHEME2: (
|
||||
(229, 191, 252),
|
||||
(191, 191, 252),
|
||||
(191, 222, 252),
|
||||
(183, 219, 197),
|
||||
(206, 246, 209)),
|
||||
BACKGROUND_WHITE: ((255, 255, 255),
|
||||
(255, 255, 255),),
|
||||
(206, 246, 209),
|
||||
),
|
||||
BACKGROUND_WHITE: (
|
||||
(255, 255, 255),
|
||||
(255, 255, 255),
|
||||
),
|
||||
}
|
||||
|
||||
MAX_AGE = 100
|
||||
|
@@ -50,6 +50,7 @@ WINDOWS = ["Windows", "win32"]
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
def lin():
|
||||
"""
|
||||
Return True if a linux system
|
||||
@@ -59,6 +60,7 @@ def lin():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def mac():
|
||||
"""
|
||||
Return True if a Macintosh system
|
||||
@@ -67,6 +69,7 @@ def mac():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def win():
|
||||
"""
|
||||
Return True if a windows system
|
||||
@@ -75,10 +78,12 @@ def win():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
## The following functions do import gtk, but only when called. They
|
||||
## should only be called after translation system has been
|
||||
## initialized!
|
||||
|
||||
|
||||
def is_quartz():
|
||||
"""
|
||||
Tests to see if Python is currently running with gtk and
|
||||
@@ -87,8 +92,9 @@ def is_quartz():
|
||||
if mac():
|
||||
try:
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version("Gdk", "3.0")
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
except ImportError:
|
||||
@@ -96,6 +102,7 @@ def is_quartz():
|
||||
return Gdk.Display.get_default().__class__.__name__.endswith("QuartzDisplay")
|
||||
return False
|
||||
|
||||
|
||||
def has_display():
|
||||
"""
|
||||
Tests to see if Python is currently running with gtk
|
||||
@@ -105,27 +112,29 @@ def has_display():
|
||||
temp, sys.argv = sys.argv, sys.argv[:1]
|
||||
try:
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version("Gdk", "3.0")
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
except ImportError:
|
||||
return False
|
||||
|
||||
try:
|
||||
test = Gtk.init_check(temp) and \
|
||||
Gdk.Display.get_default()
|
||||
test = Gtk.init_check(temp) and Gdk.Display.get_default()
|
||||
sys.argv = temp
|
||||
return bool(test)
|
||||
except:
|
||||
sys.argv = temp
|
||||
return False
|
||||
|
||||
|
||||
# A couple of places add menu accelerators using <alt>, which doesn't
|
||||
# work with Gtk-quartz. <Meta> is the usually correct replacement, but
|
||||
# in one case the key is a number, and <meta>number is used by Spaces
|
||||
# (a mac feature), so we'll use control instead.
|
||||
|
||||
|
||||
def mod_key():
|
||||
"""
|
||||
Returns a string to pass to an accelerator map.
|
||||
@@ -136,6 +145,7 @@ def mod_key():
|
||||
|
||||
return "<alt>"
|
||||
|
||||
|
||||
# Python2 on Windows munges environemnt variables to match the system
|
||||
# code page. This breaks all manner of things and the workaround
|
||||
# though a bit ugly, is encapsulated here. Use this to retrieve
|
||||
@@ -146,21 +156,22 @@ def mod_key():
|
||||
|
||||
|
||||
def get_env_var(name, default=None):
|
||||
'''
|
||||
"""
|
||||
Python2 on Windows can't directly read unicode values from
|
||||
environment variables. This routine does so using the native C
|
||||
wide-character function.
|
||||
'''
|
||||
"""
|
||||
if not name or name not in os.environ:
|
||||
return default
|
||||
|
||||
return os.environ[name]
|
||||
|
||||
|
||||
def get_curr_dir():
|
||||
'''
|
||||
"""
|
||||
In Python2 on Windows, os.getcwd() returns a string encoded with
|
||||
the current code page, which may not be able to correctly handle
|
||||
an arbitrary unicode character in a path. This function uses the
|
||||
native GetCurrentDirectory function to return a unicode cwd.
|
||||
'''
|
||||
"""
|
||||
return os.getcwd()
|
||||
|
@@ -37,10 +37,17 @@ import logging
|
||||
# -------------------------------------------------------------------------
|
||||
from ..utils.grampslocale import GrampsLocale
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
# import prerequisites for localized handlers
|
||||
from ._datehandler import (LANG, LANG_SHORT, LANG_TO_PARSER, LANG_TO_DISPLAY,
|
||||
locale_tformat, main_locale)
|
||||
from ._datehandler import (
|
||||
LANG,
|
||||
LANG_SHORT,
|
||||
LANG_TO_PARSER,
|
||||
LANG_TO_DISPLAY,
|
||||
locale_tformat,
|
||||
main_locale,
|
||||
)
|
||||
from . import _datestrings
|
||||
|
||||
# Import all the localized handlers
|
||||
@@ -84,14 +91,14 @@ try:
|
||||
else:
|
||||
parser = LANG_TO_PARSER[LANG_SHORT](plocale=dlocale)
|
||||
except:
|
||||
logging.warning(
|
||||
_("Date parser for '%s' not available, using default") % LANG)
|
||||
logging.warning(_("Date parser for '%s' not available, using default") % LANG)
|
||||
parser = LANG_TO_PARSER["C"](plocale=dlocale)
|
||||
|
||||
# Initialize global displayer
|
||||
try:
|
||||
from ..config import config
|
||||
val = config.get('preferences.date-format')
|
||||
|
||||
val = config.get("preferences.date-format")
|
||||
except:
|
||||
val = 0
|
||||
|
||||
@@ -101,8 +108,7 @@ try:
|
||||
else:
|
||||
displayer = LANG_TO_DISPLAY[LANG_SHORT](val, blocale=dlocale)
|
||||
except:
|
||||
logging.warning(
|
||||
_("Date displayer for '%s' not available, using default") % LANG)
|
||||
logging.warning(_("Date displayer for '%s' not available, using default") % LANG)
|
||||
displayer = LANG_TO_DISPLAY["C"](val, blocale=dlocale)
|
||||
|
||||
|
||||
@@ -112,17 +118,23 @@ from ._dateutils import *
|
||||
# set GRAMPS_RESOURCES then: python3 -m gramps.gen.datehandler.__init__
|
||||
if __name__ == "__main__":
|
||||
from ._datedisplay import DateDisplay
|
||||
|
||||
m = 0
|
||||
date_handlers = sorted(LANG_TO_DISPLAY.items())
|
||||
for l, d in date_handlers:
|
||||
if len(l) != 2 and l not in ('zh_TW'): # Chinese has two date_handlers
|
||||
if len(l) != 2 and l not in ("zh_TW"): # Chinese has two date_handlers
|
||||
continue
|
||||
if l.upper() == l and (l.lower(), d) in date_handlers:
|
||||
continue # don't need to see the upper-case variant also
|
||||
m = max(m, len(d.formats))
|
||||
print("{}: {} {} own-f:{} own-dc:{} own-dg:{}".format(
|
||||
l, len(d.formats), d.formats,
|
||||
print(
|
||||
"{}: {} {} own-f:{} own-dc:{} own-dg:{}".format(
|
||||
l,
|
||||
len(d.formats),
|
||||
d.formats,
|
||||
d.formats != DateDisplay.formats,
|
||||
d._display_calendar != DateDisplay._display_calendar,
|
||||
d._display_gregorian != DateDisplay._display_gregorian))
|
||||
d._display_gregorian != DateDisplay._display_gregorian,
|
||||
)
|
||||
)
|
||||
print("MAX: ", m)
|
||||
|
@@ -41,6 +41,7 @@ from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
from ..const import ARABIC_COMMA
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Arabic parser class
|
||||
|
@@ -40,13 +40,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Bulgarian parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserBG(DateParser):
|
||||
|
||||
modifier_to_int = {
|
||||
"преди": Date.MOD_BEFORE,
|
||||
"пр.": Date.MOD_BEFORE,
|
||||
|
@@ -42,13 +42,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Catalan parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserCA(DateParser):
|
||||
|
||||
modifier_to_int = {
|
||||
"abans de": Date.MOD_BEFORE,
|
||||
"abans": Date.MOD_BEFORE,
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Czech parser
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Danish parser class
|
||||
|
@@ -40,13 +40,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# German parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserDE(DateParser):
|
||||
|
||||
month_to_int = DateParser.month_to_int
|
||||
# Always add german and austrian name variants no matter what the current
|
||||
# locale is
|
||||
|
@@ -41,6 +41,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Greek parser class
|
||||
|
@@ -40,13 +40,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Spanish parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserES(DateParser):
|
||||
|
||||
modifier_to_int = {
|
||||
"antes de": Date.MOD_BEFORE,
|
||||
"antes": Date.MOD_BEFORE,
|
||||
@@ -123,14 +123,30 @@ class DateDisplayES(DateDisplay):
|
||||
Spanish language date display class.
|
||||
"""
|
||||
|
||||
short_months = ( "", "ene", "feb", "mar", "abr", "may",
|
||||
"jun", "jul", "ago", "sep", "oct", "nov",
|
||||
"dic" )
|
||||
short_months = (
|
||||
"",
|
||||
"ene",
|
||||
"feb",
|
||||
"mar",
|
||||
"abr",
|
||||
"may",
|
||||
"jun",
|
||||
"jul",
|
||||
"ago",
|
||||
"sep",
|
||||
"oct",
|
||||
"nov",
|
||||
"dic",
|
||||
)
|
||||
|
||||
calendar = (
|
||||
"", "Juliano", "Hebreo",
|
||||
"Revolucionario francés", "Persa", "Islámico",
|
||||
"Sueco"
|
||||
"",
|
||||
"Juliano",
|
||||
"Hebreo",
|
||||
"Revolucionario francés",
|
||||
"Persa",
|
||||
"Islámico",
|
||||
"Sueco",
|
||||
)
|
||||
|
||||
_mod_str = ("", "antes de ", "después de ", "hacia ", "", "", "")
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Finnish parser
|
||||
@@ -49,7 +50,6 @@ from ._datehandler import register_datehandler
|
||||
# - Parsing Finnish is much more complicated than English
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserFI(DateParser):
|
||||
|
||||
# NOTE: these need to be in lower case because the "key" comparison
|
||||
# is done as lower case. In the display method correct capitalization
|
||||
# can be used.
|
||||
|
@@ -44,6 +44,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# French parser
|
||||
@@ -281,12 +282,10 @@ class DateDisplayFR(DateDisplay):
|
||||
# this must agree with its locale-specific "formats" definition
|
||||
year = self._slash_year(date_val[2], date_val[3])
|
||||
if self.format == 0:
|
||||
|
||||
# ISO
|
||||
|
||||
return self.display_iso(date_val)
|
||||
elif self.format == 1:
|
||||
|
||||
# numerical
|
||||
|
||||
if date_val[2] < 0 or date_val[3]:
|
||||
@@ -304,7 +303,6 @@ class DateDisplayFR(DateDisplay):
|
||||
|
||||
value = value.replace("%Y", str(date_val[2]))
|
||||
elif self.format == 2:
|
||||
|
||||
# day month_name year
|
||||
|
||||
if date_val[0] == 0:
|
||||
@@ -313,10 +311,8 @@ class DateDisplayFR(DateDisplay):
|
||||
else:
|
||||
value = "%s %s" % (self.long_months[date_val[1]], year)
|
||||
else:
|
||||
|
||||
value = "%d %s %s" % (date_val[0], self.long_months[date_val[1]], year)
|
||||
elif self.format == 3:
|
||||
|
||||
# day month_abbreviation year
|
||||
|
||||
if date_val[0] == 0:
|
||||
@@ -325,10 +321,8 @@ class DateDisplayFR(DateDisplay):
|
||||
else:
|
||||
value = "%s %s" % (self.short_months[date_val[1]], year)
|
||||
else:
|
||||
|
||||
value = "%d %s %s" % (date_val[0], self.short_months[date_val[1]], year)
|
||||
elif self.format == 4:
|
||||
|
||||
# day. month_name year
|
||||
|
||||
if date_val[0] == 0:
|
||||
@@ -337,14 +331,12 @@ class DateDisplayFR(DateDisplay):
|
||||
else:
|
||||
value = "%s %s" % (self.long_months[date_val[1]], year)
|
||||
else:
|
||||
|
||||
# base_display :
|
||||
# value = "%d %s %s" % (date_val[0],
|
||||
# self.long_months[date_val[1]], year)
|
||||
|
||||
value = "%d. %s %s" % (date_val[0], self.long_months[date_val[1]], year)
|
||||
elif self.format == 5:
|
||||
|
||||
# day. month_abbreviation year
|
||||
|
||||
if date_val[0] == 0:
|
||||
@@ -353,7 +345,6 @@ class DateDisplayFR(DateDisplay):
|
||||
else:
|
||||
value = "%s %s" % (self.short_months[date_val[1]], year)
|
||||
else:
|
||||
|
||||
# base_display :
|
||||
# value = "%d %s %s" % (date_val[0],
|
||||
# self.short_months[date_val[1]], year)
|
||||
@@ -364,7 +355,6 @@ class DateDisplayFR(DateDisplay):
|
||||
year,
|
||||
)
|
||||
elif self.format == 6:
|
||||
|
||||
# month_name day, year
|
||||
|
||||
if date_val[0] == 0:
|
||||
@@ -375,7 +365,6 @@ class DateDisplayFR(DateDisplay):
|
||||
else:
|
||||
value = "%s %d, %s" % (self.long_months[date_val[1]], date_val[0], year)
|
||||
elif self.format == 7:
|
||||
|
||||
# month_abbreviation day, year
|
||||
|
||||
if date_val[0] == 0:
|
||||
@@ -390,7 +379,6 @@ class DateDisplayFR(DateDisplay):
|
||||
year,
|
||||
)
|
||||
elif self.format == 8:
|
||||
|
||||
# French numerical with 0
|
||||
|
||||
if date_val[2] < 0 or date_val[3]:
|
||||
@@ -399,9 +387,9 @@ class DateDisplayFR(DateDisplay):
|
||||
if date_val[0] == date_val[1] == 0:
|
||||
value = str(date_val[2])
|
||||
else:
|
||||
value = self.dhformat.replace('%m', str(date_val[1]).zfill(2))
|
||||
value = value.replace('%d', str(date_val[0]).zfill(2))
|
||||
value = value.replace('%Y', str(date_val[2]))
|
||||
value = self.dhformat.replace("%m", str(date_val[1]).zfill(2))
|
||||
value = value.replace("%d", str(date_val[0]).zfill(2))
|
||||
value = value.replace("%Y", str(date_val[2]))
|
||||
else:
|
||||
return self.display_iso(date_val)
|
||||
|
||||
|
@@ -45,6 +45,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Croatian parser
|
||||
|
@@ -41,6 +41,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Hungarian parser
|
||||
@@ -48,7 +49,6 @@ from ._datehandler import register_datehandler
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserHU(DateParser):
|
||||
|
||||
month_to_int = DateParser.month_to_int
|
||||
|
||||
month_to_int["-"] = 0 # to make the Zero month to work
|
||||
|
@@ -42,6 +42,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Icelandic parser class
|
||||
|
@@ -42,13 +42,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Italian parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserIT(DateParser):
|
||||
|
||||
modifier_to_int = {
|
||||
"prima del": Date.MOD_BEFORE,
|
||||
"prima": Date.MOD_BEFORE,
|
||||
|
@@ -43,6 +43,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Japanese parser
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Lithuanian parser
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Norwegian parser class
|
||||
|
@@ -46,13 +46,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Dutch parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserNL(DateParser):
|
||||
|
||||
month_to_int = DateParser.month_to_int
|
||||
# Always add dutch and flemish name variants
|
||||
# no matter what the current locale is
|
||||
|
@@ -43,13 +43,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Polish parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserPL(DateParser):
|
||||
|
||||
month_to_int = DateParser.month_to_int
|
||||
month_to_int["styczeń"] = 1
|
||||
month_to_int["sty"] = 1
|
||||
|
@@ -42,13 +42,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Portuguese parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserPT(DateParser):
|
||||
|
||||
modifier_to_int = {
|
||||
"antes de": Date.MOD_BEFORE,
|
||||
"antes": Date.MOD_BEFORE,
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Russian parser
|
||||
|
@@ -40,13 +40,13 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Slovak parser
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DateParserSK(DateParser):
|
||||
|
||||
modifier_to_int = {
|
||||
"pred": Date.MOD_BEFORE,
|
||||
"do": Date.MOD_BEFORE,
|
||||
|
@@ -42,6 +42,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Slovenian parser
|
||||
|
@@ -43,6 +43,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Serbian parser
|
||||
|
@@ -40,6 +40,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Swedish parser class
|
||||
|
@@ -42,6 +42,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Ukrainian parser
|
||||
|
@@ -42,6 +42,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Simplified-Chinese parser
|
||||
|
@@ -42,6 +42,7 @@ from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Traditional-Chinese parser
|
||||
|
@@ -52,6 +52,7 @@ from ..const import GRAMPS_LOCALE as glocale
|
||||
from ..utils.grampslocale import GrampsLocale
|
||||
from ._datestrings import DateStrings
|
||||
|
||||
|
||||
# _T_ is a gramps-defined keyword -- see po/update_po.py and po/genpot.sh
|
||||
def _T_(value, context=""): # enable deferred translations
|
||||
return "%s\x04%s" % (context, value) if context else value
|
||||
|
@@ -36,6 +36,7 @@ import os
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(".gen.datehandler")
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -66,7 +67,7 @@ if not LANG:
|
||||
LANG = os.environ["LANG"]
|
||||
|
||||
if LANG:
|
||||
LANG_SHORT = LANG.split('_')[0]
|
||||
LANG_SHORT = LANG.split("_")[0]
|
||||
else:
|
||||
LANG_SHORT = "C"
|
||||
|
||||
@@ -74,12 +75,12 @@ LANG = str(LANG)
|
||||
LANG_SHORT = str(LANG_SHORT)
|
||||
|
||||
LANG_TO_PARSER = {
|
||||
'C' : DateParser,
|
||||
"C": DateParser,
|
||||
}
|
||||
|
||||
LANG_TO_DISPLAY = {
|
||||
'C' : DateDisplayEn,
|
||||
'ko_KR' : DateDisplay,
|
||||
"C": DateDisplayEn,
|
||||
"ko_KR": DateDisplay,
|
||||
}
|
||||
|
||||
main_locale = {} # this will be augmented by calls to register_datehandler
|
||||
@@ -87,25 +88,27 @@ main_locale = { } # this will be augmented by calls to register_datehandler
|
||||
locale_tformat = {} # locale "tformat" (date format) strings
|
||||
|
||||
for no_handler in (
|
||||
('C', ('%d/%m/%Y',)),
|
||||
('eo_EO', 'eo', 'Esperanto', ('%d/%m/%Y',)), # 'eo_EO' is a placeholder
|
||||
('he_IL', 'he', 'Hebrew', ('%d/%m/%Y',)),
|
||||
('sq_AL', 'sq', 'Albanian', ('%Y/%b/%d',)),
|
||||
('ta_IN', 'ta', 'Tamil', ('%A %d %B %Y',)),
|
||||
('tr_TR', 'tr', 'Turkish', ('%d/%m/%Y',)),
|
||||
('vi_VN', 'vi', 'Vietnamese', ('%d/%m/%Y',)),
|
||||
("C", ("%d/%m/%Y",)),
|
||||
("eo_EO", "eo", "Esperanto", ("%d/%m/%Y",)), # 'eo_EO' is a placeholder
|
||||
("he_IL", "he", "Hebrew", ("%d/%m/%Y",)),
|
||||
("sq_AL", "sq", "Albanian", ("%Y/%b/%d",)),
|
||||
("ta_IN", "ta", "Tamil", ("%A %d %B %Y",)),
|
||||
("tr_TR", "tr", "Turkish", ("%d/%m/%Y",)),
|
||||
("vi_VN", "vi", "Vietnamese", ("%d/%m/%Y",)),
|
||||
):
|
||||
format_string = ''
|
||||
format_string = ""
|
||||
for possible_format in no_handler:
|
||||
if isinstance(possible_format, tuple):
|
||||
format_string = possible_format[0] # pre-seeded date format string
|
||||
# maintain legacy gramps transformations
|
||||
format_string = format_string.replace('%y','%Y').replace('-', '/')
|
||||
format_string = format_string.replace("%y", "%Y").replace("-", "/")
|
||||
for lang_str in no_handler:
|
||||
if isinstance(lang_str, tuple): continue
|
||||
if isinstance(lang_str, tuple):
|
||||
continue
|
||||
main_locale[lang_str] = no_handler[0]
|
||||
locale_tformat[lang_str] = format_string # locale's date format string
|
||||
|
||||
|
||||
def register_datehandler(locales, parse_class, display_class):
|
||||
"""
|
||||
Registers the passed date parser class and date displayer
|
||||
@@ -123,14 +126,15 @@ def register_datehandler(locales,parse_class,display_class):
|
||||
:param display_class: Class to be associated with displaying
|
||||
:type display_class: :class:`.DateDisplay`
|
||||
"""
|
||||
format_string = ''
|
||||
format_string = ""
|
||||
for possible_format in locales: # allow possibly embedding a date format
|
||||
if isinstance(possible_format, tuple):
|
||||
format_string = possible_format[0] # pre-seeded date format string
|
||||
# maintain legacy gramps transformations
|
||||
format_string = format_string.replace('%y','%Y').replace('-', '/')
|
||||
format_string = format_string.replace("%y", "%Y").replace("-", "/")
|
||||
for lang_str in locales:
|
||||
if isinstance(lang_str, tuple): continue
|
||||
if isinstance(lang_str, tuple):
|
||||
continue
|
||||
LANG_TO_PARSER[lang_str] = parse_class
|
||||
LANG_TO_DISPLAY[lang_str] = display_class
|
||||
main_locale[lang_str] = locales[0]
|
||||
@@ -138,10 +142,11 @@ def register_datehandler(locales,parse_class,display_class):
|
||||
|
||||
parse_class._locale = display_class._locale = GrampsLocale(lang=locales[0])
|
||||
|
||||
register_datehandler(
|
||||
('en_GB', 'English_United Kingdom', ("%d/%m/%y",)),
|
||||
DateParser, DateDisplayGB)
|
||||
|
||||
register_datehandler(
|
||||
('en_US', 'en', 'English_United States', ("%m/%d/%y",)),
|
||||
DateParser, DateDisplayEn)
|
||||
("en_GB", "English_United Kingdom", ("%d/%m/%y",)), DateParser, DateDisplayGB
|
||||
)
|
||||
|
||||
register_datehandler(
|
||||
("en_US", "en", "English_United States", ("%m/%d/%y",)), DateParser, DateDisplayEn
|
||||
)
|
||||
|
@@ -544,30 +544,40 @@ class DateParser:
|
||||
r"%s\.?(\s+\d+)?\s*,?\s+((\d+)(/\d+)?)?\s*$" % self._mon_str, re.IGNORECASE
|
||||
)
|
||||
# this next RE has the (possibly-slashed) year at the string's end
|
||||
self._text2 = re.compile(r'(\d+)?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._mon_str, re.IGNORECASE)
|
||||
self._jtext = re.compile(r'%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._jmon_str, re.IGNORECASE)
|
||||
self._jtext2 = re.compile(r'(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._jmon_str, re.IGNORECASE)
|
||||
self._ftext = re.compile(r'%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._fmon_str, re.IGNORECASE)
|
||||
self._ftext2 = re.compile(r'(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._fmon_str, re.IGNORECASE)
|
||||
self._ptext = re.compile(r'%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._pmon_str, re.IGNORECASE)
|
||||
self._ptext2 = re.compile(r'(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._pmon_str, re.IGNORECASE)
|
||||
self._itext = re.compile(r'%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._imon_str, re.IGNORECASE)
|
||||
self._itext2 = re.compile(r'(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._imon_str, re.IGNORECASE)
|
||||
self._stext = re.compile(r'%s\.?\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._smon_str, re.IGNORECASE)
|
||||
self._stext2 = re.compile(r'(\d+)?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$'
|
||||
% self._smon_str, re.IGNORECASE)
|
||||
self._numeric = re.compile(
|
||||
r"((\d+)[/\.]\s*)?((\d+)[/\.]\s*)?(\d+)\s*$")
|
||||
self._text2 = re.compile(
|
||||
r"(\d+)?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$" % self._mon_str, re.IGNORECASE
|
||||
)
|
||||
self._jtext = re.compile(
|
||||
r"%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$" % self._jmon_str, re.IGNORECASE
|
||||
)
|
||||
self._jtext2 = re.compile(
|
||||
r"(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$" % self._jmon_str, re.IGNORECASE
|
||||
)
|
||||
self._ftext = re.compile(
|
||||
r"%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$" % self._fmon_str, re.IGNORECASE
|
||||
)
|
||||
self._ftext2 = re.compile(
|
||||
r"(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$" % self._fmon_str, re.IGNORECASE
|
||||
)
|
||||
self._ptext = re.compile(
|
||||
r"%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$" % self._pmon_str, re.IGNORECASE
|
||||
)
|
||||
self._ptext2 = re.compile(
|
||||
r"(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$" % self._pmon_str, re.IGNORECASE
|
||||
)
|
||||
self._itext = re.compile(
|
||||
r"%s\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$" % self._imon_str, re.IGNORECASE
|
||||
)
|
||||
self._itext2 = re.compile(
|
||||
r"(\d+)?\s+?%s\s*((\d+)(/\d+)?)?\s*$" % self._imon_str, re.IGNORECASE
|
||||
)
|
||||
self._stext = re.compile(
|
||||
r"%s\.?\s+(\d+)?\s*,?\s*((\d+)(/\d+)?)?\s*$" % self._smon_str, re.IGNORECASE
|
||||
)
|
||||
self._stext2 = re.compile(
|
||||
r"(\d+)?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$" % self._smon_str, re.IGNORECASE
|
||||
)
|
||||
self._numeric = re.compile(r"((\d+)[/\.]\s*)?((\d+)[/\.]\s*)?(\d+)\s*$")
|
||||
self._iso = re.compile(r"(\d+)(/(\d+))?-(\d+)(-(\d+))?\s*$")
|
||||
self._isotimestamp = re.compile(
|
||||
r"^\s*?(\d{4})([01]\d)([0123]\d)(?:(?:[012]\d[0-5]\d[0-5]\d)|"
|
||||
|
@@ -47,6 +47,7 @@ import logging
|
||||
|
||||
log = logging.getLogger(".DateStrings")
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# DateStrings
|
||||
@@ -97,7 +98,8 @@ class DateStrings:
|
||||
_("September", "localized lexeme inflections"),
|
||||
_("October", "localized lexeme inflections"),
|
||||
_("November", "localized lexeme inflections"),
|
||||
_("December", "localized lexeme inflections") )
|
||||
_("December", "localized lexeme inflections"),
|
||||
)
|
||||
|
||||
self.short_months = (
|
||||
"",
|
||||
@@ -116,7 +118,8 @@ class DateStrings:
|
||||
_("Sep", "localized lexeme inflections - short month form"),
|
||||
_("Oct", "localized lexeme inflections - short month form"),
|
||||
_("Nov", "localized lexeme inflections - short month form"),
|
||||
_("Dec", "localized lexeme inflections - short month form") )
|
||||
_("Dec", "localized lexeme inflections - short month form"),
|
||||
)
|
||||
|
||||
_ = locale.translation.sgettext
|
||||
self.alt_long_months = (
|
||||
@@ -136,7 +139,8 @@ class DateStrings:
|
||||
_("", "alternative month names for September"),
|
||||
_("", "alternative month names for October"),
|
||||
_("", "alternative month names for November"),
|
||||
_("", "alternative month names for December") )
|
||||
_("", "alternative month names for December"),
|
||||
)
|
||||
|
||||
self.calendar = (
|
||||
# Must appear in the order indexed by Date.CAL_... numeric constants
|
||||
|
@@ -38,6 +38,7 @@ from ..const import GRAMPS_LOCALE as glocale
|
||||
from ..lib.date import Date
|
||||
from . import LANG_TO_DISPLAY, LANG, parser, displayer
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
#
|
||||
# Convenience functions
|
||||
@@ -54,11 +55,12 @@ def get_date_formats(flocale=glocale):
|
||||
# trans_text is a defined keyword (see po/update_po.py, po/genpot.sh)
|
||||
trans_text = flocale.translation.sgettext
|
||||
try:
|
||||
return tuple(trans_text(fmt)
|
||||
for fmt in LANG_TO_DISPLAY[flocale.lang](0).formats)
|
||||
return tuple(
|
||||
trans_text(fmt) for fmt in LANG_TO_DISPLAY[flocale.lang](0).formats
|
||||
)
|
||||
except:
|
||||
return tuple(trans_text(fmt)
|
||||
for fmt in LANG_TO_DISPLAY['C'](0).formats)
|
||||
return tuple(trans_text(fmt) for fmt in LANG_TO_DISPLAY["C"](0).formats)
|
||||
|
||||
|
||||
def set_format(value):
|
||||
try:
|
||||
@@ -66,6 +68,7 @@ def set_format(value):
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def set_date(date_base, text):
|
||||
"""
|
||||
Set the date of the :class:`.DateBase` instance.
|
||||
@@ -79,6 +82,7 @@ def set_date(date_base, text):
|
||||
"""
|
||||
parser.set_date(date_base.get_date_object(), text)
|
||||
|
||||
|
||||
def get_date(date_base):
|
||||
"""
|
||||
Return a string representation of the date of the :class:`.DateBase`
|
||||
@@ -92,10 +96,12 @@ def get_date(date_base):
|
||||
"""
|
||||
return displayer.display(date_base.get_date_object())
|
||||
|
||||
|
||||
def get_date_valid(date_base):
|
||||
date_obj = date_base.get_date_object()
|
||||
return date_obj.get_valid()
|
||||
|
||||
|
||||
def format_time(secs):
|
||||
"""
|
||||
Format a time in seconds as a date in the preferred date format and a
|
||||
@@ -103,4 +109,4 @@ def format_time(secs):
|
||||
"""
|
||||
t = time.localtime(secs)
|
||||
d = Date(t.tm_year, t.tm_mon, t.tm_mday)
|
||||
return displayer.display(d) + time.strftime(' %X', t)
|
||||
return displayer.display(d) + time.strftime(" %X", t)
|
||||
|
@@ -47,7 +47,6 @@ set, we have to convert to unicode.
|
||||
codeset = glocale.encoding # TODO I don't think "codeset" is used anymore
|
||||
|
||||
try:
|
||||
|
||||
# here only for the upgrade tool, see _datestrings.py __main__
|
||||
_deprecated_long_months = (
|
||||
"",
|
||||
@@ -114,34 +113,34 @@ except:
|
||||
|
||||
_deprecated_long_months = (
|
||||
"",
|
||||
time.strftime('%B',(1,1,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,2,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,3,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,4,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,5,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,6,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,7,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,8,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,9,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,10,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,11,1,1,1,1,1,1,1)),
|
||||
time.strftime('%B',(1,12,1,1,1,1,1,1,1)),
|
||||
time.strftime("%B", (1, 1, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 2, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 3, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 4, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 5, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 6, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 7, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 8, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 9, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 10, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 11, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%B", (1, 12, 1, 1, 1, 1, 1, 1, 1)),
|
||||
)
|
||||
|
||||
_deprecated_short_months = (
|
||||
"",
|
||||
time.strftime('%b',(1,1,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,2,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,3,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,4,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,5,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,6,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,7,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,8,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,9,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,10,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,11,1,1,1,1,1,1,1)),
|
||||
time.strftime('%b',(1,12,1,1,1,1,1,1,1)),
|
||||
time.strftime("%b", (1, 1, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 2, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 3, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 4, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 5, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 6, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 7, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 8, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 9, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 10, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 11, 1, 1, 1, 1, 1, 1, 1)),
|
||||
time.strftime("%b", (1, 12, 1, 1, 1, 1, 1, 1, 1)),
|
||||
)
|
||||
|
||||
# Gramps day number: Sunday => 1, Monday => 2, etc
|
||||
@@ -155,22 +154,22 @@ except:
|
||||
# just a dummy.
|
||||
_deprecated_long_days = (
|
||||
"",
|
||||
time.strftime('%A',(1,1,1,1,1,1,6,1,1)), # Sunday
|
||||
time.strftime('%A',(1,1,1,1,1,1,0,1,1)), # Monday
|
||||
time.strftime('%A',(1,1,1,1,1,1,1,1,1)), # Tuesday
|
||||
time.strftime('%A',(1,1,1,1,1,1,2,1,1)), # Wednesday
|
||||
time.strftime('%A',(1,1,1,1,1,1,3,1,1)), # Thursday
|
||||
time.strftime('%A',(1,1,1,1,1,1,4,1,1)), # Friday
|
||||
time.strftime('%A',(1,1,1,1,1,1,5,1,1)), # Saturday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 6, 1, 1)), # Sunday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 0, 1, 1)), # Monday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 1, 1, 1)), # Tuesday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 2, 1, 1)), # Wednesday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 3, 1, 1)), # Thursday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 4, 1, 1)), # Friday
|
||||
time.strftime("%A", (1, 1, 1, 1, 1, 1, 5, 1, 1)), # Saturday
|
||||
)
|
||||
|
||||
_deprecated_short_days = (
|
||||
"",
|
||||
time.strftime('%a',(1,1,1,1,1,1,6,1,1)), # Sun
|
||||
time.strftime('%a',(1,1,1,1,1,1,0,1,1)), # Mon
|
||||
time.strftime('%a',(1,1,1,1,1,1,1,1,1)), # Tue
|
||||
time.strftime('%a',(1,1,1,1,1,1,2,1,1)), # Wed
|
||||
time.strftime('%a',(1,1,1,1,1,1,3,1,1)), # Thu
|
||||
time.strftime('%a',(1,1,1,1,1,1,4,1,1)), # Fri
|
||||
time.strftime('%a',(1,1,1,1,1,1,5,1,1)), # Sat
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 6, 1, 1)), # Sun
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 0, 1, 1)), # Mon
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 1, 1, 1)), # Tue
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 2, 1, 1)), # Wed
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 3, 1, 1)), # Thu
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 4, 1, 1)), # Fri
|
||||
time.strftime("%a", (1, 1, 1, 1, 1, 1, 5, 1, 1)), # Sat
|
||||
)
|
||||
|
@@ -28,11 +28,13 @@ import unittest
|
||||
from ...utils.grampslocale import GrampsLocale
|
||||
from ...lib.date import Date
|
||||
|
||||
|
||||
class DateDisplayTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from .._datedisplay import DateDisplayEn
|
||||
|
||||
self.display = DateDisplayEn()
|
||||
self.display_RU = GrampsLocale(lang='ru').date_displayer
|
||||
self.display_RU = GrampsLocale(lang="ru").date_displayer
|
||||
|
||||
def assert_map_key_val(self, m, k, v):
|
||||
try:
|
||||
@@ -40,12 +42,14 @@ class DateDisplayTest(unittest.TestCase):
|
||||
except KeyError:
|
||||
self.assertTrue(False, list(m.items()))
|
||||
|
||||
|
||||
class DateDisplayCalendarTest(DateDisplayTest):
|
||||
def test_calendar_gregorian_is_empty(self):
|
||||
self.assert_map_key_val(self.display.calendar, Date.CAL_GREGORIAN, "")
|
||||
|
||||
def test_calendar_julian_RU(self):
|
||||
self.assert_map_key_val(self.display_RU.calendar, Date.CAL_JULIAN, 'Юлианский')
|
||||
self.assert_map_key_val(self.display_RU.calendar, Date.CAL_JULIAN, "Юлианский")
|
||||
|
||||
|
||||
# This class tests common functionality in DateDisplay as applied to RU,
|
||||
# and so it is coupled to translated strings and inflection names
|
||||
@@ -63,32 +67,31 @@ class DateDisplayInflectionsTestRU(DateDisplayTest):
|
||||
if month is None:
|
||||
month = date.get_month()
|
||||
month_lexeme = self.months[month]
|
||||
self.assertIn(month_lexeme.forms[inflection],
|
||||
self.dd.display(date))
|
||||
self.assertIn(month_lexeme.forms[inflection], self.dd.display(date))
|
||||
|
||||
def test_month_only_date_nominative_quality_none(self):
|
||||
d1945may = Date(1945, 5, 0)
|
||||
d1945may.set_quality(Date.QUAL_NONE)
|
||||
self.assertInflectionInDate('И', d1945may)
|
||||
self.assertInflectionInDate("И", d1945may)
|
||||
|
||||
def test_month_only_date_nominative_quality_estimated(self):
|
||||
d1945may = Date(1945, 5, 0)
|
||||
d1945may.set_quality(Date.QUAL_ESTIMATED)
|
||||
self.assertInflectionInDate('Т', d1945may)
|
||||
self.assertInflectionInDate("Т", d1945may)
|
||||
|
||||
def test_month_only_date_nominative_quality_calculated(self):
|
||||
d1945may = Date(1945, 5, 0)
|
||||
d1945may.set_quality(Date.QUAL_CALCULATED)
|
||||
self.assertInflectionInDate('И', d1945may)
|
||||
self.assertInflectionInDate("И", d1945may)
|
||||
|
||||
def test_day_month_date_genitive(self):
|
||||
d1945may9 = Date(1945, 5, 9)
|
||||
self.assertInflectionInDate('Р', d1945may9)
|
||||
self.assertInflectionInDate("Р", d1945may9)
|
||||
|
||||
def test_day_month_date_genitiive_quality_estimated(self):
|
||||
d1945may9 = Date(1945, 5, 9)
|
||||
d1945may9.set_quality(Date.QUAL_ESTIMATED)
|
||||
self.assertInflectionInDate('Р', d1945may9)
|
||||
self.assertInflectionInDate("Р", d1945may9)
|
||||
|
||||
def test_before_month_only_date_genitive(self):
|
||||
d1945may = Date(1945, 5, 0)
|
||||
@@ -123,8 +126,8 @@ class DateDisplayInflectionsTestRU(DateDisplayTest):
|
||||
def test_between_month_only_dates_ablative(self):
|
||||
b1945may_1946may = Date()
|
||||
b1945may_1946may.set(
|
||||
modifier=Date.MOD_RANGE,
|
||||
value=(0, 5, 1945, False, 0, 5, 1946, False))
|
||||
modifier=Date.MOD_RANGE, value=(0, 5, 1945, False, 0, 5, 1946, False)
|
||||
)
|
||||
# TODO hardwired magic numbers! Bad API smell.
|
||||
for inflecting_format in (3, 4):
|
||||
self.dd.set_format(inflecting_format)
|
||||
@@ -136,8 +139,8 @@ class DateDisplayInflectionsTestRU(DateDisplayTest):
|
||||
def test_month_only_date_span_from_genitive_to_accusative(self):
|
||||
f1945may_t1946may = Date()
|
||||
f1945may_t1946may.set(
|
||||
modifier=Date.MOD_SPAN,
|
||||
value=(0, 5, 1945, False, 0, 5, 1946, False))
|
||||
modifier=Date.MOD_SPAN, value=(0, 5, 1945, False, 0, 5, 1946, False)
|
||||
)
|
||||
# TODO hardwired magic numbers! Bad API smell.
|
||||
for inflecting_format in (3, 4):
|
||||
self.dd.set_format(inflecting_format)
|
||||
@@ -146,5 +149,6 @@ class DateDisplayInflectionsTestRU(DateDisplayTest):
|
||||
self.assertIn("с мая", self.dd.display(f1945may_t1946may))
|
||||
self.assertIn("по май", self.dd.display(f1945may_t1946may))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -55,6 +55,7 @@ from ...lib import Date, DateError
|
||||
from ...utils.grampslocale import GrampsLocale, _LOCALE_NAMES
|
||||
from .. import LANG_TO_PARSER
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
@@ -65,7 +66,6 @@ class DateHandlerTest(unittest.TestCase):
|
||||
config.set("preferences.date-format", 0)
|
||||
|
||||
def __base_test_all_languages(self, dates):
|
||||
|
||||
languages = [
|
||||
lang for lang in LANG_TO_PARSER.keys() if lang in _LOCALE_NAMES.keys()
|
||||
]
|
||||
@@ -74,7 +74,6 @@ class DateHandlerTest(unittest.TestCase):
|
||||
self.__test_language(language, dates)
|
||||
|
||||
def __test_language(self, language, dates):
|
||||
|
||||
locale = GrampsLocale(lang=language)
|
||||
displayer = locale.date_displayer
|
||||
parser = locale.date_parser
|
||||
@@ -90,7 +89,6 @@ class DateHandlerTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_simple(self):
|
||||
|
||||
dates = []
|
||||
for calendar in (Date.CAL_GREGORIAN, Date.CAL_JULIAN):
|
||||
for newyear in (Date.NEWYEAR_JAN1, Date.NEWYEAR_MAR25, (5, 5)):
|
||||
@@ -123,7 +121,6 @@ class DateHandlerTest(unittest.TestCase):
|
||||
self.__base_test_all_languages(dates)
|
||||
|
||||
def test_span(self):
|
||||
|
||||
dates = []
|
||||
calendar = Date.CAL_GREGORIAN
|
||||
for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED):
|
||||
@@ -207,7 +204,6 @@ class DateHandlerTest(unittest.TestCase):
|
||||
self.__base_test_all_languages(dates)
|
||||
|
||||
def test_textual(self):
|
||||
|
||||
dates = []
|
||||
calendar = Date.CAL_GREGORIAN
|
||||
modifier = Date.MOD_TEXTONLY
|
||||
|
@@ -28,11 +28,13 @@ import unittest
|
||||
from ...utils.grampslocale import GrampsLocale
|
||||
from ...lib.date import Date
|
||||
|
||||
|
||||
class DateParserTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from .._dateparser import DateParser
|
||||
|
||||
self.parser = DateParser()
|
||||
self.parser_RU = GrampsLocale(lang='ru').date_parser
|
||||
self.parser_RU = GrampsLocale(lang="ru").date_parser
|
||||
|
||||
def assert_map_key_val(self, m, k, v):
|
||||
try:
|
||||
@@ -41,87 +43,96 @@ class DateParserTest(unittest.TestCase):
|
||||
self.assertTrue(False, list(m.items()))
|
||||
|
||||
def test_month_to_int_jan_is_1(self):
|
||||
self.assert_map_key_val(self.parser.month_to_int, 'jan', 1)
|
||||
self.assert_map_key_val(self.parser.month_to_int, "jan", 1)
|
||||
|
||||
def test_prefix_table_for_RU_built(self):
|
||||
self.assertIn('ru_RU', self.parser._langs)
|
||||
self.assertIn("ru_RU", self.parser._langs)
|
||||
|
||||
def test_month_to_int_septem_RU_is_9(self):
|
||||
self.assert_map_key_val(self.parser.month_to_int, 'сентяб', 9)
|
||||
self.assert_map_key_val(self.parser.month_to_int, "сентяб", 9)
|
||||
|
||||
def test_hebrew_to_int_av_is_12(self):
|
||||
self.assert_map_key_val(self.parser.hebrew_to_int, 'av', 12)
|
||||
self.assert_map_key_val(self.parser.hebrew_to_int, 'ав', 12) # RU
|
||||
self.assert_map_key_val(self.parser.hebrew_to_int, "av", 12)
|
||||
self.assert_map_key_val(self.parser.hebrew_to_int, "ав", 12) # RU
|
||||
|
||||
def test_french_to_int_thermidor_is_11(self):
|
||||
self.assert_map_key_val(self.parser.french_to_int, 'thermidor', 11)
|
||||
self.assert_map_key_val(self.parser.french_to_int, 'термидор', 11) # RU
|
||||
self.assert_map_key_val(self.parser.french_to_int, "thermidor", 11)
|
||||
self.assert_map_key_val(self.parser.french_to_int, "термидор", 11) # RU
|
||||
|
||||
def test_islamic_to_int_ramadan_is_9(self):
|
||||
self.assert_map_key_val(self.parser.islamic_to_int, 'ramadan', 9)
|
||||
self.assert_map_key_val(self.parser.islamic_to_int, 'рамадан', 9) # RU
|
||||
self.assert_map_key_val(self.parser.islamic_to_int, "ramadan", 9)
|
||||
self.assert_map_key_val(self.parser.islamic_to_int, "рамадан", 9) # RU
|
||||
|
||||
def test_persian_to_int_tir_is_4(self):
|
||||
self.assert_map_key_val(self.parser.persian_to_int, 'tir', 4)
|
||||
self.assert_map_key_val(self.parser.persian_to_int, 'тир', 4) # RU
|
||||
self.assert_map_key_val(self.parser.persian_to_int, "tir", 4)
|
||||
self.assert_map_key_val(self.parser.persian_to_int, "тир", 4) # RU
|
||||
|
||||
def test_calendar_to_int_gregorian(self):
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'gregorian', Date.CAL_GREGORIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'g', Date.CAL_GREGORIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'григорианский', Date.CAL_GREGORIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'г', Date.CAL_GREGORIAN)
|
||||
self.assert_map_key_val(
|
||||
self.parser.calendar_to_int, "gregorian", Date.CAL_GREGORIAN
|
||||
)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, "g", Date.CAL_GREGORIAN)
|
||||
self.assert_map_key_val(
|
||||
self.parser.calendar_to_int, "григорианский", Date.CAL_GREGORIAN
|
||||
)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, "г", Date.CAL_GREGORIAN)
|
||||
|
||||
def test_calendar_to_int_julian(self):
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'julian', Date.CAL_JULIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'j', Date.CAL_JULIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'юлианский', Date.CAL_JULIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, 'ю', Date.CAL_JULIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, "julian", Date.CAL_JULIAN)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, "j", Date.CAL_JULIAN)
|
||||
self.assert_map_key_val(
|
||||
self.parser.calendar_to_int, "юлианский", Date.CAL_JULIAN
|
||||
)
|
||||
self.assert_map_key_val(self.parser.calendar_to_int, "ю", Date.CAL_JULIAN)
|
||||
|
||||
def test_quarter_1(self):
|
||||
date = self.parser.parse('q1 1900')
|
||||
self.assertTrue(date.is_equal(self.parser.parse('Q1 1900')))
|
||||
date = self.parser.parse("q1 1900")
|
||||
self.assertTrue(date.is_equal(self.parser.parse("Q1 1900")))
|
||||
self.assertEqual(date.get_ymd(), (1900, 1, 1))
|
||||
self.assertEqual(date.get_stop_ymd(), (1900, 3, 31))
|
||||
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
|
||||
|
||||
def test_quarter_2(self):
|
||||
date = self.parser.parse('q2 1900')
|
||||
self.assertTrue(date.is_equal(self.parser.parse('Q2 1900')))
|
||||
date = self.parser.parse("q2 1900")
|
||||
self.assertTrue(date.is_equal(self.parser.parse("Q2 1900")))
|
||||
self.assertEqual(date.get_ymd(), (1900, 4, 1))
|
||||
self.assertEqual(date.get_stop_ymd(), (1900, 6, 30))
|
||||
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
|
||||
|
||||
def test_quarter_3(self):
|
||||
date = self.parser.parse('q3 1900')
|
||||
self.assertTrue(date.is_equal(self.parser.parse('Q3 1900')))
|
||||
date = self.parser.parse("q3 1900")
|
||||
self.assertTrue(date.is_equal(self.parser.parse("Q3 1900")))
|
||||
self.assertEqual(date.get_ymd(), (1900, 7, 1))
|
||||
self.assertEqual(date.get_stop_ymd(), (1900, 9, 30))
|
||||
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
|
||||
|
||||
def test_quarter_4(self):
|
||||
date = self.parser.parse('q4 1900')
|
||||
self.assertTrue(date.is_equal(self.parser.parse('Q4 1900')))
|
||||
date = self.parser.parse("q4 1900")
|
||||
self.assertTrue(date.is_equal(self.parser.parse("Q4 1900")))
|
||||
self.assertEqual(date.get_ymd(), (1900, 10, 1))
|
||||
self.assertEqual(date.get_stop_ymd(), (1900, 12, 31))
|
||||
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
|
||||
|
||||
def test_quarter_quality_calendar(self):
|
||||
date = self.parser.parse('calc q1 1900 (julian)')
|
||||
date = self.parser.parse("calc q1 1900 (julian)")
|
||||
self.assertEqual(date.get_quality(), Date.QUAL_CALCULATED)
|
||||
self.assertEqual(date.get_calendar(), Date.CAL_JULIAN)
|
||||
|
||||
|
||||
class Test_generate_variants(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from .. import _datestrings
|
||||
from .._dateparser import _generate_variants
|
||||
self.ds = ds = _datestrings.DateStrings(GrampsLocale(languages=('ru')))
|
||||
self.month_variants = list(_generate_variants(
|
||||
zip(ds.long_months, ds.short_months,
|
||||
ds.swedish_SV, ds.alt_long_months)))
|
||||
|
||||
self.ds = ds = _datestrings.DateStrings(GrampsLocale(languages=("ru")))
|
||||
self.month_variants = list(
|
||||
_generate_variants(
|
||||
zip(ds.long_months, ds.short_months, ds.swedish_SV, ds.alt_long_months)
|
||||
)
|
||||
)
|
||||
|
||||
def testVariantsSameLengthAsLongMonths(self):
|
||||
self.assertEqual(len(self.ds.long_months),
|
||||
len(self.month_variants))
|
||||
self.assertEqual(len(self.ds.long_months), len(self.month_variants))
|
||||
|
||||
def testRussianHasDifferentVariantsForEachMonth(self):
|
||||
for i in range(1, 13):
|
||||
@@ -154,5 +165,6 @@ class Test_generate_variants(unittest.TestCase):
|
||||
v = self.month_variants[5]
|
||||
self.assertIn("Maj", v)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -24,16 +24,18 @@ import unittest
|
||||
from .. import _datestrings
|
||||
from ...lib.date import Date
|
||||
|
||||
|
||||
class DateStringsTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from ...utils.grampslocale import GrampsLocale
|
||||
|
||||
self.ds = _datestrings.DateStrings(GrampsLocale()) # whatever the default...
|
||||
self.ds_EN = _datestrings.DateStrings(GrampsLocale(languages='en'))
|
||||
self.ds_RU = _datestrings.DateStrings(GrampsLocale(languages='ru'))
|
||||
self.ds_EN = _datestrings.DateStrings(GrampsLocale(languages="en"))
|
||||
self.ds_RU = _datestrings.DateStrings(GrampsLocale(languages="ru"))
|
||||
|
||||
def testTwelfthMonthIsDecember(self):
|
||||
self.assertEqual(self.ds_EN.long_months[12], 'December')
|
||||
self.assertEqual(self.ds_EN.short_months[12], 'Dec')
|
||||
self.assertEqual(self.ds_EN.long_months[12], "December")
|
||||
self.assertEqual(self.ds_EN.short_months[12], "Dec")
|
||||
|
||||
# May is 3-letter in Russian, and so abbreviated form
|
||||
# will be different for inflections!
|
||||
@@ -76,5 +78,6 @@ class DateStringsTest(unittest.TestCase):
|
||||
def testDayNamesLenIs8(self):
|
||||
self.assertEqual(len(self.ds.long_days), 8)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -42,6 +42,7 @@ import logging
|
||||
# -------------------------------------------------------------------------
|
||||
from ..db.dbconst import DBLOGNAME
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
from ..lib.childreftype import ChildRefType
|
||||
from ..lib.childref import ChildRef
|
||||
@@ -1264,8 +1265,14 @@ class DbReadBase:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def load(self, name, callback, mode=None, force_schema_upgrade=False,
|
||||
force_bsddb_upgrade=False):
|
||||
def load(
|
||||
self,
|
||||
name,
|
||||
callback,
|
||||
mode=None,
|
||||
force_schema_upgrade=False,
|
||||
force_bsddb_upgrade=False,
|
||||
):
|
||||
"""
|
||||
Open the specified database.
|
||||
"""
|
||||
@@ -1295,8 +1302,9 @@ class DbReadBase:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def set_prefixes(self, person, media, family, source, citation,
|
||||
place, event, repository, note):
|
||||
def set_prefixes(
|
||||
self, person, media, family, source, citation, place, event, repository, note
|
||||
):
|
||||
"""
|
||||
Set the prefixes for the gramps ids for all gramps objects
|
||||
"""
|
||||
@@ -1797,10 +1805,9 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def add_child_to_family(self, family, child,
|
||||
mrel=ChildRefType(),
|
||||
frel=ChildRefType(),
|
||||
trans=None):
|
||||
def add_child_to_family(
|
||||
self, family, child, mrel=ChildRefType(), frel=ChildRefType(), trans=None
|
||||
):
|
||||
"""
|
||||
Adds a child to a family.
|
||||
"""
|
||||
@@ -1813,26 +1820,23 @@ class DbWriteBase(DbReadBase):
|
||||
child.add_parent_family_handle(family.handle)
|
||||
|
||||
if trans is None:
|
||||
with DbTxn(_('Add child to family'), self) as trans:
|
||||
with DbTxn(_("Add child to family"), self) as trans:
|
||||
self.commit_family(family, trans)
|
||||
self.commit_person(child, trans)
|
||||
else:
|
||||
self.commit_family(family, trans)
|
||||
self.commit_person(child, trans)
|
||||
|
||||
def remove_child_from_family(self, person_handle, family_handle,
|
||||
trans=None):
|
||||
def remove_child_from_family(self, person_handle, family_handle, trans=None):
|
||||
"""
|
||||
Remove a person as a child of the family, deleting the family if
|
||||
it becomes empty.
|
||||
"""
|
||||
if trans is None:
|
||||
with DbTxn(_("Remove child from family"), self) as trans:
|
||||
self.__remove_child_from_family(person_handle, family_handle,
|
||||
trans)
|
||||
self.__remove_child_from_family(person_handle, family_handle, trans)
|
||||
else:
|
||||
self.__remove_child_from_family(person_handle, family_handle,
|
||||
trans)
|
||||
self.__remove_child_from_family(person_handle, family_handle, trans)
|
||||
trans.set_description(_("Remove child from family"))
|
||||
|
||||
def __remove_child_from_family(self, person_handle, family_handle, trans):
|
||||
@@ -1845,8 +1849,11 @@ class DbWriteBase(DbReadBase):
|
||||
person.remove_parent_family_handle(family_handle)
|
||||
family.remove_child_handle(person_handle)
|
||||
|
||||
if (not family.get_father_handle() and not family.get_mother_handle()
|
||||
and not family.get_child_ref_list()):
|
||||
if (
|
||||
not family.get_father_handle()
|
||||
and not family.get_mother_handle()
|
||||
and not family.get_child_ref_list()
|
||||
):
|
||||
self.remove_family_relationships(family_handle, trans)
|
||||
else:
|
||||
self.commit_family(family, trans)
|
||||
@@ -1874,9 +1881,11 @@ class DbWriteBase(DbReadBase):
|
||||
else:
|
||||
family.set_mother_handle(None)
|
||||
|
||||
if not family.get_father_handle() and \
|
||||
not family.get_mother_handle() and \
|
||||
not family.get_child_ref_list():
|
||||
if (
|
||||
not family.get_father_handle()
|
||||
and not family.get_mother_handle()
|
||||
and not family.get_child_ref_list()
|
||||
):
|
||||
self.remove_family_relationships(family_handle, trans)
|
||||
else:
|
||||
self.commit_family(family, trans)
|
||||
@@ -1885,9 +1894,11 @@ class DbWriteBase(DbReadBase):
|
||||
if family_handle:
|
||||
family = self.get_family_from_handle(family_handle)
|
||||
family.remove_child_handle(person.get_handle())
|
||||
if not family.get_father_handle() and \
|
||||
not family.get_mother_handle() and \
|
||||
not family.get_child_ref_list():
|
||||
if (
|
||||
not family.get_father_handle()
|
||||
and not family.get_mother_handle()
|
||||
and not family.get_child_ref_list()
|
||||
):
|
||||
self.remove_family_relationships(family_handle, trans)
|
||||
else:
|
||||
self.commit_family(family, trans)
|
||||
@@ -1896,7 +1907,7 @@ class DbWriteBase(DbReadBase):
|
||||
|
||||
for obj_type, ohandle in self.find_backlink_handles(handle):
|
||||
obj = self.method("get_%s_from_handle", obj_type)(ohandle)
|
||||
obj.remove_handle_references('Person', [handle])
|
||||
obj.remove_handle_references("Person", [handle])
|
||||
self.method("commit_%s", obj_type)(obj, trans)
|
||||
self.remove_person(handle, trans)
|
||||
|
||||
@@ -1918,24 +1929,23 @@ class DbWriteBase(DbReadBase):
|
||||
for obj_type, ohandle in self.find_backlink_handles(family_handle):
|
||||
obj = self.method("get_%s_from_handle", obj_type)(ohandle)
|
||||
if obj:
|
||||
obj.remove_handle_references('Family', [family_handle])
|
||||
obj.remove_handle_references("Family", [family_handle])
|
||||
self.method("commit_%s", obj_type)(obj, trans)
|
||||
self.remove_family(family_handle, trans)
|
||||
|
||||
def remove_parent_from_family(self, person_handle, family_handle,
|
||||
trans=None):
|
||||
def remove_parent_from_family(self, person_handle, family_handle, trans=None):
|
||||
"""
|
||||
Remove a person as either the father or mother of a family,
|
||||
deleting the family if it becomes empty.
|
||||
"""
|
||||
if trans is None:
|
||||
with DbTxn('', self) as trans:
|
||||
msg = self.__remove_parent_from_family(person_handle,
|
||||
family_handle, trans)
|
||||
with DbTxn("", self) as trans:
|
||||
msg = self.__remove_parent_from_family(
|
||||
person_handle, family_handle, trans
|
||||
)
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
msg = self.__remove_parent_from_family(person_handle,
|
||||
family_handle, trans)
|
||||
msg = self.__remove_parent_from_family(person_handle, family_handle, trans)
|
||||
trans.set_description(msg)
|
||||
|
||||
def __remove_parent_from_family(self, person_handle, family_handle, trans):
|
||||
@@ -1954,13 +1964,18 @@ class DbWriteBase(DbReadBase):
|
||||
msg = _("Remove mother from family")
|
||||
family.set_mother_handle(None)
|
||||
else:
|
||||
raise DbTransactionCancel("The relation between the person and "
|
||||
raise DbTransactionCancel(
|
||||
"The relation between the person and "
|
||||
"the family you try to remove is not consistent, please fix "
|
||||
"that first, for example from the family editor or by running "
|
||||
"the database repair tool, before removing the family.")
|
||||
"the database repair tool, before removing the family."
|
||||
)
|
||||
|
||||
if (not family.get_father_handle() and not family.get_mother_handle()
|
||||
and not family.get_child_ref_list()):
|
||||
if (
|
||||
not family.get_father_handle()
|
||||
and not family.get_mother_handle()
|
||||
and not family.get_child_ref_list()
|
||||
):
|
||||
self.remove_family_relationships(family_handle, trans)
|
||||
else:
|
||||
self.commit_family(family, trans)
|
||||
@@ -1992,8 +2007,18 @@ class DbWriteBase(DbReadBase):
|
||||
note_len = self.get_number_of_notes()
|
||||
tag_len = self.get_number_of_tags()
|
||||
|
||||
return (person_len + family_len + event_len + place_len + repo_len +
|
||||
source_len + citation_len + media_len + note_len + tag_len)
|
||||
return (
|
||||
person_len
|
||||
+ family_len
|
||||
+ event_len
|
||||
+ place_len
|
||||
+ repo_len
|
||||
+ source_len
|
||||
+ citation_len
|
||||
+ media_len
|
||||
+ note_len
|
||||
+ tag_len
|
||||
)
|
||||
|
||||
def set_birth_death_index(self, person):
|
||||
"""
|
||||
@@ -2004,13 +2029,17 @@ class DbWriteBase(DbReadBase):
|
||||
event_ref_list = person.get_event_ref_list()
|
||||
for index, ref in enumerate(event_ref_list):
|
||||
event = self.get_event_from_handle(ref.ref)
|
||||
if (event.type.is_birth()
|
||||
if (
|
||||
event.type.is_birth()
|
||||
and ref.role.is_primary()
|
||||
and (birth_ref_index == -1)):
|
||||
and (birth_ref_index == -1)
|
||||
):
|
||||
birth_ref_index = index
|
||||
elif (event.type.is_death()
|
||||
elif (
|
||||
event.type.is_death()
|
||||
and ref.role.is_primary()
|
||||
and (death_ref_index == -1)):
|
||||
and (death_ref_index == -1)
|
||||
):
|
||||
death_ref_index = index
|
||||
|
||||
person.birth_ref_index = birth_ref_index
|
||||
|
@@ -28,15 +28,41 @@ Declare constants used by database modules
|
||||
# constants
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
__all__ = ( 'DBPAGE', 'DBMODE', 'DBCACHE', 'DBLOCKS', 'DBOBJECTS', 'DBUNDO',
|
||||
'DBEXT', 'DBMODE_R', 'DBMODE_W', 'DBUNDOFN', 'DBLOCKFN',
|
||||
'DBRECOVFN','BDBVERSFN', 'DBLOGNAME', 'SCHVERSFN', 'PCKVERSFN',
|
||||
'DBBACKEND',
|
||||
'PERSON_KEY', 'FAMILY_KEY', 'SOURCE_KEY', 'CITATION_KEY',
|
||||
'EVENT_KEY', 'MEDIA_KEY', 'PLACE_KEY', 'REPOSITORY_KEY',
|
||||
'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY',
|
||||
'TXNADD', 'TXNUPD', 'TXNDEL',
|
||||
"CLASS_TO_KEY_MAP", "KEY_TO_CLASS_MAP", "KEY_TO_NAME_MAP"
|
||||
__all__ = (
|
||||
"DBPAGE",
|
||||
"DBMODE",
|
||||
"DBCACHE",
|
||||
"DBLOCKS",
|
||||
"DBOBJECTS",
|
||||
"DBUNDO",
|
||||
"DBEXT",
|
||||
"DBMODE_R",
|
||||
"DBMODE_W",
|
||||
"DBUNDOFN",
|
||||
"DBLOCKFN",
|
||||
"DBRECOVFN",
|
||||
"BDBVERSFN",
|
||||
"DBLOGNAME",
|
||||
"SCHVERSFN",
|
||||
"PCKVERSFN",
|
||||
"DBBACKEND",
|
||||
"PERSON_KEY",
|
||||
"FAMILY_KEY",
|
||||
"SOURCE_KEY",
|
||||
"CITATION_KEY",
|
||||
"EVENT_KEY",
|
||||
"MEDIA_KEY",
|
||||
"PLACE_KEY",
|
||||
"REPOSITORY_KEY",
|
||||
"NOTE_KEY",
|
||||
"REFERENCE_KEY",
|
||||
"TAG_KEY",
|
||||
"TXNADD",
|
||||
"TXNUPD",
|
||||
"TXNDEL",
|
||||
"CLASS_TO_KEY_MAP",
|
||||
"KEY_TO_CLASS_MAP",
|
||||
"KEY_TO_NAME_MAP",
|
||||
)
|
||||
|
||||
DBEXT = ".db" # File extension to be used for database files
|
||||
@@ -72,7 +98,8 @@ CITATION_KEY = 10
|
||||
|
||||
TXNADD, TXNUPD, TXNDEL = 0, 1, 2
|
||||
|
||||
CLASS_TO_KEY_MAP = {"Person": PERSON_KEY,
|
||||
CLASS_TO_KEY_MAP = {
|
||||
"Person": PERSON_KEY,
|
||||
"Family": FAMILY_KEY,
|
||||
"Source": SOURCE_KEY,
|
||||
"Citation": CITATION_KEY,
|
||||
@@ -81,9 +108,11 @@ CLASS_TO_KEY_MAP = {"Person": PERSON_KEY,
|
||||
"Place": PLACE_KEY,
|
||||
"Repository": REPOSITORY_KEY,
|
||||
"Note": NOTE_KEY,
|
||||
"Tag": TAG_KEY}
|
||||
"Tag": TAG_KEY,
|
||||
}
|
||||
|
||||
KEY_TO_CLASS_MAP = {PERSON_KEY: "Person",
|
||||
KEY_TO_CLASS_MAP = {
|
||||
PERSON_KEY: "Person",
|
||||
FAMILY_KEY: "Family",
|
||||
SOURCE_KEY: "Source",
|
||||
CITATION_KEY: "Citation",
|
||||
@@ -92,16 +121,19 @@ KEY_TO_CLASS_MAP = {PERSON_KEY: "Person",
|
||||
PLACE_KEY: "Place",
|
||||
REPOSITORY_KEY: "Repository",
|
||||
NOTE_KEY: "Note",
|
||||
TAG_KEY: "Tag"}
|
||||
TAG_KEY: "Tag",
|
||||
}
|
||||
|
||||
KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
|
||||
FAMILY_KEY: 'family',
|
||||
EVENT_KEY: 'event',
|
||||
SOURCE_KEY: 'source',
|
||||
CITATION_KEY: 'citation',
|
||||
PLACE_KEY: 'place',
|
||||
MEDIA_KEY: 'media',
|
||||
REPOSITORY_KEY: 'repository',
|
||||
KEY_TO_NAME_MAP = {
|
||||
PERSON_KEY: "person",
|
||||
FAMILY_KEY: "family",
|
||||
EVENT_KEY: "event",
|
||||
SOURCE_KEY: "source",
|
||||
CITATION_KEY: "citation",
|
||||
PLACE_KEY: "place",
|
||||
MEDIA_KEY: "media",
|
||||
REPOSITORY_KEY: "repository",
|
||||
# REFERENCE_KEY: 'reference',
|
||||
NOTE_KEY: 'note',
|
||||
TAG_KEY: 'tag'}
|
||||
NOTE_KEY: "note",
|
||||
TAG_KEY: "tag",
|
||||
}
|
||||
|
@@ -87,6 +87,7 @@ def wrapper(method):
|
||||
every function in a class. The 'wrapped' method logs the original function
|
||||
that was called, and where it was called from.
|
||||
"""
|
||||
|
||||
@wraps(method)
|
||||
def wrapped(*args, **keywargs):
|
||||
"""
|
||||
@@ -99,10 +100,16 @@ def wrapper(method):
|
||||
frame = inspect.currentframe()
|
||||
c_frame = frame.f_back
|
||||
c_code = c_frame.f_code
|
||||
LOG.debug('calling %s.%s()... from file %s, line %s in %s',
|
||||
class_name, func_name, c_code.co_filename,
|
||||
c_frame.f_lineno, c_code.co_name)
|
||||
LOG.debug(
|
||||
"calling %s.%s()... from file %s, line %s in %s",
|
||||
class_name,
|
||||
func_name,
|
||||
c_code.co_filename,
|
||||
c_frame.f_lineno,
|
||||
c_code.co_name,
|
||||
)
|
||||
return method(*args, **keywargs)
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
@@ -111,6 +118,7 @@ class MetaClass(type):
|
||||
transform class by wrapping it with a diagnostic wrapper (if __debig__ is
|
||||
not set
|
||||
"""
|
||||
|
||||
def __new__(mcs, class_name, bases, classdict):
|
||||
"""
|
||||
When the class this is applied to (DummyDb) is instantiated, each method
|
||||
@@ -134,6 +142,7 @@ class M_A_M_B(ABCMeta, MetaClass):
|
||||
See recipe: http://code.activestate.com/recipes/204197-solving-the-
|
||||
metaclass-conflict/
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -142,7 +151,17 @@ class M_A_M_B(ABCMeta, MetaClass):
|
||||
# class DummyDb
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
class DummyDb(
|
||||
M_A_M_B(
|
||||
"NewBaseClass",
|
||||
(
|
||||
DbReadBase,
|
||||
Callback,
|
||||
object,
|
||||
),
|
||||
{},
|
||||
)
|
||||
):
|
||||
"""
|
||||
Gramps database object. This object is a dummy database class that is always
|
||||
empty and is read-only.
|
||||
@@ -469,7 +488,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_family_handles(self, sort_handles=False, locale=glocale):
|
||||
"""
|
||||
@@ -611,7 +630,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_note_handles(self):
|
||||
"""
|
||||
@@ -731,7 +750,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_person_attribute_types(self):
|
||||
"""
|
||||
@@ -778,7 +797,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_person_handles(self, sort_handles=False, locale=glocale):
|
||||
"""
|
||||
@@ -839,7 +858,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_place_handles(self, sort_handles=False, locale=glocale):
|
||||
"""
|
||||
@@ -862,7 +881,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_family_data(self, handle):
|
||||
"""
|
||||
@@ -871,7 +890,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_note_data(self, handle):
|
||||
"""
|
||||
@@ -880,7 +899,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_media_data(self, handle):
|
||||
"""
|
||||
@@ -889,7 +908,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_person_data(self, handle):
|
||||
"""
|
||||
@@ -898,7 +917,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_place_data(self, handle):
|
||||
"""
|
||||
@@ -907,7 +926,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_repository_data(self, handle):
|
||||
"""
|
||||
@@ -916,7 +935,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_source_data(self, handle):
|
||||
"""
|
||||
@@ -925,7 +944,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_citation_data(self, handle):
|
||||
"""
|
||||
@@ -934,7 +953,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_raw_tag_data(self, handle):
|
||||
"""
|
||||
@@ -943,7 +962,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_repo_bookmarks(self):
|
||||
"""
|
||||
@@ -981,7 +1000,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_repository_handles(self):
|
||||
"""
|
||||
@@ -1052,7 +1071,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_source_handles(self, sort_handles=False, locale=glocale):
|
||||
"""
|
||||
@@ -1113,7 +1132,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_citation_handles(self, sort_handles=False, locale=glocale):
|
||||
"""
|
||||
@@ -1154,7 +1173,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
if not self.db_is_open:
|
||||
LOG.debug("database is closed")
|
||||
LOG.warning("handle %s does not exist in the dummy database", handle)
|
||||
raise HandleError('Handle %s not found' % handle)
|
||||
raise HandleError("Handle %s not found" % handle)
|
||||
|
||||
def get_tag_from_name(self, val):
|
||||
"""
|
||||
@@ -1437,11 +1456,17 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
LOG.debug("database is closed")
|
||||
return []
|
||||
|
||||
def load(self, name, callback=None, mode=None, force_schema_upgrade=False,
|
||||
def load(
|
||||
self,
|
||||
name,
|
||||
callback=None,
|
||||
mode=None,
|
||||
force_schema_upgrade=False,
|
||||
force_bsddb_upgrade=False,
|
||||
force_bsddb_downgrade=False,
|
||||
force_python_upgrade=False,
|
||||
update=True):
|
||||
update=True,
|
||||
):
|
||||
"""
|
||||
Open the specified database.
|
||||
"""
|
||||
@@ -1536,8 +1561,9 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
|
||||
"""
|
||||
LOG.warning("database is readonly")
|
||||
|
||||
def set_prefixes(self, person, media, family, source, citation,
|
||||
place, event, repository, note):
|
||||
def set_prefixes(
|
||||
self, person, media, family, source, citation, place, event, repository, note
|
||||
):
|
||||
"""
|
||||
Set the prefixes for the gramps ids for all gramps objects
|
||||
"""
|
||||
|
@@ -27,6 +27,7 @@
|
||||
# -------------------------------------------------------------------------
|
||||
from ..const import URL_WIKISTRING, URL_MANUAL_PAGE
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -35,13 +36,13 @@ _ = glocale.translation.gettext
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
URL_WIKI_START = '<a href="' + URL_WIKISTRING
|
||||
URL_MANUAL_START = URL_WIKI_START + URL_MANUAL_PAGE + '_-_Manage_Family_Trees'
|
||||
URL_MANUAL_START = URL_WIKI_START + URL_MANUAL_PAGE + "_-_Manage_Family_Trees"
|
||||
URL_BACKUP1_START = URL_WIKI_START + 'How_to_make_a_backup">'
|
||||
URL_BACKUP2_START = URL_MANUAL_START + '#Backing_up_a_Family_Tree">'
|
||||
URL_EXPORT_START = URL_MANUAL_START + '#Export_into_Gramps_formats">'
|
||||
|
||||
class DbException(Exception):
|
||||
|
||||
class DbException(Exception):
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -49,10 +50,12 @@ class DbException(Exception):
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class DbWriteFailure(Exception):
|
||||
"""
|
||||
Error used to indicate that a write to a database has failed.
|
||||
"""
|
||||
|
||||
def __init__(self, value, value2=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -64,11 +67,13 @@ class DbWriteFailure(Exception):
|
||||
def messages(self):
|
||||
return self.value, self.value2
|
||||
|
||||
|
||||
class DbTransactionCancel(Exception):
|
||||
"""
|
||||
Error used to indicate that a transaction needs to be canceled,
|
||||
for example becuase it is lengthy and the users requests so.
|
||||
"""
|
||||
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -76,11 +81,13 @@ class DbTransactionCancel(Exception):
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class DbVersionError(Exception):
|
||||
"""
|
||||
Error used to report that a file could not be read because it is written
|
||||
in an unsupported version of the file format.
|
||||
"""
|
||||
|
||||
def __init__(self, tree_vers, min_vers, max_vers):
|
||||
Exception.__init__(self)
|
||||
self.tree_vers = tree_vers
|
||||
@@ -88,22 +95,27 @@ class DbVersionError(Exception):
|
||||
self.max_vers = max_vers
|
||||
|
||||
def __str__(self):
|
||||
return _('The schema version is not supported by this version of '
|
||||
'Gramps.\n\n'
|
||||
'This Family Tree is schema version %(tree_vers)s, and this '
|
||||
'version of Gramps supports versions %(min_vers)s to '
|
||||
'%(max_vers)s\n\n'
|
||||
'Please upgrade to the corresponding version or use '
|
||||
'XML for porting data between different schema versions.') %\
|
||||
{'tree_vers': self.tree_vers,
|
||||
'min_vers': self.min_vers,
|
||||
'max_vers': self.max_vers}
|
||||
return _(
|
||||
"The schema version is not supported by this version of "
|
||||
"Gramps.\n\n"
|
||||
"This Family Tree is schema version %(tree_vers)s, and this "
|
||||
"version of Gramps supports versions %(min_vers)s to "
|
||||
"%(max_vers)s\n\n"
|
||||
"Please upgrade to the corresponding version or use "
|
||||
"XML for porting data between different schema versions."
|
||||
) % {
|
||||
"tree_vers": self.tree_vers,
|
||||
"min_vers": self.min_vers,
|
||||
"max_vers": self.max_vers,
|
||||
}
|
||||
|
||||
|
||||
class DbPythonError(Exception):
|
||||
"""
|
||||
Error used to report that a file could not be read because it is written
|
||||
in an unsupported version of the Python format.
|
||||
"""
|
||||
|
||||
def __init__(self, tree_vers, min_vers, max_vers):
|
||||
Exception.__init__(self)
|
||||
self.tree_vers = tree_vers
|
||||
@@ -111,16 +123,19 @@ class DbPythonError(Exception):
|
||||
self.max_vers = max_vers
|
||||
|
||||
def __str__(self):
|
||||
return _('The Python version is not supported by this version of '
|
||||
'Gramps.\n\n'
|
||||
'This Family Tree is Python version %(tree_vers)s, and this '
|
||||
'version of Gramps supports versions %(min_vers)s to '
|
||||
'%(max_vers)s\n\n'
|
||||
'Please upgrade to the corresponding version or use '
|
||||
'XML for porting data between different Python versions.') %\
|
||||
{'tree_vers': self.tree_vers,
|
||||
'min_vers': self.min_vers,
|
||||
'max_vers': self.max_vers}
|
||||
return _(
|
||||
"The Python version is not supported by this version of "
|
||||
"Gramps.\n\n"
|
||||
"This Family Tree is Python version %(tree_vers)s, and this "
|
||||
"version of Gramps supports versions %(min_vers)s to "
|
||||
"%(max_vers)s\n\n"
|
||||
"Please upgrade to the corresponding version or use "
|
||||
"XML for porting data between different Python versions."
|
||||
) % {
|
||||
"tree_vers": self.tree_vers,
|
||||
"min_vers": self.min_vers,
|
||||
"max_vers": self.max_vers,
|
||||
}
|
||||
|
||||
|
||||
class DbUpgradeRequiredError(Exception):
|
||||
@@ -128,84 +143,94 @@ class DbUpgradeRequiredError(Exception):
|
||||
Error used to report that a database needs to be upgraded before it can be
|
||||
used.
|
||||
"""
|
||||
|
||||
def __init__(self, oldschema, newschema):
|
||||
Exception.__init__(self)
|
||||
self.oldschema = oldschema
|
||||
self.newschema = newschema
|
||||
|
||||
def __str__(self):
|
||||
return _('The Family Tree you are trying to load is in the schema '
|
||||
'version %(oldschema)s format. This version of Gramps uses '
|
||||
'schema version %(newschema)s. Therefore you cannot load this '
|
||||
'Family Tree without upgrading the schema version of the '
|
||||
'Family Tree.\n\n'
|
||||
'If you upgrade then you won\'t be able to use the previous '
|
||||
'version of Gramps, even if you subsequently '
|
||||
'%(wiki_manual_backup_html_start)sbackup%(html_end)s or '
|
||||
'%(wiki_manual_export_html_start)sexport%(html_end)s '
|
||||
'your upgraded Family Tree.\n\n'
|
||||
'Upgrading is a difficult task which could irretrievably '
|
||||
'corrupt your Family Tree if it is interrupted or fails.\n\n'
|
||||
'If you have not already made a backup of your Family Tree, '
|
||||
'then you should start your %(bold_start)sold%(bold_end)s '
|
||||
'version of Gramps and '
|
||||
'%(wiki_backup_html_start)smake a backup%(html_end)s '
|
||||
'of your Family Tree.') % {
|
||||
'wiki_backup_html_start' : URL_BACKUP1_START ,
|
||||
'wiki_manual_backup_html_start' : URL_BACKUP2_START ,
|
||||
'wiki_manual_export_html_start' : URL_EXPORT_START ,
|
||||
'html_end' : '</a>' ,
|
||||
'bold_start' : '<b>' ,
|
||||
'bold_end' : '</b>' ,
|
||||
'oldschema' : self.oldschema,
|
||||
'newschema' : self.newschema }
|
||||
return _(
|
||||
"The Family Tree you are trying to load is in the schema "
|
||||
"version %(oldschema)s format. This version of Gramps uses "
|
||||
"schema version %(newschema)s. Therefore you cannot load this "
|
||||
"Family Tree without upgrading the schema version of the "
|
||||
"Family Tree.\n\n"
|
||||
"If you upgrade then you won't be able to use the previous "
|
||||
"version of Gramps, even if you subsequently "
|
||||
"%(wiki_manual_backup_html_start)sbackup%(html_end)s or "
|
||||
"%(wiki_manual_export_html_start)sexport%(html_end)s "
|
||||
"your upgraded Family Tree.\n\n"
|
||||
"Upgrading is a difficult task which could irretrievably "
|
||||
"corrupt your Family Tree if it is interrupted or fails.\n\n"
|
||||
"If you have not already made a backup of your Family Tree, "
|
||||
"then you should start your %(bold_start)sold%(bold_end)s "
|
||||
"version of Gramps and "
|
||||
"%(wiki_backup_html_start)smake a backup%(html_end)s "
|
||||
"of your Family Tree."
|
||||
) % {
|
||||
"wiki_backup_html_start": URL_BACKUP1_START,
|
||||
"wiki_manual_backup_html_start": URL_BACKUP2_START,
|
||||
"wiki_manual_export_html_start": URL_EXPORT_START,
|
||||
"html_end": "</a>",
|
||||
"bold_start": "<b>",
|
||||
"bold_end": "</b>",
|
||||
"oldschema": self.oldschema,
|
||||
"newschema": self.newschema,
|
||||
}
|
||||
|
||||
|
||||
class DbConnectionError(Exception):
|
||||
"""
|
||||
Error used to report that a database connection failed.
|
||||
"""
|
||||
|
||||
def __init__(self, msg, settings_file):
|
||||
Exception.__init__(self)
|
||||
self.msg = msg
|
||||
self.settings_file = settings_file
|
||||
|
||||
def __str__(self):
|
||||
return _('Database connection failed.\n\n'
|
||||
'%(message)s\n'
|
||||
'Please check your connection settings file:\n'
|
||||
'%(settings_file)s') % {
|
||||
'message': self.msg,
|
||||
'settings_file': self.settings_file}
|
||||
return _(
|
||||
"Database connection failed.\n\n"
|
||||
"%(message)s\n"
|
||||
"Please check your connection settings file:\n"
|
||||
"%(settings_file)s"
|
||||
) % {"message": self.msg, "settings_file": self.settings_file}
|
||||
|
||||
|
||||
class DbSupportedError(Exception):
|
||||
"""
|
||||
Error used to report that a database is no longer supported.
|
||||
"""
|
||||
|
||||
def __init__(self, msg):
|
||||
Exception.__init__(self)
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
return _('The Family Tree you are trying to load is in the %(dbtype)s '
|
||||
'database, which is no longer supported.\nTherefore you '
|
||||
'cannot load this Family Tree without upgrading.\n\n'
|
||||
'If you upgrade then you won\'t be able to use the previous '
|
||||
'version of Gramps, even if you subsequently '
|
||||
'%(wiki_manual_backup_html_start)sbackup%(html_end)s or '
|
||||
'%(wiki_manual_export_html_start)sexport%(html_end)s '
|
||||
'your upgraded Family Tree.\n\n'
|
||||
'You are strongly advised to backup your Family Tree.\n\n'
|
||||
'If you have not already made a backup of your Family Tree, '
|
||||
'then you should start your previous version of Gramps and '
|
||||
'%(wiki_backup_html_start)smake a backup%(html_end)s '
|
||||
'of your Family Tree.') % {
|
||||
'dbtype' : self.msg,
|
||||
'wiki_manual_backup_html_start' : URL_BACKUP2_START ,
|
||||
'wiki_manual_export_html_start' : URL_EXPORT_START ,
|
||||
'wiki_backup_html_start' : URL_BACKUP1_START ,
|
||||
'html_end' : '</a>'}
|
||||
return _(
|
||||
"The Family Tree you are trying to load is in the %(dbtype)s "
|
||||
"database, which is no longer supported.\nTherefore you "
|
||||
"cannot load this Family Tree without upgrading.\n\n"
|
||||
"If you upgrade then you won't be able to use the previous "
|
||||
"version of Gramps, even if you subsequently "
|
||||
"%(wiki_manual_backup_html_start)sbackup%(html_end)s or "
|
||||
"%(wiki_manual_export_html_start)sexport%(html_end)s "
|
||||
"your upgraded Family Tree.\n\n"
|
||||
"You are strongly advised to backup your Family Tree.\n\n"
|
||||
"If you have not already made a backup of your Family Tree, "
|
||||
"then you should start your previous version of Gramps and "
|
||||
"%(wiki_backup_html_start)smake a backup%(html_end)s "
|
||||
"of your Family Tree."
|
||||
) % {
|
||||
"dbtype": self.msg,
|
||||
"wiki_manual_backup_html_start": URL_BACKUP2_START,
|
||||
"wiki_manual_export_html_start": URL_EXPORT_START,
|
||||
"wiki_backup_html_start": URL_BACKUP1_START,
|
||||
"html_end": "</a>",
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
@@ -215,11 +240,8 @@ if __name__ == "__main__":
|
||||
"""
|
||||
import sys
|
||||
|
||||
print("\nDbVersionError:\n",
|
||||
DbVersionError('1.6.0', '1.5.0', '1.5.1'))
|
||||
print("\nDbUpgradeRequiredError:\n",
|
||||
DbUpgradeRequiredError('1.5.1', '1.6.0'))
|
||||
print("\nDbVersionError:\n", DbVersionError("1.6.0", "1.5.0", "1.5.1"))
|
||||
print("\nDbUpgradeRequiredError:\n", DbUpgradeRequiredError("1.5.1", "1.6.0"))
|
||||
sys.exit(0)
|
||||
|
||||
print("\nxxx:\n",
|
||||
xxx('4.8.30', '4.8.29'))
|
||||
print("\nxxx:\n", xxx("4.8.30", "4.8.29"))
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -55,8 +55,16 @@ class DbTxn(defaultdict):
|
||||
Define a group of database commits that define a single logical operation.
|
||||
"""
|
||||
|
||||
__slots__ = ('msg', 'commitdb', 'db', 'batch', 'first',
|
||||
'last', 'timestamp', '__dict__')
|
||||
__slots__ = (
|
||||
"msg",
|
||||
"commitdb",
|
||||
"db",
|
||||
"batch",
|
||||
"first",
|
||||
"last",
|
||||
"timestamp",
|
||||
"__dict__",
|
||||
)
|
||||
|
||||
def __enter__(self):
|
||||
"""
|
||||
@@ -81,10 +89,15 @@ class DbTxn(defaultdict):
|
||||
frame = inspect.currentframe()
|
||||
c_frame = frame.f_back
|
||||
c_code = c_frame.f_code
|
||||
_LOG.debug(" **** DbTxn %s exited. Called from file %s, "
|
||||
_LOG.debug(
|
||||
" **** DbTxn %s exited. Called from file %s, "
|
||||
"line %s, in %s **** %.2f seconds",
|
||||
hex(id(self)), c_code.co_filename, c_frame.f_lineno,
|
||||
c_code.co_name, elapsed_time)
|
||||
hex(id(self)),
|
||||
c_code.co_filename,
|
||||
c_frame.f_lineno,
|
||||
c_code.co_name,
|
||||
elapsed_time,
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
@@ -129,16 +142,20 @@ class DbTxn(defaultdict):
|
||||
# frame to get any real information. The test does not accurately
|
||||
# check this, but seems to be good enough for the current diagnostic
|
||||
# purposes.
|
||||
if os.path.split(caller_frame[1])[1] == "generic.py" and \
|
||||
caller_frame[3] == "__init__":
|
||||
if (
|
||||
os.path.split(caller_frame[1])[1] == "generic.py"
|
||||
and caller_frame[3] == "__init__"
|
||||
):
|
||||
caller_frame = inspect.stack()[2]
|
||||
_LOG.debug("%sDbTxn %s instantiated for '%s'. Called from file %s, "
|
||||
"line %s, in %s" %
|
||||
(("Batch " if batch else "",)+
|
||||
(hex(id(self)),)+
|
||||
(msg,)+
|
||||
(os.path.split(caller_frame[1])[1],)+
|
||||
(tuple(caller_frame[i] for i in range(2, 4)))
|
||||
_LOG.debug(
|
||||
"%sDbTxn %s instantiated for '%s'. Called from file %s, "
|
||||
"line %s, in %s"
|
||||
% (
|
||||
("Batch " if batch else "",)
|
||||
+ (hex(id(self)),)
|
||||
+ (msg,)
|
||||
+ (os.path.split(caller_frame[1])[1],)
|
||||
+ (tuple(caller_frame[i] for i in range(2, 4)))
|
||||
)
|
||||
)
|
||||
defaultdict.__init__(self, list, {})
|
||||
@@ -176,12 +193,13 @@ class DbTxn(defaultdict):
|
||||
data is the tuple returned by the object's serialize method.
|
||||
"""
|
||||
self.last = self.commitdb.append(
|
||||
pickle.dumps((obj_type, trans_type, handle, old_data, new_data), 1))
|
||||
pickle.dumps((obj_type, trans_type, handle, old_data, new_data), 1)
|
||||
)
|
||||
if self.last is None:
|
||||
self.last = len(self.commitdb) - 1
|
||||
if self.first is None:
|
||||
self.first = self.last
|
||||
_LOG.debug('added to trans: %d %d %s' % (obj_type, trans_type, handle))
|
||||
_LOG.debug("added to trans: %d %d %s" % (obj_type, trans_type, handle))
|
||||
self[(obj_type, trans_type)] += [(handle, new_data)]
|
||||
return
|
||||
|
||||
|
@@ -26,13 +26,14 @@ from abc import ABCMeta, abstractmethod
|
||||
import time
|
||||
from collections import deque
|
||||
|
||||
|
||||
class DbUndo(metaclass=ABCMeta):
|
||||
"""
|
||||
Base class for the Gramps undo/redo manager. Needs to be subclassed
|
||||
for use with a real backend.
|
||||
"""
|
||||
|
||||
__slots__ = ('undodb', 'db', 'undo_history_timestamp', 'undoq', 'redoq')
|
||||
__slots__ = ("undodb", "db", "undo_history_timestamp", "undoq", "redoq")
|
||||
|
||||
def __init__(self, db):
|
||||
"""
|
||||
@@ -109,13 +110,11 @@ class DbUndo(metaclass=ABCMeta):
|
||||
|
||||
@abstractmethod
|
||||
def _redo(self, update_history):
|
||||
"""
|
||||
"""
|
||||
""" """
|
||||
|
||||
@abstractmethod
|
||||
def _undo(self, update_history):
|
||||
"""
|
||||
"""
|
||||
""" """
|
||||
|
||||
def commit(self, txn, msg):
|
||||
"""
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@ from ..constfunc import win, get_env_var
|
||||
from ..config import config
|
||||
from .dbconst import DBLOGNAME, DBLOCKFN, DBBACKEND
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -52,6 +53,7 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
_LOG = logging.getLogger(DBLOGNAME)
|
||||
|
||||
|
||||
def make_database(plugin_id):
|
||||
"""
|
||||
Make a database, given a plugin id.
|
||||
@@ -73,19 +75,26 @@ def make_database(plugin_id):
|
||||
db = database()
|
||||
if __debug__ and _LOG.isEnabledFor(logging.DEBUG):
|
||||
import inspect
|
||||
|
||||
frame = inspect.currentframe()
|
||||
c_frame = frame.f_back
|
||||
c_code = c_frame.f_code
|
||||
_LOG.debug("Database class instance created Class:%s instance:%s. "
|
||||
_LOG.debug(
|
||||
"Database class instance created Class:%s instance:%s. "
|
||||
"Called from File %s, line %s, in %s",
|
||||
db.__class__.__name__, hex(id(db)), c_code.co_filename,
|
||||
c_frame.f_lineno, c_code.co_name)
|
||||
db.__class__.__name__,
|
||||
hex(id(db)),
|
||||
c_code.co_filename,
|
||||
c_frame.f_lineno,
|
||||
c_code.co_name,
|
||||
)
|
||||
return db
|
||||
else:
|
||||
raise Exception("can't load database backend: '%s'" % plugin_id)
|
||||
else:
|
||||
raise Exception("no such database backend: '%s'" % plugin_id)
|
||||
|
||||
|
||||
def open_database(dbname, force_unlock=False, callback=None):
|
||||
"""
|
||||
Open a database by name and return the database.
|
||||
@@ -99,16 +108,17 @@ def open_database(dbname, force_unlock=False, callback=None):
|
||||
database.load(dbpath, callback=callback)
|
||||
return database
|
||||
|
||||
|
||||
def lookup_family_tree(dbname):
|
||||
"""
|
||||
Find a Family Tree given its name, and return properties.
|
||||
"""
|
||||
dbdir = os.path.expanduser(config.get('database.path'))
|
||||
dbdir = os.path.expanduser(config.get("database.path"))
|
||||
for dpath in os.listdir(dbdir):
|
||||
dirpath = os.path.join(dbdir, dpath)
|
||||
path_name = os.path.join(dirpath, "name.txt")
|
||||
if os.path.isfile(path_name):
|
||||
with open(path_name, 'r', encoding='utf8') as file:
|
||||
with open(path_name, "r", encoding="utf8") as file:
|
||||
name = file.readline().strip()
|
||||
if dbname == name:
|
||||
locked = False
|
||||
@@ -116,7 +126,7 @@ def lookup_family_tree(dbname):
|
||||
backend = get_dbid_from_path(dirpath)
|
||||
try:
|
||||
fname = os.path.join(dirpath, "lock")
|
||||
with open(fname, 'r', encoding='utf8') as ifile:
|
||||
with open(fname, "r", encoding="utf8") as ifile:
|
||||
locked_by = ifile.read().strip()
|
||||
locked = True
|
||||
except (OSError, IOError):
|
||||
@@ -124,6 +134,7 @@ def lookup_family_tree(dbname):
|
||||
return (dirpath, locked, locked_by, backend)
|
||||
return None
|
||||
|
||||
|
||||
def get_dbid_from_path(dirpath):
|
||||
"""
|
||||
Return a database backend from a directory path.
|
||||
@@ -135,6 +146,7 @@ def get_dbid_from_path(dirpath):
|
||||
dbid = file.read().strip()
|
||||
return dbid
|
||||
|
||||
|
||||
def import_as_dict(filename, user, skp_imp_adds=True):
|
||||
"""
|
||||
Import the filename into a InMemoryDB and return it.
|
||||
@@ -143,18 +155,20 @@ def import_as_dict(filename, user, skp_imp_adds=True):
|
||||
db.load(":memory:")
|
||||
db.set_feature("skip-import-additions", skp_imp_adds)
|
||||
db.set_prefixes(
|
||||
config.get('preferences.iprefix'),
|
||||
config.get('preferences.oprefix'),
|
||||
config.get('preferences.fprefix'),
|
||||
config.get('preferences.sprefix'),
|
||||
config.get('preferences.cprefix'),
|
||||
config.get('preferences.pprefix'),
|
||||
config.get('preferences.eprefix'),
|
||||
config.get('preferences.rprefix'),
|
||||
config.get('preferences.nprefix'))
|
||||
config.get("preferences.iprefix"),
|
||||
config.get("preferences.oprefix"),
|
||||
config.get("preferences.fprefix"),
|
||||
config.get("preferences.sprefix"),
|
||||
config.get("preferences.cprefix"),
|
||||
config.get("preferences.pprefix"),
|
||||
config.get("preferences.eprefix"),
|
||||
config.get("preferences.rprefix"),
|
||||
config.get("preferences.nprefix"),
|
||||
)
|
||||
status = import_from_filename(db, filename, user)
|
||||
return db if status else None
|
||||
|
||||
|
||||
def import_from_filename(db, filename, user):
|
||||
"""
|
||||
Import a file into a database.
|
||||
@@ -179,6 +193,7 @@ def import_from_filename(db, filename, user):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def find_surname_name(key, data):
|
||||
"""
|
||||
Creating a surname from raw name, to use for sort and index
|
||||
@@ -186,6 +201,7 @@ def find_surname_name(key, data):
|
||||
"""
|
||||
return __index_surname(data[5])
|
||||
|
||||
|
||||
def __index_surname(surn_list):
|
||||
"""
|
||||
All non pa/matronymic surnames are used in indexing.
|
||||
@@ -193,26 +209,36 @@ def __index_surname(surn_list):
|
||||
returns a byte string
|
||||
"""
|
||||
from ..lib import NameOriginType
|
||||
|
||||
if surn_list:
|
||||
surn = " ".join([x[0] for x in surn_list if not (x[3][0] in [
|
||||
NameOriginType.PATRONYMIC, NameOriginType.MATRONYMIC])])
|
||||
surn = " ".join(
|
||||
[
|
||||
x[0]
|
||||
for x in surn_list
|
||||
if not (
|
||||
x[3][0] in [NameOriginType.PATRONYMIC, NameOriginType.MATRONYMIC]
|
||||
)
|
||||
]
|
||||
)
|
||||
else:
|
||||
surn = ""
|
||||
return surn
|
||||
|
||||
|
||||
def clear_lock_file(name):
|
||||
try:
|
||||
os.unlink(os.path.join(name, DBLOCKFN))
|
||||
except OSError:
|
||||
return
|
||||
|
||||
|
||||
def write_lock_file(name):
|
||||
if not os.path.isdir(name):
|
||||
os.mkdir(name)
|
||||
with open(os.path.join(name, DBLOCKFN), "w", encoding='utf8') as f:
|
||||
with open(os.path.join(name, DBLOCKFN), "w", encoding="utf8") as f:
|
||||
if win():
|
||||
user = get_env_var('USERNAME')
|
||||
host = get_env_var('USERDOMAIN')
|
||||
user = get_env_var("USERNAME")
|
||||
host = get_env_var("USERDOMAIN")
|
||||
if not user:
|
||||
user = _("Unknown")
|
||||
else:
|
||||
@@ -223,7 +249,7 @@ def write_lock_file(name):
|
||||
except:
|
||||
# not win, so don't need get_env_var.
|
||||
# under cron getlogin() throws and there is no USER.
|
||||
user = os.environ.get('USER', 'noUSER')
|
||||
user = os.environ.get("USER", "noUSER")
|
||||
if host:
|
||||
text = "%s@%s" % (user, host)
|
||||
else:
|
||||
|
@@ -52,14 +52,15 @@ from .db.dummydb import DummyDb
|
||||
LOG = logging.getLogger(".dbstate")
|
||||
_LOG = logging.getLogger(DBLOGNAME)
|
||||
|
||||
|
||||
class DbState(Callback):
|
||||
"""
|
||||
Provide a class to encapsulate the state of the database.
|
||||
"""
|
||||
|
||||
__signals__ = {
|
||||
'database-changed' : ((DbReadBase, ProxyDbBase), ),
|
||||
'no-database' : None,
|
||||
"database-changed": ((DbReadBase, ProxyDbBase),),
|
||||
"no-database": None,
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
@@ -91,9 +92,14 @@ class DbState(Callback):
|
||||
frame = inspect.currentframe()
|
||||
c_frame = frame.f_back
|
||||
c_code = c_frame.f_code
|
||||
_LOG.debug('calling %s.%s()... from file %s, line %s in %s',
|
||||
class_name, func_name, c_code.co_filename,
|
||||
c_frame.f_lineno, c_code.co_name)
|
||||
_LOG.debug(
|
||||
"calling %s.%s()... from file %s, line %s in %s",
|
||||
class_name,
|
||||
func_name,
|
||||
c_code.co_filename,
|
||||
c_frame.f_lineno,
|
||||
c_code.co_name,
|
||||
)
|
||||
return (self.db is not None) and self.db.is_open()
|
||||
|
||||
def change_database(self, database):
|
||||
@@ -102,7 +108,7 @@ class DbState(Callback):
|
||||
Retained for backward compatibility.
|
||||
"""
|
||||
if database:
|
||||
self.emit('no-database', ())
|
||||
self.emit("no-database", ())
|
||||
if self.is_open():
|
||||
self.db.close()
|
||||
self.change_database_noclose(database)
|
||||
@@ -113,33 +119,34 @@ class DbState(Callback):
|
||||
"""
|
||||
self.db = database
|
||||
self.db.set_prefixes(
|
||||
config.get('preferences.iprefix'),
|
||||
config.get('preferences.oprefix'),
|
||||
config.get('preferences.fprefix'),
|
||||
config.get('preferences.sprefix'),
|
||||
config.get('preferences.cprefix'),
|
||||
config.get('preferences.pprefix'),
|
||||
config.get('preferences.eprefix'),
|
||||
config.get('preferences.rprefix'),
|
||||
config.get('preferences.nprefix'))
|
||||
config.get("preferences.iprefix"),
|
||||
config.get("preferences.oprefix"),
|
||||
config.get("preferences.fprefix"),
|
||||
config.get("preferences.sprefix"),
|
||||
config.get("preferences.cprefix"),
|
||||
config.get("preferences.pprefix"),
|
||||
config.get("preferences.eprefix"),
|
||||
config.get("preferences.rprefix"),
|
||||
config.get("preferences.nprefix"),
|
||||
)
|
||||
self.open = True
|
||||
|
||||
def signal_change(self):
|
||||
"""
|
||||
Emits the database-changed signal with the new database
|
||||
"""
|
||||
self.emit('database-changed', (self.db, ))
|
||||
self.emit("database-changed", (self.db,))
|
||||
|
||||
def no_database(self):
|
||||
"""
|
||||
Closes the database without a new database (except for the DummyDb)
|
||||
"""
|
||||
self.emit('no-database', ())
|
||||
self.emit("no-database", ())
|
||||
if self.is_open():
|
||||
self.db.close()
|
||||
self.db = DummyDb()
|
||||
self.open = False
|
||||
self.emit('database-changed', (self.db, ))
|
||||
self.emit("database-changed", (self.db,))
|
||||
|
||||
def get_database(self):
|
||||
"""
|
||||
@@ -168,7 +175,7 @@ class DbState(Callback):
|
||||
"""
|
||||
self.stack.append(self.db)
|
||||
self.db = proxy(self.db, *args, **kwargs)
|
||||
self.emit('database-changed', (self.db, ))
|
||||
self.emit("database-changed", (self.db,))
|
||||
|
||||
def pop_proxy(self):
|
||||
"""
|
||||
@@ -180,4 +187,4 @@ class DbState(Callback):
|
||||
>>> dbstate.pop_proxy()
|
||||
"""
|
||||
self.db = self.stack.pop()
|
||||
self.emit('database-changed', (self.db, ))
|
||||
self.emit("database-changed", (self.db,))
|
||||
|
@@ -18,4 +18,3 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -36,11 +36,13 @@ import xml.dom.minidom
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ..const import PLACE_FORMATS, GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
from ..config import config
|
||||
from ..utils.location import get_location_list
|
||||
from ..lib import PlaceType
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# PlaceFormat class
|
||||
@@ -61,17 +63,16 @@ class PlaceFormat:
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class PlaceDisplay:
|
||||
|
||||
def __init__(self):
|
||||
self.place_formats = []
|
||||
self.default_format = config.get('preferences.place-format')
|
||||
self.default_format = config.get("preferences.place-format")
|
||||
if os.path.exists(PLACE_FORMATS):
|
||||
try:
|
||||
self.load_formats()
|
||||
return
|
||||
except BaseException:
|
||||
print(_("Error in '%s' file: cannot load.") % PLACE_FORMATS)
|
||||
pf = PlaceFormat(_('Full'), ':', '', 0, False)
|
||||
pf = PlaceFormat(_("Full"), ":", "", 0, False)
|
||||
self.place_formats.append(pf)
|
||||
|
||||
def display_event(self, db, event, fmt=-1):
|
||||
@@ -87,11 +88,11 @@ class PlaceDisplay:
|
||||
def display(self, db, place, date=None, fmt=-1):
|
||||
if not place:
|
||||
return ""
|
||||
if not config.get('preferences.place-auto'):
|
||||
if not config.get("preferences.place-auto"):
|
||||
return place.title
|
||||
else:
|
||||
if fmt == -1:
|
||||
fmt = config.get('preferences.place-format')
|
||||
fmt = config.get("preferences.place-format")
|
||||
pf = self.place_formats[fmt]
|
||||
lang = pf.language
|
||||
all_places = get_location_list(db, place, date, lang)
|
||||
@@ -99,8 +100,8 @@ class PlaceDisplay:
|
||||
# Apply format string to place list
|
||||
index = _find_populated_place(all_places)
|
||||
places = []
|
||||
for slice in pf.levels.split(','):
|
||||
parts = slice.split(':')
|
||||
for slice in pf.levels.split(","):
|
||||
parts = slice.split(":")
|
||||
if len(parts) == 1:
|
||||
offset = _get_offset(parts[0], index)
|
||||
if offset is not None:
|
||||
@@ -126,11 +127,15 @@ class PlaceDisplay:
|
||||
idx = None
|
||||
if idx is not None and len(places) > idx + 1:
|
||||
if pf.street == 1:
|
||||
combined = (places[idx][0] + ' ' + places[idx+1][0],
|
||||
places[idx+1][1])
|
||||
combined = (
|
||||
places[idx][0] + " " + places[idx + 1][0],
|
||||
places[idx + 1][1],
|
||||
)
|
||||
else:
|
||||
combined = (places[idx+1][0] + ' ' + places[idx][0],
|
||||
places[idx+1][1])
|
||||
combined = (
|
||||
places[idx + 1][0] + " " + places[idx][0],
|
||||
places[idx + 1][1],
|
||||
)
|
||||
places = places[:idx] + [combined] + places[idx + 2 :]
|
||||
|
||||
names = [item[0] for item in places]
|
||||
@@ -148,14 +153,14 @@ class PlaceDisplay:
|
||||
|
||||
def load_formats(self):
|
||||
dom = xml.dom.minidom.parse(PLACE_FORMATS)
|
||||
top = dom.getElementsByTagName('place_formats')
|
||||
top = dom.getElementsByTagName("place_formats")
|
||||
|
||||
for fmt in top[0].getElementsByTagName('format'):
|
||||
name = fmt.attributes['name'].value
|
||||
levels = fmt.attributes['levels'].value
|
||||
language = fmt.attributes['language'].value
|
||||
street = int(fmt.attributes['street'].value)
|
||||
reverse = fmt.attributes['reverse'].value == 'True'
|
||||
for fmt in top[0].getElementsByTagName("format"):
|
||||
name = fmt.attributes["name"].value
|
||||
levels = fmt.attributes["levels"].value
|
||||
language = fmt.attributes["language"].value
|
||||
street = int(fmt.attributes["street"].value)
|
||||
reverse = fmt.attributes["reverse"].value == "True"
|
||||
pf = PlaceFormat(name, levels, language, street, reverse)
|
||||
self.place_formats.append(pf)
|
||||
|
||||
@@ -163,22 +168,22 @@ class PlaceDisplay:
|
||||
|
||||
def save_formats(self):
|
||||
doc = xml.dom.minidom.Document()
|
||||
place_formats = doc.createElement('place_formats')
|
||||
place_formats = doc.createElement("place_formats")
|
||||
doc.appendChild(place_formats)
|
||||
for fmt in self.place_formats:
|
||||
node = doc.createElement('format')
|
||||
node = doc.createElement("format")
|
||||
place_formats.appendChild(node)
|
||||
node.setAttribute('name', fmt.name)
|
||||
node.setAttribute('levels', fmt.levels)
|
||||
node.setAttribute('language', fmt.language)
|
||||
node.setAttribute('street', str(fmt.street))
|
||||
node.setAttribute('reverse', str(fmt.reverse))
|
||||
with open(PLACE_FORMATS, 'w', encoding='utf-8') as f_d:
|
||||
doc.writexml(f_d, addindent=' ', newl='\n', encoding='utf-8')
|
||||
node.setAttribute("name", fmt.name)
|
||||
node.setAttribute("levels", fmt.levels)
|
||||
node.setAttribute("language", fmt.language)
|
||||
node.setAttribute("street", str(fmt.street))
|
||||
node.setAttribute("reverse", str(fmt.reverse))
|
||||
with open(PLACE_FORMATS, "w", encoding="utf-8") as f_d:
|
||||
doc.writexml(f_d, addindent=" ", newl="\n", encoding="utf-8")
|
||||
|
||||
|
||||
def _get_offset(value, index):
|
||||
if index is not None and value.startswith('p'):
|
||||
if index is not None and value.startswith("p"):
|
||||
try:
|
||||
offset = int(value[1:])
|
||||
except ValueError:
|
||||
@@ -191,12 +196,18 @@ def _get_offset(value, index):
|
||||
offset = None
|
||||
return offset
|
||||
|
||||
|
||||
def _find_populated_place(places):
|
||||
populated_place = None
|
||||
for index, item in enumerate(places):
|
||||
if int(item[1]) in [PlaceType.HAMLET, PlaceType.VILLAGE,
|
||||
PlaceType.TOWN, PlaceType.CITY]:
|
||||
if int(item[1]) in [
|
||||
PlaceType.HAMLET,
|
||||
PlaceType.VILLAGE,
|
||||
PlaceType.TOWN,
|
||||
PlaceType.CITY,
|
||||
]:
|
||||
populated_place = index
|
||||
return populated_place
|
||||
|
||||
|
||||
displayer = PlaceDisplay()
|
||||
|
@@ -25,185 +25,231 @@ from gramps.gen.lib import Name
|
||||
|
||||
|
||||
class NameTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.name_display = NameDisplay()
|
||||
|
||||
def test_get_name_format_for_all_without_default_format(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=False, only_custom=False, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=False, only_custom=False, only_active=False
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(1, 'Surname, Given Suffix', '%l, %f %s', True),
|
||||
(2, 'Given Surname Suffix', '%f %l %s', True),
|
||||
(3, 'Patronymic, Given', '%y, %s %f', False),
|
||||
(4, 'Given', '%f', True),
|
||||
(5, 'Main Surnames, Given Patronymic Suffix Prefix', '%1m %2m %o, %f %1y %s %0m', True),
|
||||
(-2, 'SURNAME, Given Suffix (Call)', 'SURNAME, Given Suffix (Call)', False),
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(1, "Surname, Given Suffix", "%l, %f %s", True),
|
||||
(2, "Given Surname Suffix", "%f %l %s", True),
|
||||
(3, "Patronymic, Given", "%y, %s %f", False),
|
||||
(4, "Given", "%f", True),
|
||||
(
|
||||
5,
|
||||
"Main Surnames, Given Patronymic Suffix Prefix",
|
||||
"%1m %2m %o, %f %1y %s %0m",
|
||||
True,
|
||||
),
|
||||
(-2, "SURNAME, Given Suffix (Call)", "SURNAME, Given Suffix (Call)", False),
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True),
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_all_active_without_default_format(self):
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=False, only_custom=False, only_active=True)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=False, only_custom=False, only_active=True
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(1, 'Surname, Given Suffix', '%l, %f %s', True),
|
||||
(2, 'Given Surname Suffix', '%f %l %s', True),
|
||||
(4, 'Given', '%f', True),
|
||||
(5, 'Main Surnames, Given Patronymic Suffix Prefix', '%1m %2m %o, %f %1y %s %0m', True),
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(1, "Surname, Given Suffix", "%l, %f %s", True),
|
||||
(2, "Given Surname Suffix", "%f %l %s", True),
|
||||
(4, "Given", "%f", True),
|
||||
(
|
||||
5,
|
||||
"Main Surnames, Given Patronymic Suffix Prefix",
|
||||
"%1m %2m %o, %f %1y %s %0m",
|
||||
True,
|
||||
),
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True),
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_all_custom_formats_without_default_format(self):
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=False, only_custom=True, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=False, only_custom=True, only_active=False
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(-2, 'SURNAME, Given Suffix (Call)', 'SURNAME, Given Suffix (Call)', False),
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(-2, "SURNAME, Given Suffix (Call)", "SURNAME, Given Suffix (Call)", False),
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True),
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_active_custom_formats_without_default_format(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=False, only_custom=True, only_active=True)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=False, only_custom=True, only_active=True
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True)
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_all(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=False, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=False, only_active=False
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(0, 'Default format (defined by Gramps preferences)', '', True),
|
||||
(1, 'Surname, Given Suffix', '%l, %f %s', True),
|
||||
(2, 'Given Surname Suffix', '%f %l %s', True),
|
||||
(3, 'Patronymic, Given', '%y, %s %f', False),
|
||||
(4, 'Given', '%f', True),
|
||||
(5, 'Main Surnames, Given Patronymic Suffix Prefix', '%1m %2m %o, %f %1y %s %0m', True),
|
||||
(-2, 'SURNAME, Given Suffix (Call)', 'SURNAME, Given Suffix (Call)', False),
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(0, "Default format (defined by Gramps preferences)", "", True),
|
||||
(1, "Surname, Given Suffix", "%l, %f %s", True),
|
||||
(2, "Given Surname Suffix", "%f %l %s", True),
|
||||
(3, "Patronymic, Given", "%y, %s %f", False),
|
||||
(4, "Given", "%f", True),
|
||||
(
|
||||
5,
|
||||
"Main Surnames, Given Patronymic Suffix Prefix",
|
||||
"%1m %2m %o, %f %1y %s %0m",
|
||||
True,
|
||||
),
|
||||
(-2, "SURNAME, Given Suffix (Call)", "SURNAME, Given Suffix (Call)", False),
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True),
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_all_active(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=False, only_active=True)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=False, only_active=True
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(0, 'Default format (defined by Gramps preferences)', '', True),
|
||||
(1, 'Surname, Given Suffix', '%l, %f %s', True),
|
||||
(2, 'Given Surname Suffix', '%f %l %s', True),
|
||||
(4, 'Given', '%f', True),
|
||||
(5, 'Main Surnames, Given Patronymic Suffix Prefix', '%1m %2m %o, %f %1y %s %0m', True),
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(0, "Default format (defined by Gramps preferences)", "", True),
|
||||
(1, "Surname, Given Suffix", "%l, %f %s", True),
|
||||
(2, "Given Surname Suffix", "%f %l %s", True),
|
||||
(4, "Given", "%f", True),
|
||||
(
|
||||
5,
|
||||
"Main Surnames, Given Patronymic Suffix Prefix",
|
||||
"%1m %2m %o, %f %1y %s %0m",
|
||||
True,
|
||||
),
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True),
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_all_custom_formats(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=True, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=True, only_active=False
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(-2, 'SURNAME, Given Suffix (Call)', 'SURNAME, Given Suffix (Call)', False),
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(-2, "SURNAME, Given Suffix (Call)", "SURNAME, Given Suffix (Call)", False),
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True),
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_get_name_format_for_active_custom_formats(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=True, only_active=True)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=True, only_active=True
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(-1, 'Surname, Name|Common Suffix', 'Surname, Name|Common Suffix', True)
|
||||
(-1, "Surname, Name|Common Suffix", "Surname, Name|Common Suffix", True)
|
||||
]
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_clear_custom_formats(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
self.name_display.clear_custom_formats()
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=False, only_custom=True, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=False, only_custom=True, only_active=False
|
||||
)
|
||||
|
||||
self.assertEqual([], actual_name_format)
|
||||
|
||||
def test_do_not_clear_default_formats(self):
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_inactive_custom_name_format('SURNAME, Given Suffix (Call)')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.add_inactive_custom_name_format("SURNAME, Given Suffix (Call)")
|
||||
|
||||
self.name_display.clear_custom_formats()
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=False, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=False, only_active=False
|
||||
)
|
||||
|
||||
expected_name_format = [
|
||||
(0, 'Default format (defined by Gramps preferences)', '', True),
|
||||
(1, 'Surname, Given Suffix', '%l, %f %s', True),
|
||||
(2, 'Given Surname Suffix', '%f %l %s', True),
|
||||
(3, 'Patronymic, Given', '%y, %s %f', False),
|
||||
(4, 'Given', '%f', True),
|
||||
(5, 'Main Surnames, Given Patronymic Suffix Prefix', '%1m %2m %o, %f %1y %s %0m', True),
|
||||
(0, "Default format (defined by Gramps preferences)", "", True),
|
||||
(1, "Surname, Given Suffix", "%l, %f %s", True),
|
||||
(2, "Given Surname Suffix", "%f %l %s", True),
|
||||
(3, "Patronymic, Given", "%y, %s %f", False),
|
||||
(4, "Given", "%f", True),
|
||||
(
|
||||
5,
|
||||
"Main Surnames, Given Patronymic Suffix Prefix",
|
||||
"%1m %2m %o, %f %1y %s %0m",
|
||||
True,
|
||||
),
|
||||
]
|
||||
|
||||
self.assertEqual(expected_name_format, actual_name_format)
|
||||
|
||||
def test_set_name_format(self):
|
||||
standard_formats_overrides = [
|
||||
(0, "Default", '', True),
|
||||
(1, "Surname", '%l', True),
|
||||
(2, "Suffix", '%s', True),
|
||||
(3, "Given", '%s', False),
|
||||
(4, "Patronymic", '%y', True),
|
||||
(5, "Prefix", '%0m', True),
|
||||
(0, "Default", "", True),
|
||||
(1, "Surname", "%l", True),
|
||||
(2, "Suffix", "%s", True),
|
||||
(3, "Given", "%s", False),
|
||||
(4, "Patronymic", "%y", True),
|
||||
(5, "Prefix", "%0m", True),
|
||||
]
|
||||
|
||||
self.name_display.set_name_format(standard_formats_overrides)
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=False, only_active=False)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=False, only_active=False
|
||||
)
|
||||
|
||||
self.assertEqual(standard_formats_overrides, actual_name_format)
|
||||
|
||||
def test_add_existing_name_format(self):
|
||||
self.assertEqual(
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix'),
|
||||
self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix"),
|
||||
self.add_custom_name_format("Surname, Name|Common Suffix"),
|
||||
)
|
||||
|
||||
def test_delete_name_format(self):
|
||||
index = self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
index = self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.name_display.del_name_format(index)
|
||||
|
||||
actual_name_format = self.name_display.get_name_format(also_default=True, only_custom=True, only_active=True)
|
||||
actual_name_format = self.name_display.get_name_format(
|
||||
also_default=True, only_custom=True, only_active=True
|
||||
)
|
||||
|
||||
self.assertEqual([], actual_name_format)
|
||||
|
||||
def test_set_default_format_to_custom_format(self):
|
||||
index = self.add_custom_name_format('Surname, Name|Common Suffix')
|
||||
index = self.add_custom_name_format("Surname, Name|Common Suffix")
|
||||
self.name_display.set_default_format(index)
|
||||
self.assertEqual(index, self.name_display.get_default_format())
|
||||
|
||||
@@ -214,26 +260,26 @@ class NameTest(unittest.TestCase):
|
||||
|
||||
def test_display_name_with_valid_format(self):
|
||||
name = Name()
|
||||
name.set_first_name('William')
|
||||
name.set_call_name('Will')
|
||||
name.set_first_name("William")
|
||||
name.set_call_name("Will")
|
||||
name.set_display_as(4)
|
||||
|
||||
actual_display_name = self.name_display.display_name(name)
|
||||
|
||||
self.assertEqual('William', actual_display_name)
|
||||
self.assertEqual("William", actual_display_name)
|
||||
|
||||
def test_display_name_with_invalid_format(self):
|
||||
name = Name()
|
||||
name.set_first_name('William')
|
||||
name.set_call_name('Will')
|
||||
name.set_first_name("William")
|
||||
name.set_call_name("Will")
|
||||
name.set_display_as(-100)
|
||||
|
||||
display_name = self.name_display.display_name(name)
|
||||
|
||||
self.assertEqual(', William', display_name)
|
||||
self.assertEqual(", William", display_name)
|
||||
|
||||
def test_display_no_name(self):
|
||||
self.assertEqual('', self.name_display.display_name(None))
|
||||
self.assertEqual("", self.name_display.display_name(None))
|
||||
|
||||
def add_custom_name_format(self, name_format):
|
||||
return self.name_display.add_name_format(name_format, name_format)
|
||||
@@ -243,5 +289,5 @@ class NameTest(unittest.TestCase):
|
||||
self.name_display.set_format_inactive(index)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -22,8 +22,10 @@
|
||||
Provide Error objects
|
||||
"""
|
||||
|
||||
|
||||
class FilterError(Exception):
|
||||
"""Error used to report Filter errors"""
|
||||
|
||||
def __init__(self, value, value2=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -37,12 +39,14 @@ class FilterError(Exception):
|
||||
"Return the messages"
|
||||
return (self.value, self.value2)
|
||||
|
||||
|
||||
class DateError(Exception):
|
||||
"""Error used to report Date errors
|
||||
|
||||
Might have a .date attribute holding an invalid Date object
|
||||
that triggered the error.
|
||||
"""
|
||||
|
||||
def __init__(self, value=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -51,8 +55,10 @@ class DateError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class DatabaseError(Exception):
|
||||
"""Error used to report database errors"""
|
||||
|
||||
def __init__(self, value=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -61,8 +67,10 @@ class DatabaseError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class ReportError(Exception):
|
||||
"""Error used to report Report errors."""
|
||||
|
||||
def __init__(self, value, value2=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -76,8 +84,10 @@ class ReportError(Exception):
|
||||
"Return the messages"
|
||||
return (self.value, self.value2)
|
||||
|
||||
|
||||
class GedcomError(Exception):
|
||||
"""Error used to report GEDCOM errors"""
|
||||
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -86,8 +96,10 @@ class GedcomError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class GrampsImportError(Exception):
|
||||
"""Error used to report mistakes during import of files into Gramps"""
|
||||
|
||||
def __init__(self, value, value2=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -101,8 +113,10 @@ class GrampsImportError(Exception):
|
||||
"Return the messages"
|
||||
return (self.value, self.value2)
|
||||
|
||||
|
||||
class PluginError(Exception):
|
||||
"""Error used to report plugin errors"""
|
||||
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -111,8 +125,10 @@ class PluginError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class HandleError(Exception):
|
||||
"""Error used to report wrong database handle errors"""
|
||||
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -121,8 +137,10 @@ class HandleError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class WindowActiveError(Exception):
|
||||
"""Error used to report that the request window is already displayed."""
|
||||
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
@@ -131,6 +149,7 @@ class WindowActiveError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class UnavailableError(Exception):
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
@@ -140,14 +159,18 @@ class UnavailableError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class MaskError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ValidationError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DbError(Exception):
|
||||
"""Error used to report BerkeleyDB errors."""
|
||||
|
||||
def __init__(self, value):
|
||||
Exception.__init__(self)
|
||||
try:
|
||||
@@ -160,8 +183,10 @@ class DbError(Exception):
|
||||
"Return string representation"
|
||||
return self.value
|
||||
|
||||
|
||||
class MergeError(Exception):
|
||||
"""Error used to report merge errors"""
|
||||
|
||||
def __init__(self, value=""):
|
||||
Exception.__init__(self)
|
||||
self.value = value
|
||||
|
@@ -26,15 +26,21 @@ CustomFilters = None
|
||||
|
||||
from ..const import CUSTOM_FILTERS
|
||||
from ._filterlist import FilterList
|
||||
from ._genericfilter import (GenericFilter, GenericFilterFactory,
|
||||
DeferredFilter, DeferredFamilyFilter)
|
||||
from ._genericfilter import (
|
||||
GenericFilter,
|
||||
GenericFilterFactory,
|
||||
DeferredFilter,
|
||||
DeferredFamilyFilter,
|
||||
)
|
||||
from ._paramfilter import ParamFilter
|
||||
from ._searchfilter import SearchFilter, ExactSearchFilter
|
||||
|
||||
|
||||
def reload_custom_filters():
|
||||
global CustomFilters
|
||||
CustomFilters = FilterList(CUSTOM_FILTERS)
|
||||
CustomFilters.load()
|
||||
|
||||
|
||||
# if not CustomFilters: # moved to viewmanager
|
||||
# reload_custom_filters()
|
||||
|
@@ -39,6 +39,8 @@ from ..plug import BasePluginManager
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
PLUGMAN = BasePluginManager.get_instance()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# FilterList
|
||||
@@ -55,17 +57,16 @@ class FilterList:
|
||||
self.file = os.path.expanduser(file)
|
||||
self._cached = {}
|
||||
|
||||
def get_filters_dict(self, namespace='generic'):
|
||||
def get_filters_dict(self, namespace="generic"):
|
||||
"""
|
||||
This runs every for every item to be matched!
|
||||
"""
|
||||
if self._cached.get(namespace, None) is None:
|
||||
filters = self.get_filters(namespace)
|
||||
self._cached[namespace] = dict([(filt.name, filt) for filt
|
||||
in filters])
|
||||
self._cached[namespace] = dict([(filt.name, filt) for filt in filters])
|
||||
return self._cached[namespace]
|
||||
|
||||
def get_filters(self, namespace='generic'):
|
||||
def get_filters(self, namespace="generic"):
|
||||
"""
|
||||
This runs every for every item to be matched!
|
||||
"""
|
||||
@@ -73,7 +74,7 @@ class FilterList:
|
||||
filters = self.filter_namespaces[namespace]
|
||||
else:
|
||||
filters = []
|
||||
plugins = PLUGMAN.process_plugin_data('Filters')
|
||||
plugins = PLUGMAN.process_plugin_data("Filters")
|
||||
if plugins:
|
||||
plugin_filters = []
|
||||
try:
|
||||
@@ -88,6 +89,7 @@ class FilterList:
|
||||
plugin_filters.append(plug)
|
||||
except:
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
filters += plugin_filters
|
||||
return filters
|
||||
@@ -106,7 +108,7 @@ class FilterList:
|
||||
if os.path.isfile(self.file):
|
||||
parser = make_parser()
|
||||
parser.setContentHandler(FilterParser(self))
|
||||
with open(self.file, 'r', encoding='utf8') as the_file:
|
||||
with open(self.file, "r", encoding="utf8") as the_file:
|
||||
parser.parse(the_file)
|
||||
except (IOError, OSError):
|
||||
print("IO/OSError in _filterlist.py")
|
||||
@@ -116,23 +118,24 @@ class FilterList:
|
||||
def fix(self, line):
|
||||
"""sanitize the custom filter name, if needed"""
|
||||
new_line = line.strip()
|
||||
new_line = new_line.replace('&', '&')
|
||||
new_line = new_line.replace('>', '>')
|
||||
new_line = new_line.replace('<', '<')
|
||||
return new_line.replace('"', '"')
|
||||
new_line = new_line.replace("&", "&")
|
||||
new_line = new_line.replace(">", ">")
|
||||
new_line = new_line.replace("<", "<")
|
||||
return new_line.replace('"', """)
|
||||
|
||||
def save(self):
|
||||
"""save the list of custom filters"""
|
||||
with open(self.file, 'w', encoding='utf8') as file:
|
||||
file.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
||||
file.write('<filters>\n')
|
||||
with open(self.file, "w", encoding="utf8") as file:
|
||||
file.write('<?xml version="1.0" encoding="utf-8"?>\n')
|
||||
file.write("<filters>\n")
|
||||
for namespace in self.filter_namespaces:
|
||||
file.write(' <object type="%s">\n' % namespace)
|
||||
filter_list = self.filter_namespaces[namespace]
|
||||
sorted_filters = sorted([(filter.get_name(), filter)
|
||||
for filter in filter_list],
|
||||
key=lambda x: glocale.sort_key(x[0]))
|
||||
for (name, the_filter) in sorted_filters: # enable a diff
|
||||
sorted_filters = sorted(
|
||||
[(filter.get_name(), filter) for filter in filter_list],
|
||||
key=lambda x: glocale.sort_key(x[0]),
|
||||
)
|
||||
for name, the_filter in sorted_filters: # enable a diff
|
||||
file.write(' <filter name="%s"' % self.fix(name))
|
||||
file.write(' function="%s"' % the_filter.get_logical_op())
|
||||
if the_filter.invert:
|
||||
@@ -140,15 +143,18 @@ class FilterList:
|
||||
comment = the_filter.get_comment()
|
||||
if comment:
|
||||
file.write(' comment="%s"' % self.fix(comment))
|
||||
file.write('>\n')
|
||||
file.write(">\n")
|
||||
for rule in the_filter.get_rules():
|
||||
file.write(' <rule class="%s" use_regex="%s" use_case="%s">'
|
||||
'\n' % (rule.__class__.__name__,
|
||||
rule.use_regex, rule.use_case))
|
||||
file.write(
|
||||
' <rule class="%s" use_regex="%s" use_case="%s">'
|
||||
"\n"
|
||||
% (rule.__class__.__name__, rule.use_regex, rule.use_case)
|
||||
)
|
||||
for value in list(rule.values()):
|
||||
file.write(' <arg value="%s"/>'
|
||||
'\n' % self.fix(value))
|
||||
file.write(' </rule>\n')
|
||||
file.write(' </filter>\n')
|
||||
file.write(' </object>\n')
|
||||
file.write('</filters>\n')
|
||||
file.write(
|
||||
' <arg value="%s"/>' "\n" % self.fix(value)
|
||||
)
|
||||
file.write(" </rule>\n")
|
||||
file.write(" </filter>\n")
|
||||
file.write(" </object>\n")
|
||||
file.write("</filters>\n")
|
||||
|
@@ -25,6 +25,7 @@
|
||||
# -------------------------------------------------------------------------
|
||||
from xml.sax import handler
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -35,6 +36,7 @@ _ = glocale.translation.gettext
|
||||
from ._genericfilter import GenericFilterFactory
|
||||
from . import rules
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# FilterParser
|
||||
@@ -50,7 +52,7 @@ class FilterParser(handler.ContentHandler):
|
||||
self.r = None
|
||||
self.a = []
|
||||
self.cname = None
|
||||
self.namespace = 'Person'
|
||||
self.namespace = "Person"
|
||||
self.use_regex = False
|
||||
self.use_case = False
|
||||
|
||||
@@ -59,86 +61,101 @@ class FilterParser(handler.ContentHandler):
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
if tag == "object":
|
||||
if 'type' in attrs:
|
||||
self.namespace = attrs['type']
|
||||
if "type" in attrs:
|
||||
self.namespace = attrs["type"]
|
||||
else:
|
||||
self.namespace = "generic"
|
||||
if self.namespace == 'MediaObject':
|
||||
if self.namespace == "MediaObject":
|
||||
# deals with older custom filters
|
||||
self.namespace = 'Media'
|
||||
self.namespace = "Media"
|
||||
elif tag == "filter":
|
||||
self.f = GenericFilterFactory(self.namespace)()
|
||||
self.f.set_name(attrs['name'])
|
||||
if 'function' in attrs:
|
||||
self.f.set_name(attrs["name"])
|
||||
if "function" in attrs:
|
||||
try:
|
||||
if int(attrs['function']):
|
||||
op = 'or'
|
||||
if int(attrs["function"]):
|
||||
op = "or"
|
||||
else:
|
||||
op = 'and'
|
||||
op = "and"
|
||||
except ValueError:
|
||||
op = attrs['function']
|
||||
op = attrs["function"]
|
||||
self.f.set_logical_op(op)
|
||||
if 'invert' in attrs:
|
||||
self.f.set_invert(attrs['invert'])
|
||||
if 'comment' in attrs:
|
||||
self.f.set_comment(attrs['comment'])
|
||||
if "invert" in attrs:
|
||||
self.f.set_invert(attrs["invert"])
|
||||
if "comment" in attrs:
|
||||
self.f.set_comment(attrs["comment"])
|
||||
self.gfilter_list.add(self.namespace, self.f)
|
||||
elif tag == "rule":
|
||||
if 'use_regex' in attrs:
|
||||
self.use_regex = attrs['use_regex'] == 'True'
|
||||
if "use_regex" in attrs:
|
||||
self.use_regex = attrs["use_regex"] == "True"
|
||||
else:
|
||||
self.use_regex = False
|
||||
if 'use_case' in attrs:
|
||||
self.use_case = attrs['use_case'] == 'True'
|
||||
if "use_case" in attrs:
|
||||
self.use_case = attrs["use_case"] == "True"
|
||||
else:
|
||||
self.use_case = False
|
||||
save_name = attrs['class']
|
||||
save_name = attrs["class"]
|
||||
if save_name in old_names_2_class:
|
||||
self.r = old_names_2_class[save_name]
|
||||
else:
|
||||
try:
|
||||
# First try to use fully qualified name
|
||||
exec('self.r = %s' % save_name)
|
||||
exec("self.r = %s" % save_name)
|
||||
except (ImportError, NameError, AttributeError):
|
||||
# Now try to use name from rules.namespace
|
||||
mc_match = save_name.split('.')
|
||||
mc_match = save_name.split(".")
|
||||
last_name = mc_match[-1]
|
||||
try:
|
||||
exec('self.r = rules.%s.%s' % (
|
||||
self.namespace.lower(), last_name))
|
||||
exec(
|
||||
"self.r = rules.%s.%s" % (self.namespace.lower(), last_name)
|
||||
)
|
||||
except (ImportError, NameError, AttributeError):
|
||||
print("ERROR: Filter rule '%s' in "\
|
||||
"filter '%s' not found!"\
|
||||
% (save_name, self.f.get_name()))
|
||||
print(
|
||||
"ERROR: Filter rule '%s' in "
|
||||
"filter '%s' not found!" % (save_name, self.f.get_name())
|
||||
)
|
||||
self.r = None
|
||||
return
|
||||
self.a = []
|
||||
elif tag == "arg":
|
||||
self.a.append(attrs['value'])
|
||||
self.a.append(attrs["value"])
|
||||
|
||||
def endElement(self, tag):
|
||||
if tag == "rule" and self.r is not None:
|
||||
if len(self.r.labels) != len(self.a):
|
||||
self.__upgrade()
|
||||
if len(self.r.labels) < len(self.a):
|
||||
print(_("WARNING: Too many arguments in filter '%s'!\n"\
|
||||
"Trying to load with subset of arguments.") %\
|
||||
self.f.get_name())
|
||||
print(
|
||||
_(
|
||||
"WARNING: Too many arguments in filter '%s'!\n"
|
||||
"Trying to load with subset of arguments."
|
||||
)
|
||||
% self.f.get_name()
|
||||
)
|
||||
nargs = len(self.r.labels)
|
||||
rule = self.r(self.a[0:nargs], self.use_regex, self.use_case)
|
||||
self.f.add_rule(rule)
|
||||
else:
|
||||
if len(self.r.labels) > len(self.a):
|
||||
print(_("WARNING: Too few arguments in filter '%s'!\n" \
|
||||
" Trying to load anyway in the hope this "\
|
||||
"will be upgraded.") %\
|
||||
self.f.get_name())
|
||||
print(
|
||||
_(
|
||||
"WARNING: Too few arguments in filter '%s'!\n"
|
||||
" Trying to load anyway in the hope this "
|
||||
"will be upgraded."
|
||||
)
|
||||
% self.f.get_name()
|
||||
)
|
||||
try:
|
||||
rule = self.r(self.a, self.use_regex, self.use_case)
|
||||
except AssertionError as msg:
|
||||
print(msg)
|
||||
print(_("ERROR: filter %s could not be correctly loaded. "
|
||||
"Edit the filter!") % self.f.get_name())
|
||||
print(
|
||||
_(
|
||||
"ERROR: filter %s could not be correctly loaded. "
|
||||
"Edit the filter!"
|
||||
)
|
||||
% self.f.get_name()
|
||||
)
|
||||
return
|
||||
|
||||
self.f.add_rule(rule)
|
||||
@@ -152,31 +169,43 @@ class FilterParser(handler.ContentHandler):
|
||||
"""
|
||||
# HasPlace rule has extra locality field in v3.3
|
||||
if self.r == rules.place.HasPlace and len(self.a) == 8:
|
||||
self.a = self.a[0:2] + [''] + self.a[4:8] + [self.a[3]] + \
|
||||
[self.a[2]]
|
||||
self.a = self.a[0:2] + [""] + self.a[4:8] + [self.a[3]] + [self.a[2]]
|
||||
# HasNameOf rule has new fields for surnames in v3.3
|
||||
if self.r == rules.person.HasNameOf and len(self.a) == 7:
|
||||
self.a = self.a[0:2] + [self.a[3]] + [self.a[2]] + [self.a[6]] + \
|
||||
[''] + [self.a[4]] + ['', ''] + [self.a[5]] + \
|
||||
['', '0']
|
||||
self.a = (
|
||||
self.a[0:2]
|
||||
+ [self.a[3]]
|
||||
+ [self.a[2]]
|
||||
+ [self.a[6]]
|
||||
+ [""]
|
||||
+ [self.a[4]]
|
||||
+ ["", ""]
|
||||
+ [self.a[5]]
|
||||
+ ["", "0"]
|
||||
)
|
||||
# New regular expression code in v3.4
|
||||
if (self.r in (rules.person.HasNameOf,
|
||||
if (
|
||||
self.r
|
||||
in (
|
||||
rules.person.HasNameOf,
|
||||
rules.family.FatherHasNameOf,
|
||||
rules.family.MotherHasNameOf,
|
||||
rules.family.ChildHasNameOf)
|
||||
and len(self.a) == 12):
|
||||
self.use_regex = self.a[11] == '1'
|
||||
rules.family.ChildHasNameOf,
|
||||
)
|
||||
and len(self.a) == 12
|
||||
):
|
||||
self.use_regex = self.a[11] == "1"
|
||||
self.a = self.a[:11]
|
||||
if (self.r == rules.person.HasTextMatchingSubstringOf
|
||||
and len(self.a) == 3):
|
||||
self.use_regex = self.a[2] == '1'
|
||||
if self.r == rules.person.HasTextMatchingSubstringOf and len(self.a) == 3:
|
||||
self.use_regex = self.a[2] == "1"
|
||||
self.a = self.a[:2]
|
||||
# HasEvent rule has extra primary role field in v3.4.7
|
||||
if self.r == rules.person.HasEvent and len(self.a) == 5:
|
||||
self.a.append('1')
|
||||
self.a.append("1")
|
||||
# IsEnclosedBy rule has extra inclusive field in v4.2.4
|
||||
if self.r == rules.place.IsEnclosedBy and len(self.a) == 1:
|
||||
self.a.append('0')
|
||||
self.a.append("0")
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
@@ -197,23 +226,17 @@ old_names_2_class = {
|
||||
"Is a descendant of": rules.person.IsDescendantOf,
|
||||
"Is a descendant family member of": rules.person.IsDescendantFamilyOf,
|
||||
"Is a descendant of filter match": rules.person.IsDescendantOfFilterMatch,
|
||||
"Is a descendant of person not more than N generations away":
|
||||
rules.person.IsLessThanNthGenerationDescendantOf,
|
||||
"Is a descendant of person at least N generations away":
|
||||
rules.person.IsMoreThanNthGenerationDescendantOf,
|
||||
"Is an descendant of person at least N generations away" :
|
||||
rules.person.IsMoreThanNthGenerationDescendantOf,
|
||||
"Is a descendant of person not more than N generations away": rules.person.IsLessThanNthGenerationDescendantOf,
|
||||
"Is a descendant of person at least N generations away": rules.person.IsMoreThanNthGenerationDescendantOf,
|
||||
"Is an descendant of person at least N generations away": rules.person.IsMoreThanNthGenerationDescendantOf,
|
||||
"Is a child of filter match": rules.person.IsChildOfFilterMatch,
|
||||
"Is an ancestor of": rules.person.IsAncestorOf,
|
||||
"Is an ancestor of filter match": rules.person.IsAncestorOfFilterMatch,
|
||||
"Is an ancestor of person not more than N generations away" :
|
||||
rules.person.IsLessThanNthGenerationAncestorOf,
|
||||
"Is an ancestor of person at least N generations away":
|
||||
rules.person.IsMoreThanNthGenerationAncestorOf,
|
||||
"Is an ancestor of person not more than N generations away": rules.person.IsLessThanNthGenerationAncestorOf,
|
||||
"Is an ancestor of person at least N generations away": rules.person.IsMoreThanNthGenerationAncestorOf,
|
||||
"Is a parent of filter match": rules.person.IsParentOfFilterMatch,
|
||||
"Has a common ancestor with": rules.person.HasCommonAncestorWith,
|
||||
"Has a common ancestor with filter match" :
|
||||
rules.person.HasCommonAncestorWithFilterMatch,
|
||||
"Has a common ancestor with filter match": rules.person.HasCommonAncestorWithFilterMatch,
|
||||
"Is a female": rules.person.IsFemale,
|
||||
"Is a male": rules.person.IsMale,
|
||||
"Has the personal event": rules.person.HasEvent,
|
||||
@@ -224,10 +247,8 @@ old_names_2_class = {
|
||||
"Matches the filter named": rules.person.HasSourceOf,
|
||||
"Is spouse of filter match": rules.person.IsSpouseOfFilterMatch,
|
||||
"Is a sibling of filter match": rules.person.IsSiblingOfFilterMatch,
|
||||
"Relationship path between two people" :
|
||||
rules.person.RelationshipPathBetween,
|
||||
"Relationship paths between a person and a list of people" :
|
||||
rules.person.DeepRelationshipPathBetween,
|
||||
"Relationship path between two people": rules.person.RelationshipPathBetween,
|
||||
"Relationship paths between a person and a list of people": rules.person.DeepRelationshipPathBetween,
|
||||
"People who were adopted": rules.person.HaveAltFamilies,
|
||||
"People who have images": rules.person.HavePhotos,
|
||||
"People with children": rules.person.HaveChildren,
|
||||
|
@@ -40,8 +40,10 @@ from ..lib.media import Media
|
||||
from ..lib.note import Note
|
||||
from ..lib.tag import Tag
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# GenericFilter
|
||||
@@ -50,7 +52,7 @@ _ = glocale.translation.gettext
|
||||
class GenericFilter:
|
||||
"""Filter class that consists of several rules."""
|
||||
|
||||
logical_functions = ['or', 'and', 'xor', 'one']
|
||||
logical_functions = ["or", "and", "xor", "one"]
|
||||
|
||||
def __init__(self, source=None):
|
||||
if source:
|
||||
@@ -63,9 +65,9 @@ class GenericFilter:
|
||||
else:
|
||||
self.need_param = 0
|
||||
self.flist = []
|
||||
self.name = ''
|
||||
self.comment = ''
|
||||
self.logical_op = 'and'
|
||||
self.name = ""
|
||||
self.comment = ""
|
||||
self.logical_op = "and"
|
||||
self.invert = False
|
||||
|
||||
def match(self, handle, db):
|
||||
@@ -78,15 +80,15 @@ class GenericFilter:
|
||||
return False
|
||||
|
||||
def is_empty(self):
|
||||
return ((len(self.flist) == 0) or
|
||||
(len(self.flist) == 1 and ((self.flist[0].is_empty() and
|
||||
not self.invert))))
|
||||
return (len(self.flist) == 0) or (
|
||||
len(self.flist) == 1 and ((self.flist[0].is_empty() and not self.invert))
|
||||
)
|
||||
|
||||
def set_logical_op(self, val):
|
||||
if val in GenericFilter.logical_functions:
|
||||
self.logical_op = val
|
||||
else:
|
||||
self.logical_op = 'and'
|
||||
self.logical_op = "and"
|
||||
|
||||
def get_logical_op(self):
|
||||
return self.logical_op
|
||||
@@ -136,15 +138,12 @@ class GenericFilter:
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_people()
|
||||
|
||||
def check_func(self, db, id_list, task, user=None, tupleind=None,
|
||||
tree=False):
|
||||
def check_func(self, db, id_list, task, user=None, tupleind=None, tree=False):
|
||||
final_list = []
|
||||
if user:
|
||||
user.begin_progress(_('Filter'), _('Applying ...'),
|
||||
self.get_number(db))
|
||||
user.begin_progress(_("Filter"), _("Applying ..."), self.get_number(db))
|
||||
if id_list is None:
|
||||
with (self.get_tree_cursor(db) if tree else
|
||||
self.get_cursor(db)) as cursor:
|
||||
with self.get_tree_cursor(db) if tree else self.get_cursor(db) as cursor:
|
||||
for handle, data in cursor:
|
||||
person = self.make_obj()
|
||||
person.unserialize(data)
|
||||
@@ -171,11 +170,9 @@ class GenericFilter:
|
||||
final_list = []
|
||||
flist = self.flist
|
||||
if user:
|
||||
user.begin_progress(_('Filter'), _('Applying ...'),
|
||||
self.get_number(db))
|
||||
user.begin_progress(_("Filter"), _("Applying ..."), self.get_number(db))
|
||||
if id_list is None:
|
||||
with (self.get_tree_cursor(db) if tree else
|
||||
self.get_cursor(db)) as cursor:
|
||||
with self.get_tree_cursor(db) if tree else self.get_cursor(db) as cursor:
|
||||
for handle, data in cursor:
|
||||
person = self.make_obj()
|
||||
person.unserialize(data)
|
||||
@@ -201,16 +198,13 @@ class GenericFilter:
|
||||
return final_list
|
||||
|
||||
def check_or(self, db, id_list, user=None, tupleind=None, tree=False):
|
||||
return self.check_func(db, id_list, self.or_test, user, tupleind,
|
||||
tree=False)
|
||||
return self.check_func(db, id_list, self.or_test, user, tupleind, tree=False)
|
||||
|
||||
def check_one(self, db, id_list, user=None, tupleind=None, tree=False):
|
||||
return self.check_func(db, id_list, self.one_test, user, tupleind,
|
||||
tree=False)
|
||||
return self.check_func(db, id_list, self.one_test, user, tupleind, tree=False)
|
||||
|
||||
def check_xor(self, db, id_list, user=None, tupleind=None, tree=False):
|
||||
return self.check_func(db, id_list, self.xor_test, user, tupleind,
|
||||
tree=False)
|
||||
return self.check_func(db, id_list, self.xor_test, user, tupleind, tree=False)
|
||||
|
||||
def xor_test(self, db, person):
|
||||
test = False
|
||||
@@ -232,7 +226,7 @@ class GenericFilter:
|
||||
|
||||
def get_check_func(self):
|
||||
try:
|
||||
m = getattr(self, 'check_' + self.logical_op)
|
||||
m = getattr(self, "check_" + self.logical_op)
|
||||
except AttributeError:
|
||||
m = self.check_and
|
||||
return m
|
||||
@@ -265,8 +259,8 @@ class GenericFilter:
|
||||
rule.requestreset()
|
||||
return res
|
||||
|
||||
class GenericFamilyFilter(GenericFilter):
|
||||
|
||||
class GenericFamilyFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -282,8 +276,8 @@ class GenericFamilyFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_families()
|
||||
|
||||
class GenericEventFilter(GenericFilter):
|
||||
|
||||
class GenericEventFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -299,8 +293,8 @@ class GenericEventFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_events()
|
||||
|
||||
class GenericSourceFilter(GenericFilter):
|
||||
|
||||
class GenericSourceFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -316,8 +310,8 @@ class GenericSourceFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_sources()
|
||||
|
||||
class GenericCitationFilter(GenericFilter):
|
||||
|
||||
class GenericCitationFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -336,8 +330,8 @@ class GenericCitationFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_citations()
|
||||
|
||||
class GenericPlaceFilter(GenericFilter):
|
||||
|
||||
class GenericPlaceFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -356,8 +350,8 @@ class GenericPlaceFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_places()
|
||||
|
||||
class GenericMediaFilter(GenericFilter):
|
||||
|
||||
class GenericMediaFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -373,8 +367,8 @@ class GenericMediaFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_media()
|
||||
|
||||
class GenericRepoFilter(GenericFilter):
|
||||
|
||||
class GenericRepoFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -390,8 +384,8 @@ class GenericRepoFilter(GenericFilter):
|
||||
def get_number(self, db):
|
||||
return db.get_number_of_repositories()
|
||||
|
||||
class GenericNoteFilter(GenericFilter):
|
||||
|
||||
class GenericNoteFilter(GenericFilter):
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
|
||||
@@ -409,23 +403,23 @@ class GenericNoteFilter(GenericFilter):
|
||||
|
||||
|
||||
def GenericFilterFactory(namespace):
|
||||
if namespace == 'Person':
|
||||
if namespace == "Person":
|
||||
return GenericFilter
|
||||
elif namespace == 'Family':
|
||||
elif namespace == "Family":
|
||||
return GenericFamilyFilter
|
||||
elif namespace == 'Event':
|
||||
elif namespace == "Event":
|
||||
return GenericEventFilter
|
||||
elif namespace == 'Source':
|
||||
elif namespace == "Source":
|
||||
return GenericSourceFilter
|
||||
elif namespace == 'Citation':
|
||||
elif namespace == "Citation":
|
||||
return GenericCitationFilter
|
||||
elif namespace == 'Place':
|
||||
elif namespace == "Place":
|
||||
return GenericPlaceFilter
|
||||
elif namespace == 'Media':
|
||||
elif namespace == "Media":
|
||||
return GenericMediaFilter
|
||||
elif namespace == 'Repository':
|
||||
elif namespace == "Repository":
|
||||
return GenericRepoFilter
|
||||
elif namespace == 'Note':
|
||||
elif namespace == "Note":
|
||||
return GenericNoteFilter
|
||||
|
||||
|
||||
@@ -453,6 +447,7 @@ class DeferredFilter(GenericFilter):
|
||||
return self._(self.name_pair[0]) % self.name_pair[1]
|
||||
return self._(self.name_pair[0])
|
||||
|
||||
|
||||
class DeferredFamilyFilter(GenericFamilyFilter):
|
||||
"""
|
||||
Filter class allowing for deferred translation of the filter name
|
||||
|
@@ -30,13 +30,13 @@ Package providing filtering framework for Gramps.
|
||||
from ._genericfilter import GenericFilter
|
||||
from ..errors import FilterError
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# ParamFilter
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
class ParamFilter(GenericFilter):
|
||||
|
||||
def __init__(self, source=None):
|
||||
GenericFilter.__init__(self, source)
|
||||
self.need_param = 1
|
||||
@@ -58,8 +58,9 @@ class ParamFilter(GenericFilter):
|
||||
rule.set_list(new_list)
|
||||
for rule in self.flist:
|
||||
if rule.nrprepare > 0:
|
||||
raise FilterError('Custom filters can not twice be used' \
|
||||
' in a parameter filter')
|
||||
raise FilterError(
|
||||
"Custom filters can not twice be used" " in a parameter filter"
|
||||
)
|
||||
rule.requestprepare(db, user)
|
||||
result = GenericFilter.apply(self, db, id_list)
|
||||
for rule in self.flist:
|
||||
|
@@ -22,6 +22,7 @@
|
||||
Package providing filtering framework for Gramps.
|
||||
"""
|
||||
|
||||
|
||||
class SearchFilter:
|
||||
def __init__(self, func, text, invert):
|
||||
self.func = func
|
||||
@@ -31,10 +32,10 @@ class SearchFilter:
|
||||
def match(self, handle, db):
|
||||
return self.invert ^ (self.func(handle).upper().find(self.text) != -1)
|
||||
|
||||
|
||||
class ExactSearchFilter(SearchFilter):
|
||||
def __init__(self, func, text, invert):
|
||||
SearchFilter.__init__(self, func, text, invert)
|
||||
|
||||
def match(self, handle, db):
|
||||
return self.invert ^ (self.func(handle).upper() == self.text.strip())
|
||||
|
||||
|
@@ -81,6 +81,7 @@ from ._matcheseventfilterbase import MatchesEventFilterBase
|
||||
from ._matchessourceconfidencebase import MatchesSourceConfidenceBase
|
||||
from ._matchessourcefilterbase import MatchesSourceFilterBase
|
||||
from ._changedsincebase import ChangedSinceBase
|
||||
|
||||
# object filters
|
||||
from . import person
|
||||
from . import family
|
||||
|
@@ -36,8 +36,10 @@ import time
|
||||
from . import Rule
|
||||
from ...errors import FilterError
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# ChangedSince
|
||||
@@ -48,12 +50,14 @@ class ChangedSinceBase(Rule):
|
||||
Rule that checks for primary objects changed since a specific time.
|
||||
"""
|
||||
|
||||
labels = [ 'Changed after:', 'but before:' ]
|
||||
name = 'Objects changed after <date time>'
|
||||
description = "Matches object records changed after a specified " \
|
||||
"date/time (yyyy-mm-dd hh:mm:ss) or in range, if a second " \
|
||||
labels = ["Changed after:", "but before:"]
|
||||
name = "Objects changed after <date time>"
|
||||
description = (
|
||||
"Matches object records changed after a specified "
|
||||
"date/time (yyyy-mm-dd hh:mm:ss) or in range, if a second "
|
||||
"date/time is given."
|
||||
category = _('General filters')
|
||||
)
|
||||
category = _("General filters")
|
||||
|
||||
def add_time(self, date):
|
||||
if re.search(r"\d.*\s+\d{1,2}:\d{2}:\d{2}", date):
|
||||
@@ -80,9 +84,13 @@ class ChangedSinceBase(Rule):
|
||||
except ValueError:
|
||||
raise FilterError(
|
||||
_("Wrong format of date-time"),
|
||||
_("Only date-times in the iso format of yyyy-mm-dd "
|
||||
_(
|
||||
"Only date-times in the iso format of yyyy-mm-dd "
|
||||
"hh:mm:ss, where the time part is optional, are "
|
||||
"accepted. %s does not satisfy.") % iso_date_time)
|
||||
"accepted. %s does not satisfy."
|
||||
)
|
||||
% iso_date_time,
|
||||
)
|
||||
return time_sec
|
||||
|
||||
def prepare(self, db, user):
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -33,6 +34,7 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# Everyone
|
||||
@@ -41,9 +43,9 @@ from . import Rule
|
||||
class Everything(Rule):
|
||||
"""Match Everyone."""
|
||||
|
||||
name = 'Every object'
|
||||
category = _('General filters')
|
||||
description = 'Matches every object in the database'
|
||||
name = "Every object"
|
||||
category = _("General filters")
|
||||
description = "Matches every object in the database"
|
||||
|
||||
def is_empty(self):
|
||||
return True
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -46,11 +47,10 @@ class HasAttributeBase(Rule):
|
||||
Rule that checks for an object with a particular attribute.
|
||||
"""
|
||||
|
||||
labels = ['Attribute:', 'Value:']
|
||||
name = 'Objects with the <attribute>'
|
||||
description = "Matches objects with the given attribute " \
|
||||
"of a particular value"
|
||||
category = _('General filters')
|
||||
labels = ["Attribute:", "Value:"]
|
||||
name = "Objects with the <attribute>"
|
||||
description = "Matches objects with the given attribute " "of a particular value"
|
||||
category = _("General filters")
|
||||
allow_regex = True
|
||||
|
||||
def apply(self, db, obj):
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -35,6 +36,7 @@ _ = glocale.translation.gettext
|
||||
from ...datehandler import parser
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# HasCitation
|
||||
@@ -46,12 +48,10 @@ class HasCitationBase(Rule):
|
||||
First parameter is [Volume/page, Date, Confidence]
|
||||
"""
|
||||
|
||||
labels = [ _('Volume/Page:'),
|
||||
_('Date:'),
|
||||
_('Confidence:') ]
|
||||
name = _('Citations matching parameters')
|
||||
labels = [_("Volume/Page:"), _("Date:"), _("Confidence:")]
|
||||
name = _("Citations matching parameters")
|
||||
description = _("Matches citations with particular parameters")
|
||||
category = _('Citation/source filters')
|
||||
category = _("Citation/source filters")
|
||||
allow_regex = True
|
||||
|
||||
def prepare(self, db, user):
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -37,6 +38,7 @@ from . import Rule
|
||||
from ...utils.db import get_participant_from_event
|
||||
from ...display.place import displayer as place_displayer
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# HasEventBase
|
||||
@@ -45,15 +47,10 @@ from ...display.place import displayer as place_displayer
|
||||
class HasEventBase(Rule):
|
||||
"""Rule that checks for an event with a particular value."""
|
||||
|
||||
|
||||
labels = [ 'Event type:',
|
||||
'Date:',
|
||||
'Place:',
|
||||
'Description:',
|
||||
'Main Participants:' ]
|
||||
name = 'Events matching parameters'
|
||||
labels = ["Event type:", "Date:", "Place:", "Description:", "Main Participants:"]
|
||||
name = "Events matching parameters"
|
||||
description = "Matches events with particular parameters"
|
||||
category = _('Event filters')
|
||||
category = _("Event filters")
|
||||
allow_regex = True
|
||||
|
||||
def prepare(self, db, user):
|
||||
@@ -94,8 +91,9 @@ class HasEventBase(Rule):
|
||||
else:
|
||||
return False
|
||||
|
||||
if not self.match_substring(4,
|
||||
get_participant_from_event(db, event.get_handle(), all_=True)):
|
||||
if not self.match_substring(
|
||||
4, get_participant_from_event(db, event.get_handle(), all_=True)
|
||||
):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -36,22 +37,23 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# "People who have images"
|
||||
# -------------------------------------------------------------------------
|
||||
class HasGalleryBase(Rule):
|
||||
"""Objects who have Media Object"""
|
||||
|
||||
labels = [ _('Number of instances:'), _('Number must be:')]
|
||||
name = 'Object with <count> Media references'
|
||||
labels = [_("Number of instances:"), _("Number must be:")]
|
||||
name = "Object with <count> Media references"
|
||||
description = "Matches objects with certain number of items in the gallery"
|
||||
category = _('General filters')
|
||||
category = _("General filters")
|
||||
|
||||
def prepare(self, db, user):
|
||||
# things we want to do just once, not for every handle
|
||||
if self.list[1] == 'less than':
|
||||
if self.list[1] == "less than":
|
||||
self.count_type = 0
|
||||
elif self.list[1] == 'greater than':
|
||||
elif self.list[1] == "greater than":
|
||||
self.count_type = 2
|
||||
else:
|
||||
self.count_type = 1 # "equal to"
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -34,6 +35,7 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# HasIdOf
|
||||
@@ -42,10 +44,10 @@ from . import Rule
|
||||
class HasGrampsId(Rule):
|
||||
"""Rule that checks for an object with a specific Gramps ID."""
|
||||
|
||||
labels = [ _('ID:') ]
|
||||
name = 'Object with <Id>'
|
||||
labels = [_("ID:")]
|
||||
name = "Object with <Id>"
|
||||
description = "Matches objects with a specified Gramps ID"
|
||||
category = _('General filters')
|
||||
category = _("General filters")
|
||||
|
||||
def apply(self, db, obj):
|
||||
"""
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -37,6 +38,7 @@ _ = glocale.translation.gettext
|
||||
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
# HasLDSBase
|
||||
@@ -45,16 +47,16 @@ from . import Rule
|
||||
class HasLDSBase(Rule):
|
||||
"""Rule that checks for object with a LDS event"""
|
||||
|
||||
labels = [ _('Number of instances:'), _('Number must be:')]
|
||||
name = 'Objects with LDS events'
|
||||
labels = [_("Number of instances:"), _("Number must be:")]
|
||||
name = "Objects with LDS events"
|
||||
description = "Matches objects with LDS events"
|
||||
category = _('General filters')
|
||||
category = _("General filters")
|
||||
|
||||
def prepare(self, db, user):
|
||||
# things we want to do just once, not for every handle
|
||||
if self.list[1] == 'less than':
|
||||
if self.list[1] == "less than":
|
||||
self.count_type = 0
|
||||
elif self.list[1] == 'greater than':
|
||||
elif self.list[1] == "greater than":
|
||||
self.count_type = 2
|
||||
else:
|
||||
self.count_type = 1 # "equal to"
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -37,37 +38,37 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# "Objects having notes"
|
||||
# -------------------------------------------------------------------------
|
||||
class HasNoteBase(Rule):
|
||||
"""Objects having notes"""
|
||||
|
||||
labels = [ _('Number of instances:'), _('Number must be:')]
|
||||
name = 'Object with notes'
|
||||
labels = [_("Number of instances:"), _("Number must be:")]
|
||||
name = "Object with notes"
|
||||
description = "Matches objects that have a certain number of notes"
|
||||
category = _('General filters')
|
||||
category = _("General filters")
|
||||
|
||||
def __init__(self, arg, use_regex=False, use_case=False):
|
||||
# Upgrade from pre 3.1 HasNote filter, use defaults that correspond
|
||||
# Previous filter had 0 arguments
|
||||
if len(arg) == 0:
|
||||
Rule.__init__(self, ["0", 'greater than'], use_regex, use_case)
|
||||
Rule.__init__(self, ["0", "greater than"], use_regex, use_case)
|
||||
else:
|
||||
Rule.__init__(self, arg, use_regex, use_case)
|
||||
|
||||
def prepare(self, db, user):
|
||||
# things we want to do just once, not for every handle
|
||||
if self.list[1] == 'less than':
|
||||
if self.list[1] == "less than":
|
||||
self.count_type = 0
|
||||
elif self.list[1] == 'greater than':
|
||||
elif self.list[1] == "greater than":
|
||||
self.count_type = 2
|
||||
else:
|
||||
self.count_type = 1 # "equal to"
|
||||
|
||||
self.userSelectedCount = int(self.list[0])
|
||||
|
||||
|
||||
def apply(self, db, obj):
|
||||
count = len(obj.get_note_list())
|
||||
if self.count_type == 0: # "less than"
|
||||
|
@@ -25,6 +25,7 @@
|
||||
# -------------------------------------------------------------------------
|
||||
import re
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -34,17 +35,20 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Objects having notes that contain a substring or match a regular expression
|
||||
# -------------------------------------------------------------------------
|
||||
class HasNoteRegexBase(Rule):
|
||||
"""Objects having notes containing <text>."""
|
||||
|
||||
labels = [ _('Text:')]
|
||||
name = 'Objects having notes containing <text>'
|
||||
description = ("Matches objects whose notes contain a substring "
|
||||
"or match a regular expression")
|
||||
category = _('General filters')
|
||||
labels = [_("Text:")]
|
||||
name = "Objects having notes containing <text>"
|
||||
description = (
|
||||
"Matches objects whose notes contain a substring "
|
||||
"or match a regular expression"
|
||||
)
|
||||
category = _("General filters")
|
||||
allow_regex = True
|
||||
|
||||
def apply(self, db, person):
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#
|
||||
# -------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -33,17 +34,17 @@ _ = glocale.translation.gettext
|
||||
# -------------------------------------------------------------------------
|
||||
from . import Rule
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# "People having notes that contain a substring"
|
||||
# -------------------------------------------------------------------------
|
||||
class HasNoteSubstrBase(Rule):
|
||||
"""People having notes containing <substring>."""
|
||||
|
||||
labels = [ _('Substring:')]
|
||||
name = 'Objects having notes containing <substring>'
|
||||
description = "Matches objects whose notes contain text matching a " \
|
||||
"substring"
|
||||
category = _('General filters')
|
||||
labels = [_("Substring:")]
|
||||
name = "Objects having notes containing <substring>"
|
||||
description = "Matches objects whose notes contain text matching a " "substring"
|
||||
category = _("General filters")
|
||||
|
||||
def apply(self, db, person):
|
||||
notelist = person.get_note_list()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user