Compare commits

...

28 Commits

Author SHA1 Message Date
Jérôme Rapinat d080d15352 ready for alpha3
svn: r20964
2013-01-03 18:20:37 +00:00
Jérôme Rapinat f3c4314a89 new strings added for alpha3
svn: r20963
2013-01-03 18:15:08 +00:00
Jérôme Rapinat 2284694530 typo
svn: r20962
2013-01-03 17:48:03 +00:00
Benny Malengier 15edee3a26 support for upgrade of database on python3
svn: r20960
2013-01-03 15:33:50 +00:00
Benny Malengier d0e698ffac note model with wrong tag handle, gracefully continue
svn: r20958
2013-01-03 15:09:18 +00:00
Benny Malengier addfaa933f FIX MAJOR ERROR blocking upgrade of old family trees !
svn: r20956
2013-01-03 11:26:13 +00:00
Benny Malengier e2fc32c4c0 Fix exec problem in python 2 after previous change
svn: r20954
2013-01-03 11:19:05 +00:00
Mirko Leonhäuser 46e8d865b1 updated german translation
svn: r20953
2013-01-03 11:18:16 +00:00
Benny Malengier c208b91184 Recover gracefully from some errors in python3
svn: r20950
2013-01-03 10:28:51 +00:00
Benny Malengier ab6342af70 6258: Error during start of Gramps for certain LANG values
svn: r20948
2013-01-03 09:50:36 +00:00
Doug Blank 715ddbbab3 6274: Tried to use Charts View and receive 'NameError: global name 'gen' is not defined'
svn: r20947
2013-01-03 05:41:28 +00:00
Erik De Richter cc936c589b updated dutch translation
svn: r20945
2013-01-03 00:04:42 +00:00
Doug Blank f554ffd57d URL for Welcome Gramplet was still pointing to 3.3 manual
svn: r20942
2013-01-02 20:26:23 +00:00
John Ralls 46e9edaf59 [r20933]Bug 6268: Fix check_po for python3
svn: r20940
2013-01-02 17:27:39 +00:00
Doug Blank 29620a31ef 6249: Please, add a tag when importing. Adds preference, and tag on import for CSV, XML, and GEDCOM. Cleaned up preferences, and added 'GEDCOM' to add source on import text.
svn: r20939
2013-01-02 07:12:22 +00:00
Doug Blank ca2fd738d0 Wait for report to exist before trying to download
svn: r20937
2013-01-02 03:20:16 +00:00
Doug Blank 821caa8a5f 4719: Narweb Privacy issue, probably_alive uses spouse birth/death directly
svn: r20936
2013-01-02 03:02:25 +00:00
Doug Blank 3a45e70f54 New URL for gramps-addons
svn: r20931
2013-01-01 20:08:45 +00:00
Erik De Richter 89f6c7d83e updated dutch translation
svn: r20928
2013-01-01 16:45:31 +00:00
Benny Malengier ca73e01512 6266: loading plugin manager gives error
svn: r20926
2013-01-01 16:28:47 +00:00
Benny Malengier bfcecc646d 6265: can not make back up
svn: r20923
2013-01-01 11:15:45 +00:00
Jérôme Rapinat 77f9760504 6203: typo when interrupting a gramplet
svn: r20920
2013-01-01 07:15:23 +00:00
Doug Blank 3a93d03a4a Two different types of selection data
svn: r20918
2012-12-31 20:55:52 +00:00
Doug Blank 03851db458 Changes for gtk3 clipboard to work
svn: r20913
2012-12-31 18:57:02 +00:00
Nick Hall 9f87dfd54b Improve check to prevent overwriting const.py
svn: r20911
2012-12-31 18:18:20 +00:00
Benny Malengier 711e25e5bb 6258: Error during start of Gramps for certain LANG values
svn: r20908
2012-12-31 15:00:35 +00:00
Doug Blank f1eecb349d Add timestamp to downloads
svn: r20907
2012-12-31 14:58:45 +00:00
Jérôme Rapinat 04baa6b50f 6112: use get_indices method on TreePath for "old" Gtk version (e.g, 3.6.1)
svn: r20903
2012-12-31 13:39:32 +00:00
32 changed files with 10648 additions and 6770 deletions
+1 -1
View File
@@ -152,7 +152,7 @@ gramps(1) @VERSION@ gramps(1)
**Opération**
Si le premie argument de la ligne de commande ne commence pas par un
Si le premier argument de la ligne de commande ne commence pas par un
tiret (i.e. pas d'instruction), gramps va essayer d'ouvrir la base de
données avec le nom donné par le premier argument et démarrer une ses
sion interactive, en ignorant le reste de la ligne de commande.
+1 -1
View File
@@ -172,7 +172,7 @@ Imprime le numéro de version pour gramps puis quitte.
.UNINDENT
.TP
.B \fBOpération\fP
Si le premie argument de la ligne de commande ne commence pas par un
Si le premier argument de la ligne de commande ne commence pas par un
tiret (i.e. pas d\(aqinstruction), gramps va essayer d\(aqouvrir la base de
données avec le nom donné par le premier argument et démarrer une ses
sion interactive, en ignorant le reste de la ligne de commande.
+3 -1
View File
@@ -151,7 +151,7 @@ register('behavior.surname-guessing', 0)
register('behavior.use-tips', False)
register('behavior.welcome', 100)
register('behavior.web-search-url', 'http://google.com/#&q=%(text)s')
register('behavior.addons-url', "http://gramps-addons.svn.sourceforge.net/viewvc/gramps-addons/branches/gramps40/")
register('behavior.addons-url', "http://svn.code.sf.net/p/gramps-addons/code/branches/gramps40/")
register('export.proxy-order', [
["privacy", 0],
@@ -279,6 +279,8 @@ register('preferences.date-format', 0)
register('preferences.calendar-format-report', 0)
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')
+76 -28
View File
@@ -31,7 +31,7 @@ import logging
LOG = logging.getLogger(".citation")
from ..ggettext import gettext as _
from ..constfunc import cuni
from ..constfunc import cuni, UNITYPE
"""
methods to upgrade a database from version 13 to current version
@@ -144,7 +144,9 @@ def gramps_upgrade_16(self):
new_citation_list, note_list, change, tag_list,
private, person_ref_list)
with BSDDBTxn(self.env, self.person_map) as txn:
txn.put(str(handle), new_person)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_person)
self.update()
LOG.debug("%d persons upgraded with %d citations in %d seconds. " %
@@ -176,7 +178,9 @@ def gramps_upgrade_16(self):
change, date, tag_list, private)
LOG.debug(" upgrade new_media %s" % [new_media])
with BSDDBTxn(self.env, self.media_map) as txn:
txn.put(str(handle), new_media)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_media)
LOG.debug(" update ref map media %s" % [handle,
self.get_object_from_handle(handle) ])
self.update()
@@ -195,7 +199,7 @@ def gramps_upgrade_16(self):
start_time = time.time()
for place_handle in self.place_map.keys():
place = self.place_map[place_handle]
(handle, gramps_id, title, int, lat,
(handle, gramps_id, title, longi, lat,
main_loc, alt_loc, urls, media_list, source_list, note_list,
change, private) = place
if source_list:
@@ -208,11 +212,13 @@ def gramps_upgrade_16(self):
self, media_list)
if source_list or media_list:
new_place = (handle, gramps_id, title,
int, lat, main_loc, alt_loc, urls,
longi, lat, main_loc, alt_loc, urls,
media_list, new_citation_list, note_list,
change, private)
with BSDDBTxn(self.env, self.place_map) as txn:
txn.put(str(handle), new_place)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_place)
self.update()
LOG.debug("%d places upgraded with %d citations in %d seconds. " %
@@ -260,7 +266,9 @@ def gramps_upgrade_16(self):
attribute_list, lds_seal_list, new_citation_list,
note_list, change, tag_list, private)
with BSDDBTxn(self.env, self.family_map) as txn:
txn.put(str(handle), new_family)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_family)
self.update()
LOG.debug("%d familys upgraded with %d citations in %d seconds. " %
@@ -300,7 +308,9 @@ def gramps_upgrade_16(self):
attribute_list,
change, private)
with BSDDBTxn(self.env, self.event_map) as txn:
txn.put(str(handle), new_event)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_event)
t2 = time.time()
upgrade_time += t2 - t1
t3 = time.time()
@@ -332,7 +342,9 @@ def gramps_upgrade_16(self):
new_repository = (handle, gramps_id, the_type, name, note_list,
address_list, urls, change, private)
with BSDDBTxn(self.env, self.repository_map) as txn:
txn.put(str(handle), new_repository)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_repository)
self.update()
LOG.debug("%d repositorys upgraded with %d citations in %d seconds. " %
@@ -535,7 +547,9 @@ def convert_source_list_to_citation_list_16(self, source_list):
date, page, confidence, ref, note_list, new_media_list,
new_data_map, new_change, private)
with BSDDBTxn(self.env, self.citation_map) as txn:
txn.put(str(new_handle), new_citation)
if isinstance(new_handle, UNITYPE):
new_handle = new_handle.encode('utf-8')
txn.put(new_handle, new_citation)
self.cmap_index += 1
# # add backlinks for references from Citation to Source
# with BSDDBTxn(self.env) as txn:
@@ -621,7 +635,9 @@ def gramps_upgrade_15(self):
)
with BSDDBTxn(self.env, self.person_map) as txn:
txn.put(str(handle), new_person)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_person)
self.update()
#surname is now different, remove secondary index with names
_db = db.DB(self.env)
@@ -644,7 +660,9 @@ def gramps_upgrade_15(self):
new_family[13] = []
new_family = tuple(new_family)
with BSDDBTxn(self.env, self.family_map) as txn:
txn.put(str(handle), new_family)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_family)
self.update()
# ---------------------------------
@@ -661,7 +679,9 @@ def gramps_upgrade_15(self):
new_note[6] = []
new_note = tuple(new_note)
with BSDDBTxn(self.env, self.note_map) as txn:
txn.put(str(handle), new_note)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_note)
self.update()
# ---------------------------------
@@ -674,7 +694,9 @@ def gramps_upgrade_15(self):
new_media[10] = []
new_media = tuple(new_media)
with BSDDBTxn(self.env, self.media_map) as txn:
txn.put(str(handle), new_media)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_media)
self.update()
# ---------------------------------
@@ -688,7 +710,9 @@ def gramps_upgrade_15(self):
#new_event[11] = []
new_event = tuple(new_event)
with BSDDBTxn(self.env, self.event_map) as txn:
txn.put(str(handle), new_event)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_event)
self.update()
# ---------------------------------
@@ -704,7 +728,9 @@ def gramps_upgrade_15(self):
new_place = new_place[:12] + new_place[13:]
new_place = tuple(new_place)
with BSDDBTxn(self.env, self.place_map) as txn:
txn.put(str(handle), new_place)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_place)
self.update()
# ---------------------------------
@@ -717,7 +743,9 @@ def gramps_upgrade_15(self):
new_source = new_source[:11] + new_source[12:]
new_source = tuple(new_source)
with BSDDBTxn(self.env, self.source_map) as txn:
txn.put(str(handle), new_source)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_source)
self.update()
# ---------------------------------
@@ -731,7 +759,9 @@ def gramps_upgrade_15(self):
new_repository[5] = list(map(convert_address, new_repository[5]))
new_repository = tuple(new_repository)
with BSDDBTxn(self.env, self.repository_map) as txn:
txn.put(str(handle), new_repository)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_repository)
self.update()
# Bump up database version. Separate transaction to save metadata.
@@ -753,6 +783,8 @@ def convert_marker(self, marker_field):
tag.set_name(tag_name)
tag.set_priority(len(self.tags))
with BSDDBTxn(self.env, self.tag_map) as txn:
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, tag.serialize())
self.tags[tag_name] = handle
return self.tags[tag_name]
@@ -819,7 +851,9 @@ def gramps_upgrade_14(self):
new_note = (handle, gramps_id, styled_text, format, note_type,
change, marker, private)
with BSDDBTxn(self.env, self.note_map) as txn:
txn.put(str(handle), new_note)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_note)
self.update()
# ---------------------------------
@@ -839,7 +873,9 @@ def gramps_upgrade_14(self):
description, place, new_source_list, note_list,
new_media_list, new_attribute_list, change,marker,private)
with BSDDBTxn(self.env, self.event_map) as txn:
txn.put(str(handle), new_event)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_event)
self.update()
# ---------------------------------
@@ -921,7 +957,9 @@ def gramps_upgrade_14(self):
)
with BSDDBTxn(self.env, self.person_map) as txn:
txn.put(str(handle), new_person)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_person)
self.update()
# ---------------------------------
@@ -953,7 +991,9 @@ def gramps_upgrade_14(self):
change, marker, private)
with BSDDBTxn(self.env, self.family_map) as txn:
txn.put(str(handle), new_family)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_family)
self.update()
# ---------------------------------
@@ -978,7 +1018,9 @@ def gramps_upgrade_14(self):
new_address_list, urls, change, marker, private)
with BSDDBTxn(self.env, self.repository_map) as txn:
txn.put(str(handle), new_repository)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_repository)
self.update()
# ---------------------------------
@@ -996,7 +1038,9 @@ def gramps_upgrade_14(self):
new_date, marker, private)
with BSDDBTxn(self.env, self.media_map) as txn:
txn.put(str(handle), new_media)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_media)
self.update()
# ---------------------------------
@@ -1004,17 +1048,19 @@ def gramps_upgrade_14(self):
# ---------------------------------
for place_handle in self.place_map.keys():
place = self.place_map[place_handle]
(handle, gramps_id, title, int, lat,
(handle, gramps_id, title, longi, lat,
main_loc, alt_loc, urls, media_list, source_list, note_list,
change, marker, private) = place
new_media_list = new_media_list_14(media_list)
new_source_list = new_source_list_14(source_list)
new_place = (handle, gramps_id, title, int, lat,
new_place = (handle, gramps_id, title, longi, lat,
main_loc, alt_loc, urls, new_media_list,
new_source_list, note_list, change, marker, private)
with BSDDBTxn(self.env, self.place_map) as txn:
txn.put(str(handle), new_place)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_place)
self.update()
# ---------------------------------
@@ -1033,7 +1079,9 @@ def gramps_upgrade_14(self):
marker, private)
with BSDDBTxn(self.env, self.source_map) as txn:
txn.put(str(handle), new_source)
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_source)
self.update()
# Bump up database version. Separate transaction to save metadata.
+15 -3
View File
@@ -54,7 +54,10 @@ Specific symbols for parts of a name are defined:
#
#-------------------------------------------------------------------------
from ..ggettext import sgettext as _
import sys
import re
import logging
LOG = logging.getLogger(".gramps.gen")
#-------------------------------------------------------------------------
#
@@ -1047,8 +1050,17 @@ def fn(%s):
else:
return p + str + s
return cleanup_name("%s" %% (%s))""" % (args, new_fmt, ",".join(param))
exec(s)
return locals()['fn']
try:
exec(s) in globals(), locals()
return locals()['fn']
except:
LOG.error("\n" + 'Wrong name format string %s' % new_fmt
+"\n" + ("ERROR, Edit Name format in Preferences->Display to correct")
+"\n" + _('Wrong name format string %s') % new_fmt
+"\n" + ("ERROR, Edit Name format in Preferences->Display to correct")
)
def errfn(*arg):
return _("ERROR, Edit Name format in Preferences")
return errfn
displayer = NameDisplay()
+1 -1
View File
@@ -368,7 +368,7 @@ class Gramplet(object):
"""
from gi.repository import GObject
self._pause = True
if self._idle_id == 0:
if self._idle_id != 0:
GObject.source_remove(self._idle_id)
self._idle_id = 0
+6 -7
View File
@@ -43,14 +43,13 @@ from .. import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE, CATEGORY_WEB,
CATEGORY_BOOK, CATEGORY_GRAPHVIZ)
standalone_categories = {
CATEGORY_TEXT : _("Text Reports"),
CATEGORY_DRAW : _("Graphical Reports"),
CATEGORY_CODE : _("Code Generators"),
CATEGORY_WEB : _("Web Pages"),
CATEGORY_BOOK : _("Books"),
CATEGORY_GRAPHVIZ : _("Graphs"),
CATEGORY_TEXT : ("RepText", _("Text Reports")),
CATEGORY_DRAW : ("RepGraph", _("Graphical Reports")),
CATEGORY_CODE : ("RepCode", _("Code Generators")),
CATEGORY_WEB : ("RepWeb", _("Web Pages")),
CATEGORY_BOOK : ("RepBook", _("Books")),
CATEGORY_GRAPHVIZ : ("Graphs", _("Graphs")),
}
book_categories = {
CATEGORY_TEXT : _("Text"),
CATEGORY_DRAW : _("Graphics"),
+16 -4
View File
@@ -226,13 +226,25 @@ class ProbablyAlive(object):
if mother_handle == person.handle and father_handle:
father = self.db.get_person_from_handle(father_handle)
date1, date2, explain, other = self.probably_alive_range(father, is_spouse=True)
if date1 and date2:
return date1, date2, _("a spouse, ") + explain, other
if date1 and date1.get_year() != 0:
return (Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP),
Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE),
_("a spouse's birth-related date, ") + explain, other)
elif date2 and date2.get_year() != 0:
return (Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP - self.MAX_AGE_PROB_ALIVE),
Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP),
_("a spouse's death-related date, ") + explain, other)
elif father_handle == person.handle and mother_handle:
mother = self.db.get_person_from_handle(mother_handle)
date1, date2, explain, other = self.probably_alive_range(mother, is_spouse=True)
if date1 and date2:
return date1, date2, _("a spouse, ") + explain, other
if date1 and date1.get_year() != 0:
return (Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP),
Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE),
_("a spouse's birth-related date, ") + explain, other)
elif date2 and date2.get_year() != 0:
return (Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP - self.MAX_AGE_PROB_ALIVE),
Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP),
_("a spouse's death-related date, ") + explain, other)
# Let's check the family events and see if we find something
for ref in family.get_event_ref_list():
if ref:
+10
View File
@@ -187,6 +187,16 @@ if not sys.version_info >= MIN_PYTHON_VERSION :
'v3': MIN_PYTHON_VERSION[2]})
sys.exit(1)
if sys.version_info[0] >= 3:
#check if bsddb3 is installed
try:
import bsddb3
except ImportError:
logging.warning(_("\nYou don't have the python bsddb3 package installed."
" This package is needed to start Gramps.\n\n"
"Gramps will terminate now."))
sys.exit(1)
#-------------------------------------------------------------------------
#
# gramps libraries
+16 -5
View File
@@ -1163,7 +1163,10 @@ class ClipboardListView(object):
def object_drag_data_get(self, widget, context, sel_data, info, time):
tree_selection = widget.get_selection()
model, paths = tree_selection.get_selected_rows()
tgs = context.list_targets()
if hasattr(context, "targets"):
tgs = context.targets
else:
tgs = context.list_targets()
if len(paths) == 1:
path = paths[0]
node = model.get_iter(path)
@@ -1181,7 +1184,10 @@ class ClipboardListView(object):
time, title=None, value=None, dbid=None,
dbname=None):
model = widget.get_model()
sel_data = selection.get_data()
if hasattr(selection, "data"):
sel_data = selection.data
else:
sel_data = selection.get_data() # GtkSelectionData
# In Windows time is always zero. Until that is fixed, use the seconds
# of the local time to filter out double drops.
realTime = strftime("%S")
@@ -1212,7 +1218,10 @@ class ClipboardListView(object):
if dragtype in self._target_type_to_wrapper_class_map:
possible_wrappers = [dragtype]
else:
tgs = [atm.name() for atm in context.list_targets()]
if hasattr(context, "targets"):
tgs = context.targets
else:
tgs = [atm.name() for atm in context.list_targets()]
possible_wrappers = [target for target in tgs
if target in self._target_type_to_wrapper_class_map]
@@ -1246,7 +1255,8 @@ class ClipboardListView(object):
data = [o.__class__.DRAG_TARGET.drag_type, o, None,
o._type, o._value, o._dbid, o._dbname]
contains = model_contains(model, data)
if context.get_actions() != Gdk.DragAction.MOVE and contains:
if ((context.action if hasattr(context, "action") else context.get_actions())
!= Gdk.DragAction.MOVE) and contains:
continue
drop_info = widget.get_dest_row_at_pos(x, y)
if drop_info:
@@ -1263,7 +1273,8 @@ class ClipboardListView(object):
# FIXME: there is one bug here: if you multi-select and drop
# on self, then it moves the first, and copies the rest.
if context.get_actions() == Gdk.DragAction.MOVE:
if ((context.action if hasattr(context, "action") else context.get_actions()) ==
Gdk.DragAction.MOVE):
context.finish(True, True, time)
# remember time for double drop workaround.
+53 -18
View File
@@ -327,13 +327,18 @@ class ConfigureDialog(ManagedWindow):
config = self.__config
if not callback:
callback = self.update_entry
lwidget = BasicLabel("%s: " % label)
if label:
lwidget = BasicLabel("%s: " % label)
entry = Gtk.Entry()
entry.set_text(config.get(constant))
entry.connect('changed', callback, constant)
table.attach(lwidget, col_attach, col_attach+1, index, index+1, yoptions=0,
xoptions=Gtk.AttachOptions.FILL)
table.attach(entry, col_attach+1, col_attach+2, index, index+1, yoptions=0)
if label:
table.attach(lwidget, col_attach, col_attach+1, index, index+1, yoptions=0,
xoptions=Gtk.AttachOptions.FILL)
table.attach(entry, col_attach+1, col_attach+2, index, index+1, yoptions=0)
else:
table.attach(entry, col_attach, col_attach+1, index, index+1, yoptions=0)
return entry
def add_pos_int_entry(self, table, label, index, constant, callback=None,
config=None, col_attach=1):
@@ -1101,6 +1106,11 @@ class GrampsPreferences(ConfigureDialog):
config.set('behavior.do-not-show-previously-seen-updates',
bool(active))
def toggle_tag_on_import(self, obj):
active = obj.get_active()
config.set('preferences.tag-on-import', bool(active))
self.tag_format_entry.set_sensitive(bool(active))
def check_for_updates_changed(self, obj):
active = obj.get_active()
config.set('behavior.check-for-updates', active)
@@ -1153,27 +1163,49 @@ class GrampsPreferences(ConfigureDialog):
table.set_col_spacings(6)
table.set_row_spacings(6)
current_line = 0
self.add_checkbox(table,
_('Add default source on import'),
0, 'preferences.default-source')
_('Add default source on GEDCOM import'),
current_line, 'preferences.default-source')
current_line += 1
checkbutton = Gtk.CheckButton(_("Add tag on import"))
checkbutton.set_active(config.get('preferences.tag-on-import'))
checkbutton.connect("toggled", self.toggle_tag_on_import)
table.attach(checkbutton, 1, 2, current_line, current_line+1, yoptions=0)
self.tag_format_entry = self.add_entry(table, None, current_line,
'preferences.tag-on-import-format',
col_attach=2)
self.tag_format_entry.set_sensitive(config.get('preferences.tag-on-import'))
current_line += 1
self.add_checkbox(table,
_('Enable spelling checker'),
1, 'behavior.spellcheck')
current_line, 'behavior.spellcheck')
current_line += 1
self.add_checkbox(table,
_('Display Tip of the Day'),
2, 'behavior.use-tips')
current_line, 'behavior.use-tips')
current_line += 1
self.add_checkbox(table,
_('Remember last view displayed'),
3, 'preferences.use-last-view')
current_line, 'preferences.use-last-view')
current_line += 1
self.add_spinner(table,
_('Max generations for relationships'),
4, 'behavior.generation-depth', (5, 50), self.update_gendepth)
current_line, 'behavior.generation-depth', (5, 50), self.update_gendepth)
current_line += 1
self.path_entry = Gtk.Entry()
self.add_path_box(table,
_('Base path for relative media paths'),
5, self.path_entry, self.dbstate.db.get_mediapath(),
current_line, self.path_entry, self.dbstate.db.get_mediapath(),
self.set_mediapath, self.select_mediapath)
current_line += 1
# Check for updates:
obox = Gtk.ComboBoxText()
formats = [_("Never"),
@@ -1186,9 +1218,10 @@ class GrampsPreferences(ConfigureDialog):
obox.set_active(active)
obox.connect('changed', self.check_for_updates_changed)
lwidget = BasicLabel("%s: " % _('Check for updates'))
table.attach(lwidget, 1, 2, 6, 7, yoptions=0)
table.attach(obox, 2, 3, 6, 7, yoptions=0)
table.attach(lwidget, 1, 2, current_line, current_line+1, yoptions=0)
table.attach(obox, 2, 3, current_line, current_line+1, yoptions=0)
current_line += 1
self.whattype_box = Gtk.ComboBoxText()
formats = [_("Updated addons only"),
_("New addons only"),
@@ -1203,21 +1236,23 @@ class GrampsPreferences(ConfigureDialog):
self.whattype_box.set_active(0)
self.whattype_box.connect('changed', self.check_for_type_changed)
lwidget = BasicLabel("%s: " % _('What to check'))
table.attach(lwidget, 1, 2, 7, 8, yoptions=0)
table.attach(self.whattype_box, 2, 3, 7, 8, yoptions=0)
table.attach(lwidget, 1, 2, current_line, current_line+1, yoptions=0)
table.attach(self.whattype_box, 2, 3, current_line, current_line+1, yoptions=0)
self.add_entry(table, _('Where to check'), 8, 'behavior.addons-url', col_attach=1)
current_line += 1
self.add_entry(table, _('Where to check'), current_line, 'behavior.addons-url', col_attach=1)
current_line += 1
checkbutton = Gtk.CheckButton(
_("Do not ask about previously notified addons"))
checkbutton.set_active(config.get('behavior.do-not-show-previously-seen-updates'))
checkbutton.connect("toggled", self.toggle_hide_previous_addons)
table.attach(checkbutton, 0, 3, 9, 10, yoptions=0)
table.attach(checkbutton, 0, 3, current_line, current_line+1, yoptions=0)
button = Gtk.Button(_("Check now"))
button.connect("clicked", lambda obj: \
self.uistate.viewmanager.check_for_updates(force=True))
table.attach(button, 3, 4, 9, 10, yoptions=0)
table.attach(button, 3, 4, current_line, current_line+1, yoptions=0)
return _('General'), table
+8 -1
View File
@@ -51,7 +51,14 @@ except (ImportError, ValueError):
"pygobject version 3.3.2 or later.\n\n"
"Gramps will terminate now.")))
sys.exit(0)
try:
import cairo
except ImportError:
print((_("\ncairo python support not installed. Install cairo for your "
"version of python\n\n"
"Gramps will terminate now.")))
sys.exit(0)
#-------------------------------------------------------------------------
#
# Miscellaneous initialization
+1 -1
View File
@@ -216,7 +216,7 @@ class PluginDialog(ManagedWindow):
for key in key_list:
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
self.store.set(node, 0, key[1])
next = None
data.sort(key=lambda k:k.name)
for item in data:
+2 -1
View File
@@ -483,7 +483,8 @@ class PluginStatus(ManagedWindow):
'<span weight="bold" color="red">%s</span>' % _('Fail'),
i[0], str(i[1][1]), i[1], pdata.id, hiddenstr])
success_list = sorted(self.__pmgr.get_success_list())
success_list = sorted(self.__pmgr.get_success_list(),
key=lambda x: (x[0], x[2]._get_name()))
for i in success_list:
# i = (filename, module, pdata)
pdata = i[2]
+1 -2
View File
@@ -205,7 +205,7 @@ class ReportDialog(ManagedWindow):
def get_title(self):
"""The window title for this dialog"""
name = self.report_name
category = standalone_categories[self.category]
category = standalone_categories[self.category][1]
return "%s - %s - Gramps" % (name, category)
#------------------------------------------------------------------------
@@ -644,7 +644,6 @@ def report(dbstate, uistate, person, report_class, options_class,
task be in the format of task that takes a database and a person as
its arguments.
"""
if require_active and not person:
ErrorDialog(
_('Active person has not been set'),
+6 -7
View File
@@ -55,14 +55,13 @@ from gramps.gen.plug import (TOOL_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX,
#-------------------------------------------------------------------------
tool_categories = {
TOOL_DEBUG : _("Debug"),
TOOL_ANAL : _("Analysis and Exploration"),
TOOL_DBPROC : _("Family Tree Processing"),
TOOL_DBFIX : _("Family Tree Repair"),
TOOL_REVCTL : _("Revision Control"),
TOOL_UTILS : _("Utilities"),
TOOL_DEBUG : ("ToolDebug", _("Debug")),
TOOL_ANAL : ("ToolAnExp", _("Analysis and Exploration")),
TOOL_DBPROC : ("ToolProc", _("Family Tree Processing")),
TOOL_DBFIX : ("ToolRep", _("Family Tree Repair")),
TOOL_REVCTL : ("ToolRev", _("Revision Control")),
TOOL_UTILS : ("ToolUtil", _("Utilities")),
}
#-------------------------------------------------------------------------
#
# Tool
+6 -6
View File
@@ -120,7 +120,7 @@ if is_quartz():
else:
_GTKOSXAPPLICATION = False
_UNSUPPORTED = _("Unsupported")
_UNSUPPORTED = ("Unsupported", _("Unsupported"))
UIDEFAULT = '''<ui>
<menubar name="MenuBar">
@@ -250,7 +250,7 @@ def update_rows(model, path, iter, user_data):
"""
#path: (8,) iter: <GtkTreeIter at 0xbfa89fa0>
#path: (8, 0) iter: <GtkTreeIter at 0xbfa89f60>
if len(path) == 2:
if len(path.get_indices()) == 2:
row = model[path]
row[0] = user_data
model.row_changed(path, iter)
@@ -1804,9 +1804,9 @@ class ViewManager(CLIManager):
if item != _UNSUPPORTED)
for key in catlist:
new_key = key.replace(' ', '-')
new_key = key[0].replace(' ', '-')
ofile.write('<menu action="%s">' % new_key)
actions.append((new_key, None, key))
actions.append((new_key, None, key[1]))
pdatas = hash_data[key]
pdatas.sort(key=lambda x: x.name)
for pdata in pdatas:
@@ -1821,8 +1821,8 @@ class ViewManager(CLIManager):
# and the unsupported category at the end of the menu
if _UNSUPPORTED in hash_data:
ofile.write('<separator/>')
ofile.write('<menu action="%s">' % _UNSUPPORTED)
actions.append((_UNSUPPORTED, None, _UNSUPPORTED))
ofile.write('<menu action="%s">' % _UNSUPPORTED[0])
actions.append((_UNSUPPORTED[0], None, _UNSUPPORTED[1]))
pdatas = hash_data[_UNSUPPORTED]
pdatas.sort(key=lambda x: x.name)
for pdata in pdatas:
+5 -4
View File
@@ -146,10 +146,11 @@ class NoteModel(FlatBaseModel):
tag_priority = None
for handle in data[Note.POS_TAGS]:
tag = self.db.get_tag_from_handle(handle)
this_priority = tag.get_priority()
if tag_priority is None or this_priority < tag_priority:
tag_color = tag.get_color()
tag_priority = this_priority
if tag:
this_priority = tag.get_priority()
if tag_priority is None or this_priority < tag_priority:
tag_color = tag.get_color()
tag_priority = this_priority
return tag_color
def column_tags(self, data):
+6 -3
View File
@@ -39,7 +39,7 @@ import tarfile
if sys.version_info[0] < 3:
from cStringIO import StringIO
else:
from io import StringIO
import io
from gramps.gen.ggettext import gettext as _
#------------------------------------------------------------------------
@@ -63,7 +63,7 @@ from gi.repository import Gtk
#
#-------------------------------------------------------------------------
from gramps.gui.plug.export import WriterOptionBox
from exportxml import XmlWriter
from .exportxml import XmlWriter
from gramps.gen.utils.file import media_path_full, get_unicode_path_from_file_chooser
from gramps.gen.constfunc import win
@@ -214,7 +214,10 @@ class PackageWriter(object):
# select_clicked()
# Write XML now
g = StringIO()
if sys.version_info[0] < 3:
g = StringIO()
else:
g = io.BytesIO()
gfile = XmlWriter(self.db, self.user, 2)
gfile.write_handle(g)
tarinfo = tarfile.TarInfo('data.gramps')
+2 -2
View File
@@ -121,7 +121,7 @@ class GrampsXmlWriter(UpdateCallback):
self.status = None
def write(self,filename):
def write(self, filename):
"""
Write the database to the specified file.
"""
@@ -180,7 +180,7 @@ class GrampsXmlWriter(UpdateCallback):
if self.compress and _gzip_ok:
try:
g = gzip.GzipFile(mode="wb",fileobj=handle)
g = gzip.GzipFile(mode="wb", fileobj=handle)
except:
g = handle
else:
+1 -1
View File
@@ -111,7 +111,7 @@ class WelcomeGramplet(Gramplet):
welcome += linkst(_('Start with Genealogy and Gramps'),
_('http://www.gramps-project.org/wiki/index.php?title=Start_with_Genealogy')) + '\n'
welcome += linkst(_('Gramps online manual'),
_('http://www.gramps-project.org/wiki/index.php?title=Gramps_3.3_Wiki_Manual')) + '\n'
_('http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual')) + '\n'
welcome += linkst(_('Ask questions on gramps-users mailing list'),
_('http://gramps-project.org/contact/')) + '\n\n'
+31 -3
View File
@@ -50,7 +50,7 @@ LOG = logging.getLogger(".ImportCSV")
#-------------------------------------------------------------------------
from gramps.gen.ggettext import sgettext as _
from gramps.gen.ggettext import ngettext
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname, Tag
from gramps.gen.db import DbTxn
from gramps.gen.plug.utils import OpenFileOrStdin
from gramps.gen.datehandler import parser as _dp
@@ -59,6 +59,7 @@ from gramps.gen.utils.id import create_id
from gramps.gui.utils import ProgressMeter
from gramps.gen.lib.eventroletype import EventRoleType
from gramps.gen.constfunc import cuni, conv_to_unicode, STRTYPE
from gramps.gen.config import config
#-------------------------------------------------------------------------
#
@@ -95,6 +96,8 @@ class UTF8Recoder(object):
"Encode the next line of the file."
return self.reader.next().encode("utf-8")
next = __next__
class UnicodeReader(object):
"""
A CSV reader which will iterate over lines in the CSV file,
@@ -120,6 +123,8 @@ class UnicodeReader(object):
def __iter__(self):
return self
next = __next__
#-------------------------------------------------------------------------
#
# Support and main functions
@@ -141,7 +146,8 @@ def rd(line_number, row, col, key, default = None):
def importData(dbase, filename, user):
"""Function called by Gramps to import data on persons in CSV format."""
parser = CSVParser(dbase, user)
parser = CSVParser(dbase, user, (config.get('preferences.tag-on-import-format') if
config.get('preferences.tag-on-import') else None))
try:
with OpenFileOrStdin(filename, 'b') as filehandle:
parser.parse(filehandle)
@@ -157,7 +163,7 @@ def importData(dbase, filename, user):
#-------------------------------------------------------------------------
class CSVParser(object):
"""Class to read data in CSV format from a file object."""
def __init__(self, dbase, user):
def __init__(self, dbase, user, default_tag_format=None):
self.db = dbase
self.user = user
self.trans = None
@@ -235,6 +241,16 @@ class CSVParser(object):
for val in column2label[key]:
lab2col_dict.append((val, key))
self.label2column = dict(lab2col_dict)
if default_tag_format:
name = time.strftime(default_tag_format)
tag = self.db.get_tag_from_name(name)
if tag:
self.default_tag = tag
else:
self.default_tag = Tag()
self.default_tag.set_name(name)
else:
self.default_tag = None
def cleanup_column_name(self, column):
"""Handle column aliases for CSV spreadsheet import and SQL."""
@@ -313,6 +329,8 @@ class CSVParser(object):
tym = time.time()
self.db.disable_signals()
with DbTxn(_("CSV import"), self.db, batch=True) as self.trans:
if self.default_tag and self.default_tag.handle is None:
self.db.add_tag(self.default_tag, self.trans)
self._parse_csv_data(data, progress)
self.db.enable_signals()
self.db.request_rebuild()
@@ -432,6 +450,8 @@ class CSVParser(object):
new_note.handle = create_id()
new_note.type.set(NoteType.EVENT)
new_note.set(note)
if self.default_tag:
new_note.add_tag(self.default_tag.handle)
self.db.add_note(new_note, self.trans)
marriage.add_note(new_note.handle)
self.db.commit_event(marriage, self.trans)
@@ -506,6 +526,8 @@ class CSVParser(object):
new_note.handle = create_id()
new_note.type.set(NoteType.PERSON)
new_note.set(note)
if self.default_tag:
new_note.add_tag(self.default_tag.handle)
self.db.add_note(new_note, self.trans)
child.add_note(new_note.handle)
self.db.commit_person(child, self.trans)
@@ -592,6 +614,8 @@ class CSVParser(object):
new_note.handle = create_id()
new_note.type.set(NoteType.PERSON)
new_note.set(note)
if self.default_tag:
new_note.add_tag(self.default_tag.handle)
self.db.add_note(new_note, self.trans)
person.add_note(new_note.handle)
if grampsid is not None:
@@ -719,6 +743,8 @@ class CSVParser(object):
family.set_gramps_id(id_)
# add it:
family.set_handle(self.db.create_id())
if self.default_tag:
family.add_tag(self.default_tag.handle)
if husband:
family.set_father_handle(husband.get_handle())
husband.add_family_handle(family.get_handle())
@@ -775,6 +801,8 @@ class CSVParser(object):
def create_person(self):
""" Used to create a new person we know doesn't exist """
person = Person()
if self.default_tag:
person.add_tag(self.default_tag.handle)
self.db.add_person(person, self.trans)
self.indi_count += 1
return person
+4 -2
View File
@@ -115,8 +115,10 @@ def importData(database, filename, user):
stage_one.set_encoding(code_set)
ifile.seek(0)
gedparse = libgedcom.GedcomParser(
database, ifile, filename, user, stage_one,
config.get('preferences.default-source'))
database, ifile, filename, user, stage_one,
config.get('preferences.default-source'),
(config.get('preferences.tag-on-import-format') if
config.get('preferences.tag-on-import') else None))
except IOError as msg:
user.notify_error(_("%s could not be opened\n") % filename, str(msg))
return
+1
View File
@@ -94,6 +94,7 @@ def impData(database, name, user):
importer = importData
info = importer(database, imp_db_name, user)
newmediapath = database.get_mediapath()
#import of gpkg should not change media path as all media has new paths!
if not oldmediapath == newmediapath :
+27 -2
View File
@@ -67,6 +67,7 @@ from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
CITATION_KEY)
from gramps.gen.updatecallback import UpdateCallback
from gramps.gen.const import VERSION
from gramps.gen.config import config
#import gramps.plugins.lib.libgrampsxml
from gramps.plugins.lib import libgrampsxml
@@ -123,7 +124,9 @@ def importData(database, filename, user):
change = time.time()
else:
change = os.path.getmtime(filename)
parser = GrampsParser(database, user, change)
parser = GrampsParser(database, user, change,
(config.get('preferences.tag-on-import-format') if
config.get('preferences.tag-on-import') else None))
if filename != '-':
linecounter = LineParser(filename)
@@ -457,7 +460,7 @@ class ImportOpenFileContextManager:
#-------------------------------------------------------------------------
class GrampsParser(UpdateCallback):
def __init__(self, database, user, change):
def __init__(self, database, user, change, default_tag_format=None):
UpdateCallback.__init__(self, user.callback)
self.user = user
self.__gramps_version = 'unknown'
@@ -564,6 +567,17 @@ class GrampsParser(UpdateCallback):
self.eidswap = {}
self.import_handles = {}
if default_tag_format:
name = time.strftime(default_tag_format)
tag = self.db.get_tag_from_name(name)
if tag:
self.default_tag = tag
else:
self.default_tag = Tag()
self.default_tag.set_name(name)
else:
self.default_tag = None
self.func_map = {
#name part
"name": (self.start_name, self.stop_name),
@@ -895,6 +909,9 @@ class GrampsParser(UpdateCallback):
self.db.disable_signals()
if self.default_tag and self.default_tag.handle is None:
self.db.add_tag(self.default_tag, self.trans)
self.p = ParserCreate()
self.p.StartElementHandler = self.startElement
self.p.EndElementHandler = self.endElement
@@ -1384,6 +1401,8 @@ class GrampsParser(UpdateCallback):
self.person.change = int(attrs.get('change', self.change))
self.info.add('new-object', PERSON_KEY, self.person)
self.convert_marker(attrs, self.person)
if self.default_tag:
self.person.add_tag(self.default_tag.handle)
return self.person
def start_people(self, attrs):
@@ -1520,6 +1539,8 @@ class GrampsParser(UpdateCallback):
if 'type' in attrs:
self.family.type.set_from_xml_str(attrs["type"])
self.convert_marker(attrs, self.family)
if self.default_tag:
self.family.add_tag(self.default_tag.handle)
return self.family
def start_rel(self, attrs):
@@ -1833,6 +1854,8 @@ class GrampsParser(UpdateCallback):
#set correct change time
self.db.commit_note(self.note, self.trans, self.change)
self.info.add('new-object', NOTE_KEY, self.note)
if self.default_tag:
self.note.add_tag(self.default_tag.handle)
return self.note
def start_noteref(self, attrs):
@@ -2088,6 +2111,8 @@ class GrampsParser(UpdateCallback):
src = attrs.get("src", '')
if src:
self.object.path = src
if self.default_tag:
self.object.add_tag(self.default_tag.handle)
return self.object
def start_repo(self, attrs):
+33 -2
View File
@@ -127,7 +127,7 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
ChildRefType, Citation, Date, Event, EventRef, EventRoleType,
EventType, Family, FamilyRelType, LdsOrd, Location, MediaObject,
MediaRef, Name, NameType, Note, NoteType, Person, PersonRef, Place,
RepoRef, Repository, RepositoryType, Researcher, Source,
RepoRef, Repository, RepositoryType, Researcher, Source, Tag,
SourceMediaType, Surname, Url, UrlType)
from gramps.gen.db import DbTxn
from gramps.gen.updatecallback import UpdateCallback
@@ -1807,7 +1807,7 @@ class GedcomParser(UpdateCallback):
return name
def __init__(self, dbase, ifile, filename, user, stage_one,
default_source):
default_source, default_tag_format=None):
UpdateCallback.__init__(self, user.callback)
self.user = user
self.set_total(stage_one.get_line_count())
@@ -1835,6 +1835,16 @@ class GedcomParser(UpdateCallback):
self.def_src = Source()
fname = os.path.basename(filename).split('\\')[-1]
self.def_src.set_title(_("Import from GEDCOM (%s)") % fname)
if default_tag_format:
name = time.strftime(default_tag_format)
tag = self.dbase.get_tag_from_name(name)
if tag:
self.default_tag = tag
else:
self.default_tag = Tag()
self.default_tag.set_name(name)
else:
self.default_tag = None
self.dir_path = os.path.dirname(filename)
self.is_ftw = False
self.groups = None
@@ -2594,6 +2604,8 @@ class GedcomParser(UpdateCallback):
self.want_parse_warnings = True
if self.use_def_src:
self.dbase.add_source(self.def_src, self.trans)
if self.default_tag and self.default_tag.handle is None:
self.dbase.add_tag(self.default_tag, self.trans)
self.__parse_record()
self.__parse_trailer()
for title, handle in self.inline_srcs.items():
@@ -3318,6 +3330,9 @@ class GedcomParser(UpdateCallback):
# Add the default reference if no source has found
self.__add_default_source(person)
# Add a default tag if provided
self.__add_default_tag(person)
self.__check_msgs(_("INDI (individual) Gramps ID %s") %
person.get_gramps_id(), state, person)
# commit the person to the database
@@ -4579,6 +4594,9 @@ class GedcomParser(UpdateCallback):
# add default reference if no reference exists
self.__add_default_source(family)
# Add a default tag if provided
self.__add_default_tag(family)
self.__check_msgs(_("FAM (family) Gramps ID %s") % family.get_gramps_id(),
state, family)
# commit family to database
@@ -6118,6 +6136,9 @@ class GedcomParser(UpdateCallback):
# Add the default reference if no source has found
self.__add_default_source(media)
# Add a default tag if provided
self.__add_default_tag(media)
self.__check_msgs(_("OBJE (multi-media object) Gramps ID %s") %
media.get_gramps_id(), state, media)
# commit the person to the database
@@ -6931,6 +6952,9 @@ class GedcomParser(UpdateCallback):
self.__undefined)
state.msg += sub_state.msg
# Add a default tag if provided
self.__add_default_tag(new_note)
self.dbase.commit_note(new_note, self.trans, new_note.change)
obj.add_note(new_note.get_handle())
@@ -7255,6 +7279,13 @@ class GedcomParser(UpdateCallback):
self.dbase.add_citation(citation, self.trans)
obj.add_citation(citation.handle)
def __add_default_tag(self, obj):
"""
Add the default tag to the object.
"""
if self.default_tag:
obj.add_tag(self.default_tag.handle)
def __subm_name(self, line, state):
"""
@param line: The current line in GedLine format
+23 -10
View File
@@ -32,6 +32,7 @@ Each object can be operated on with the following actions:
import os
import sys
import time
if sys.version_info[0] < 3:
import cPickle as pickle
else:
@@ -171,6 +172,12 @@ def user_page(request, username=None):
else:
raise Http404(_("Requested page is not accessible."))
def timestamp():
"""
Construct a string of current time for filenames.
"""
return time.strftime("%Y-%m-%d:%H:%M:%S")
def send_file(request, filename, mimetype):
"""
Send a file through Django without loading the whole file into
@@ -215,17 +222,18 @@ def process_report_run(request, handle):
args[key] = value
#############################################################################
if report.report_type == "report":
filename = "/tmp/%s-%s.%s" % (str(profile.user.username), str(handle), args["off"])
filename = "/tmp/%s-%s-%s.%s" % (str(profile.user.username), str(handle), timestamp(), args["off"])
run_report(db, handle, of=filename, **args)
mimetype = 'application/%s' % args["off"]
elif report.report_type == "export":
filename = "/tmp/%s-%s.%s" % (str(profile.user.username), str(handle), args["off"])
filename = "/tmp/%s-%s-%s.%s" % (str(profile.user.username), str(handle), timestamp(), args["off"])
export_file(db, filename, gramps.cli.user.User()) # callback
mimetype = 'text/plain'
elif report.report_type == "import":
filename = download(args["i"], "/tmp/%s-%s.%s" % (str(profile.user.username),
str(handle),
args["iff"]))
filename = download(args["i"], "/tmp/%s-%s-%s.%s" % (str(profile.user.username),
str(handle),
timestamp(),
args["iff"]))
if filename is not None:
if True: # run in background, with error handling
import threading
@@ -248,12 +256,17 @@ def process_report_run(request, handle):
else:
make_message(request, "Invalid report type '%s'" % report.report_type)
return redirect("/report/")
if os.path.exists(filename):
return send_file(request, filename, mimetype)
# need to wait for the file to exist:
start = time.time()
while not os.path.exists(filename):
# but let's not wait forever:
if time.time() - start > 10: # after 10 seconds, give up!
context = RequestContext(request)
make_message(request, "Failed: '%s' is not found" % filename)
return redirect("/report/")
time.sleep(1)
return send_file(request, filename, mimetype)
else:
context = RequestContext(request)
make_message(request, "Failed: '%s' is not found" % filename)
return redirect("/report/")
# If failure, just fail for now:
context = RequestContext(request)
context["message"] = "You need to be logged in."
+436 -436
View File
@@ -41,558 +41,558 @@ all_coverage = {}
all_template_coverage = {}
def strip_quotes(st):
if len(st) >= 2 and st[0] == '"' and st[len(st)-1] == '"':
st = st.strip()[1:-1]
return st
if len(st) >= 2 and st[0] == '"' and st[len(st)-1] == '"':
st = st.strip()[1:-1]
return st
class CheckException( Exception ):
pass
pass
# This is a base class for all checks
class Check:
def __init__( self ):
self.msgs = []
def diag( self ):
if len( self.msgs ):
print
print self.diag_header
for m in self.msgs:
m.diag()
def summary( self ):
print "%-20s%d" % ( self.summary_text, len(self.msgs) )
def __init__( self ):
self.msgs = []
def diag( self ):
if len( self.msgs ):
print
print(self.diag_header)
for m in self.msgs:
m.diag()
def summary( self ):
print("%-20s%d" % ( self.summary_text, len(self.msgs) ))
class Check_fmt( Check ):
def __init__( self, fmt ):
Check.__init__( self )
self.diag_header = "-------- %s mismatches --------------" % fmt
self.summary_text = "%s mismatches:" % fmt
self.fmt = fmt
def __init__( self, fmt ):
Check.__init__( self )
self.diag_header = "-------- %s mismatches --------------" % fmt
self.summary_text = "%s mismatches:" % fmt
self.fmt = fmt
def __process( self, msg, msgid, msgstr ):
cnt1 = msgid.count( self.fmt )
cnt2 = msgstr.count( self.fmt )
if cnt1 != cnt2:
self.msgs.append( msg )
def __process( self, msg, msgid, msgstr ):
cnt1 = msgid.count( self.fmt )
cnt2 = msgstr.count( self.fmt )
if cnt1 != cnt2:
self.msgs.append( msg )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
class Check_named_fmt( Check ):
# A pattern to find all %()
find_named_fmt_pat = re.compile('% \( \w+ \) \d* \D', re.VERBOSE)
# A pattern to find all %()
find_named_fmt_pat = re.compile('% \( \w+ \) \d* \D', re.VERBOSE)
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- %() name mismatches --------------"
self.summary_text = "%() name mismatches:"
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- %() name mismatches --------------"
self.summary_text = "%() name mismatches:"
def __process( self, msg, msgid, msgstr ):
# Same number of named formats?
fmts1 = self.find_named_fmt_pat.findall( msgid )
fmts2 = self.find_named_fmt_pat.findall( msgstr )
if len( fmts1 ) != len( fmts2 ):
self.msgs.append( msg )
else:
# Do we have the same named formats?
fmts1.sort()
fmts2.sort()
if fmts1 != fmts2:
self.msgs.append( msg )
def __process( self, msg, msgid, msgstr ):
# Same number of named formats?
fmts1 = self.find_named_fmt_pat.findall( msgid )
fmts2 = self.find_named_fmt_pat.findall( msgstr )
if len( fmts1 ) != len( fmts2 ):
self.msgs.append( msg )
else:
# Do we have the same named formats?
fmts1.sort()
fmts2.sort()
if fmts1 != fmts2:
self.msgs.append( msg )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
class Check_missing_sd( Check ):
# A pattern to find %() without s or d
# Here is a command to use for testing
# print re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE).findall( '%(event_name)s: %(place)s%(endnotes)s. ' )
find_named_fmt_pat2 = re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE)
# A pattern to find %() without s or d
# Here is a command to use for testing
# print(re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE).findall( '%(event_name)s: %(place)s%(endnotes)s. ' ))
find_named_fmt_pat2 = re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE)
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- %() without 's' or 'd' mismatches --------------"
self.summary_text = "%() missing s/d:"
def process( self, msg ):
for msgstr in msg.msgstr:
fmts = self.find_named_fmt_pat2.findall( msgstr )
for f in fmts:
if not f in ('s', 'd'):
self.msgs.append( msg )
break
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- %() without 's' or 'd' mismatches --------------"
self.summary_text = "%() missing s/d:"
def process( self, msg ):
for msgstr in msg.msgstr:
fmts = self.find_named_fmt_pat2.findall( msgstr )
for f in fmts:
if not f in ('s', 'd'):
self.msgs.append( msg )
break
class Check_runaway( Check ):
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- Runaway context in translation ---------"
self.summary_text = "Runaway context:"
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- Runaway context in translation ---------"
self.summary_text = "Runaway context:"
def __process( self, msg, msgid, msgstr ):
# Runaway context. In the translated part we only to see
# the translation of the word after the |
if msgid.count('|') > 0 and msgstr.count('|') > 0 and msgid != msgstr:
self.msgs.append( msg )
def __process( self, msg, msgid, msgstr ):
# Runaway context. In the translated part we only to see
# the translation of the word after the |
if msgid.count('|') > 0 and msgstr.count('|') > 0 and msgid != msgstr:
self.msgs.append( msg )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
class Check_xml_chars( Check ):
# Special XML characters
# It is not allowed to have a quote, an ampersand or an angle bracket
xml_chars_pat = re.compile( r'<(?!(b>|/b>|i>|/i>|br/>)) | (?<=!(<b|/b|<i|/i|r/))> | " | & (?!(quot|nbsp|gt|amp);)', re.VERBOSE )
# Special XML characters
# It is not allowed to have a quote, an ampersand or an angle bracket
xml_chars_pat = re.compile( r'<(?!(b>|/b>|i>|/i>|br/>)) | (?<=!(<b|/b|<i|/i|r/))> | " | & (?!(quot|nbsp|gt|amp);)', re.VERBOSE )
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- unescaped XML special characters ---------"
self.summary_text = "XML special chars:"
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- unescaped XML special characters ---------"
self.summary_text = "XML special chars:"
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
# XML errors
# Only look at messages in the tips.xml
if msg.is_tips_xml:
if self.xml_chars_pat.search( msgstr ):
self.msgs.append( msg )
# XML errors
# Only look at messages in the tips.xml
if msg.is_tips_xml:
if self.xml_chars_pat.search( msgstr ):
self.msgs.append( msg )
class Check_last_char( Check ):
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- last character not identical ---------"
self.summary_text = "Last character:"
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- last character not identical ---------"
self.summary_text = "Last character:"
def __process( self, msg, msgid, msgstr ):
msgid_last = msgid[-1:]
msgstr_last = msgstr[-1:]
if msgid_last.isspace() != msgstr_last.isspace():
self.msgs.append( msg )
elif (msgid_last == '.') != (msgstr_last == '.'):
self.msgs.append( msg )
def __process( self, msg, msgid, msgstr ):
msgid_last = msgid[-1:]
msgstr_last = msgstr[-1:]
if msgid_last.isspace() != msgstr_last.isspace():
self.msgs.append( msg )
elif (msgid_last == '.') != (msgstr_last == '.'):
self.msgs.append( msg )
def process( self, msg ):
# Last character of msgid? White space? Period?
if msg.is_fuzzy:
return
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
def process( self, msg ):
# Last character of msgid? White space? Period?
if msg.is_fuzzy:
return
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
class Check_shortcut_trans( Check ):
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- shortcut key in translation ---------"
self.summary_text = "Shortcut in msgstr:"
def __init__( self ):
Check.__init__( self )
self.diag_header = "-------- shortcut key in translation ---------"
self.summary_text = "Shortcut in msgstr:"
def __process( self, msg, msgid, msgstr ):
if msgid.count('_') == 0 and msgstr.count('_') > 0:
self.msgs.append( msg )
def __process( self, msg, msgid, msgstr ):
if msgid.count('_') == 0 and msgstr.count('_') > 0:
self.msgs.append( msg )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
def process( self, msg ):
msgid = msg.msgid
msgstr = msg.msgstr[0]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
if msg.msgidp and len(msg.msgstr) >= 2:
msgid = msg.msgidp
msgstr = msg.msgstr[1]
self.__process( msg, msgid, msgstr )
class Msgid:
fuzzy_pat = re.compile( 'fuzzy' )
tips_xml_pat = re.compile( r'tips\.xml' )
def __init__( self, msgnr, lineno ):
self._msgid = [] # For debugging purpose the original text
self._msgidp = [] # For debugging purpose the original text
self._msgstr = [] # For debugging purpose the original text
self.msgid = ''
self.msgidp = ''
self.msgstr = [] # This is a list to support plural
self._cmnt = []
self.nr = msgnr
self.lineno = lineno
self.is_fuzzy = 0
self.is_tips_xml = 0
fuzzy_pat = re.compile( 'fuzzy' )
tips_xml_pat = re.compile( r'tips\.xml' )
def __init__( self, msgnr, lineno ):
self._msgid = [] # For debugging purpose the original text
self._msgidp = [] # For debugging purpose the original text
self._msgstr = [] # For debugging purpose the original text
self.msgid = ''
self.msgidp = ''
self.msgstr = [] # This is a list to support plural
self._cmnt = []
self.nr = msgnr
self.lineno = lineno
self.is_fuzzy = 0
self.is_tips_xml = 0
def diag( self ):
print
print "msg nr: %d, lineno: %d%s" % ( self.nr, self.lineno, self.is_fuzzy and " (fuzzy)" or "" )
sys.stdout.write( ''.join( self._msgid ) )
sys.stdout.write( ''.join( self._msgidp ) )
sys.stdout.write( ''.join( self._msgstr ) )
def diag( self ):
print
print("msg nr: %d, lineno: %d%s" % ( self.nr, self.lineno, self.is_fuzzy and " (fuzzy)" or "" ))
sys.stdout.write( ''.join( self._msgid ) )
sys.stdout.write( ''.join( self._msgidp ) )
sys.stdout.write( ''.join( self._msgstr ) )
def add_msgid( self, line, lineno ):
self._msgid.append( line )
line = re.sub( r'msgid\s+', '', line )
line = line.strip()
if line[0] != '"' or line[-1:] != '"':
print "ERROR at line %d: Missing quote." % lineno
line = strip_quotes( line )
self.msgid += line
def add_msgid( self, line, lineno ):
self._msgid.append( line )
line = re.sub( r'msgid\s+', '', line )
line = line.strip()
if line[0] != '"' or line[-1:] != '"':
print("ERROR at line %d: Missing quote." % lineno)
line = strip_quotes( line )
self.msgid += line
def add_msgidp( self, line, lineno ):
self._msgidp.append( line )
line = re.sub( r'msgid_plural\s+', '', line )
line = line.strip()
if line[0] != '"' or line[-1:] != '"':
print "ERROR at line %d: Missing quote." % lineno
line = strip_quotes( line )
self.msgidp += line
def add_msgidp( self, line, lineno ):
self._msgidp.append( line )
line = re.sub( r'msgid_plural\s+', '', line )
line = line.strip()
if line[0] != '"' or line[-1:] != '"':
print("ERROR at line %d: Missing quote." % lineno)
line = strip_quotes( line )
self.msgidp += line
def add_new_msgstr( self, line, lineno ):
self.msgstr.append( '' ) # Start a new msgstr
self.add_msgstr( line, lineno )
def add_new_msgstr( self, line, lineno ):
self.msgstr.append( '' ) # Start a new msgstr
self.add_msgstr( line, lineno )
def add_msgstr( self, line, lineno ):
self._msgstr.append( line )
line = re.sub( r'msgstr(\[\d\])?\s+', '', line )
line = line.strip()
if line[0] != '"' or line[-1:] != '"':
print "ERROR at line %d: Missing quote." % lineno
line = strip_quotes( line )
self.msgstr[-1] += line
def add_msgstr( self, line, lineno ):
self._msgstr.append( line )
line = re.sub( r'msgstr(\[\d\])?\s+', '', line )
line = line.strip()
if line[0] != '"' or line[-1:] != '"':
print("ERROR at line %d: Missing quote." % lineno)
line = strip_quotes( line )
self.msgstr[-1] += line
def add_cmnt( self, line ):
self._cmnt.append( line )
if not self.is_fuzzy and self.fuzzy_pat.search( line ):
self.is_fuzzy = 1
if not self.is_tips_xml and self.tips_xml_pat.search( line ):
self.is_tips_xml = 1
def add_cmnt( self, line ):
self._cmnt.append( line )
if not self.is_fuzzy and self.fuzzy_pat.search( line ):
self.is_fuzzy = 1
if not self.is_tips_xml and self.tips_xml_pat.search( line ):
self.is_tips_xml = 1
def create_new_Msgid( msgs, lineno ):
msg = Msgid( len(msgs), lineno )
msgs.append( msg )
return msg
msg = Msgid( len(msgs), lineno )
msgs.append( msg )
return msg
def read_msgs( fname ):
empty_pat = re.compile( r'^ \s* $', re.VERBOSE )
comment_pat = re.compile( r'\#', re.VERBOSE )
msgid_pat = re.compile( r'msgid \s+ "', re.VERBOSE )
msgid_plural_pat = re.compile( r'msgid_plural \s+ "', re.VERBOSE )
msgstr_pat = re.compile( r'msgstr (\[\d\])? \s+ "', re.VERBOSE )
str_pat = re.compile( r'"', re.VERBOSE )
old_pat = re.compile( r'\#~ \s+ ', re.VERBOSE )
empty_pat = re.compile( r'^ \s* $', re.VERBOSE )
comment_pat = re.compile( r'\#', re.VERBOSE )
msgid_pat = re.compile( r'msgid \s+ "', re.VERBOSE )
msgid_plural_pat = re.compile( r'msgid_plural \s+ "', re.VERBOSE )
msgstr_pat = re.compile( r'msgstr (\[\d\])? \s+ "', re.VERBOSE )
str_pat = re.compile( r'"', re.VERBOSE )
old_pat = re.compile( r'\#~ \s+ ', re.VERBOSE )
f = open( fname )
lines = f.readlines()
# parse it like a statemachine
NONE = 'NONE' # Nothing detected, yet
CMNT = 'CMNT' # Inside comment part
MSGID = 'msgid' # Inside msgid part
MSGIDP = 'msgid_plural' # Inside msgid_plural part
MSGSTR = 'msgstr' # Inside msgstr part
STR = 'STR' # A continuation string
OLD = 'OLD' # An old pattern with #~
f = open( fname )
lines = f.readlines()
global msgs
state = NONE
msg = None
# parse it like a statemachine
NONE = 'NONE' # Nothing detected, yet
CMNT = 'CMNT' # Inside comment part
MSGID = 'msgid' # Inside msgid part
MSGIDP = 'msgid_plural' # Inside msgid_plural part
MSGSTR = 'msgstr' # Inside msgstr part
STR = 'STR' # A continuation string
OLD = 'OLD' # An old pattern with #~
msgs = []
for ix, line in enumerate( lines ): # Use line numbers for messages
lineno = ix + 1
global msgs
state = NONE
msg = None
m = empty_pat.match( line )
if m:
continue # Empty lines are not interesting
msgs = []
for ix, line in enumerate( lines ): # Use line numbers for messages
lineno = ix + 1
# What's the next state?
if old_pat.match( line ):
next_state = OLD
elif comment_pat.match( line ):
next_state = CMNT
elif msgid_pat.match( line ):
next_state = MSGID
elif msgid_plural_pat.match( line ):
next_state = MSGIDP
elif msgstr_pat.match( line ):
next_state = MSGSTR
elif str_pat.match( line ):
next_state = STR
else:
print 'WARNING: Unexpected input at %(fname)s:%(lineno)d' % vars()
next_state = NONE
m = empty_pat.match( line )
if m:
continue # Empty lines are not interesting
#print "%(state)d->%(next_state)d\t%(line)s" % vars()
if state == NONE:
# expect msgid or comment or old stuff
if next_state == CMNT:
state = CMNT
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_cmnt( line )
# What's the next state?
if old_pat.match( line ):
next_state = OLD
elif comment_pat.match( line ):
next_state = CMNT
elif msgid_pat.match( line ):
next_state = MSGID
elif msgid_plural_pat.match( line ):
next_state = MSGIDP
elif msgstr_pat.match( line ):
next_state = MSGSTR
elif str_pat.match( line ):
next_state = STR
else:
print('WARNING: Unexpected input at %(fname)s:%(lineno)d' % vars())
next_state = NONE
elif next_state == MSGID:
state = MSGID
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_msgid( line, lineno )
#print("%(state)d->%(next_state)d\t%(line)s" % vars())
if state == NONE:
# expect msgid or comment or old stuff
if next_state == CMNT:
state = CMNT
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_cmnt( line )
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == MSGID:
state = MSGID
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_msgid( line, lineno )
elif next_state == MSGSTR:
print 'WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars()
state = MSGSTR
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_new_msgstr( line, lineno )
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == STR:
print 'WARNING: Wild string at %(fname)s:%(lineno)d' % vars()
elif next_state == MSGSTR:
print('WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars())
state = MSGSTR
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_new_msgstr( line, lineno )
elif next_state == OLD:
pass # Just skip
elif next_state == STR:
print('WARNING: Wild string at %(fname)s:%(lineno)d' % vars())
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == OLD:
pass # Just skip
elif state == CMNT:
# Expect more comment, or msgid. If msgstr or string it is flagged as error.
if next_state == CMNT:
if msg:
msg.add_cmnt( line )
else:
# Note. We may need to do something about these comments
# Skip for now
pass
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == MSGID:
state = MSGID
if not msg:
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_msgid( line, lineno )
elif state == CMNT:
# Expect more comment, or msgid. If msgstr or string it is flagged as error.
if next_state == CMNT:
if msg:
msg.add_cmnt( line )
else:
# Note. We may need to do something about these comments
# Skip for now
pass
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == MSGID:
state = MSGID
if not msg:
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_msgid( line, lineno )
elif next_state == MSGSTR:
print 'WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars()
state = MSGSTR
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_new_msgstr( line, lineno )
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == STR:
print 'WARNING: Wild string at %(fname)s:%(lineno)d' % vars()
elif next_state == MSGSTR:
print('WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars())
state = MSGSTR
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
msg.add_new_msgstr( line, lineno )
elif next_state == OLD:
msg = None
pass # Just skip
elif next_state == STR:
print('WARNING: Wild string at %(fname)s:%(lineno)d' % vars())
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == OLD:
msg = None
pass # Just skip
elif state == MSGID:
# Expect msgstr or msgid_plural or string
if next_state == CMNT:
# Hmmm. A comment here?
print 'WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars()
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == MSGID:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif state == MSGID:
# Expect msgstr or msgid_plural or string
if next_state == CMNT:
# Hmmm. A comment here?
print('WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars())
elif next_state == MSGIDP:
state = MSGIDP
msg.add_msgidp( line, lineno )
elif next_state == MSGID:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == MSGSTR:
state = MSGSTR
msg.add_new_msgstr( line, lineno )
elif next_state == MSGIDP:
state = MSGIDP
msg.add_msgidp( line, lineno )
elif next_state == STR:
# Continuation of msgid, stay in state MSGID
msg.add_msgid( line, lineno )
elif next_state == MSGSTR:
state = MSGSTR
msg.add_new_msgstr( line, lineno )
elif next_state == OLD:
msg = None
pass # Just skip
elif next_state == STR:
# Continuation of msgid, stay in state MSGID
msg.add_msgid( line, lineno )
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == OLD:
msg = None
pass # Just skip
elif state == MSGIDP:
# Expect msgstr or string or comment
if next_state == CMNT:
# Hmmm. A comment here?
print 'WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars()
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == MSGID:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif state == MSGIDP:
# Expect msgstr or string or comment
if next_state == CMNT:
# Hmmm. A comment here?
print('WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars())
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == MSGID:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == MSGSTR:
state = MSGSTR
msg.add_new_msgstr( line, lineno )
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == STR:
# Continuation of msgid_plural, stay in state MSGIDP
msg.add_msgidp( line, lineno )
elif next_state == MSGSTR:
state = MSGSTR
msg.add_new_msgstr( line, lineno )
elif next_state == OLD:
msg = None
pass # Just skip
elif next_state == STR:
# Continuation of msgid_plural, stay in state MSGIDP
msg.add_msgidp( line, lineno )
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == OLD:
msg = None
pass # Just skip
elif state == MSGSTR:
# Expect comment, or msgid, or string.
if next_state == CMNT:
# A comment probably starts a new item
state = CMNT
msg = create_new_Msgid( msgs, lineno )
msg.add_cmnt( line )
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == MSGID:
state = MSGID
msg = create_new_Msgid( msgs, lineno )
msg.add_msgid( line, lineno )
elif state == MSGSTR:
# Expect comment, or msgid, or string.
if next_state == CMNT:
# A comment probably starts a new item
state = CMNT
msg = create_new_Msgid( msgs, lineno )
msg.add_cmnt( line )
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == MSGID:
state = MSGID
msg = create_new_Msgid( msgs, lineno )
msg.add_msgid( line, lineno )
elif next_state == MSGSTR:
# New msgstr, probably for plural form
# Stay in MSGSTR state
msg.add_new_msgstr( line, lineno )
elif next_state == MSGIDP:
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
elif next_state == STR:
msg.add_msgstr( line, lineno )
elif next_state == MSGSTR:
# New msgstr, probably for plural form
# Stay in MSGSTR state
msg.add_new_msgstr( line, lineno )
elif next_state == OLD:
msg = None
pass # Just skip
elif next_state == STR:
msg.add_msgstr( line, lineno )
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
elif next_state == OLD:
msg = None
pass # Just skip
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
# Strip items with just comments. (Can this happen?)
msgs1 = []
for m in msgs:
if not m.msgid and not m.msgstr:
#print "INFO: No msgid or msgstr at %s:%s" % ( fname, m.lineno )
pass
else:
msgs1.append( m )
msgs = msgs1
return msgs
else:
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
# Strip items with just comments. (Can this happen?)
msgs1 = []
for m in msgs:
if not m.msgid and not m.msgstr:
#print("INFO: No msgid or msgstr at %s:%s" % ( fname, m.lineno ))
pass
else:
msgs1.append( m )
msgs = msgs1
return msgs
def analyze_msgs( args, fname, msgs, nr_templates = None, nth = 0 ):
nr_fuzzy = 0
nr_untranslated = 0
nr_fuzzy = 0
nr_untranslated = 0
checks = []
checks.append( Check_fmt( '%s' ) )
checks.append( Check_fmt( '%d' ) )
checks.append( Check_named_fmt() )
checks.append( Check_missing_sd() )
checks.append( Check_runaway() )
checks.append( Check_xml_chars() )
checks.append( Check_last_char() )
checks.append( Check_shortcut_trans() )
checks = []
checks.append( Check_fmt( '%s' ) )
checks.append( Check_fmt( '%d' ) )
checks.append( Check_named_fmt() )
checks.append( Check_missing_sd() )
checks.append( Check_runaway() )
checks.append( Check_xml_chars() )
checks.append( Check_last_char() )
checks.append( Check_shortcut_trans() )
for msg in msgs:
msgid = msg.msgid
msgstr = msg.msgstr
#print
#print "msgid: %(msgid)s" % vars()
#print "msgstr: %(msgstr)s" % vars()
for msg in msgs:
msgid = msg.msgid
msgstr = msg.msgstr
#print
#print("msgid: %(msgid)s" % vars())
#print("msgstr: %(msgstr)s" % vars())
if ''.join(msgstr) == '':
nr_untranslated += 1
continue
if ''.join(msgstr) == '':
nr_untranslated += 1
continue
if msg.is_fuzzy:
nr_fuzzy += 1
continue
if msg.is_fuzzy:
nr_fuzzy += 1
continue
for c in checks:
c.process( msg )
for c in checks:
c.process( msg )
nr_msgs = len(msgs)
if nth > 0:
print
print "====================================="
print "%-20s%s" % ( "File:", fname )
print "%-20s%d" % ( "Template total:", nr_templates )
print "%-20s%d" % ( "PO total:", nr_msgs )
print "%-20s%d" % ( "Fuzzy:", nr_fuzzy )
print "%-20s%d" % ( "Untranslated:", nr_untranslated )
nr_msgs = len(msgs)
if nth > 0:
print
print("=====================================")
print("%-20s%s" % ( "File:", fname ))
print("%-20s%d" % ( "Template total:", nr_templates ))
print("%-20s%d" % ( "PO total:", nr_msgs ))
print("%-20s%d" % ( "Fuzzy:", nr_fuzzy ))
print("%-20s%d" % ( "Untranslated:", nr_untranslated ))
for c in checks:
c.summary()
for c in checks:
c.summary()
po_coverage = (1.0 - (float(nr_untranslated) / float(nr_msgs))) * 100
print "%-20s%5.2f%%" % ( "PO Coverage:", po_coverage )
po_coverage = (1.0 - (float(nr_untranslated) / float(nr_msgs))) * 100
print("%-20s%5.2f%%" % ( "PO Coverage:", po_coverage ))
template_coverage = po_coverage * float(nr_msgs) / float(nr_templates)
print "%-20s%5.2f%%" % ( "Template Coverage:", template_coverage )
template_coverage = po_coverage * float(nr_msgs) / float(nr_templates)
print("%-20s%5.2f%%" % ( "Template Coverage:", template_coverage ))
not_displayed = nr_untranslated + nr_fuzzy
translation = (1.0 - (float(not_displayed) / float(nr_templates))) * 100
text = "%-20s%5.2f%%" % ( "Localized at:", translation)
not_displayed = nr_untranslated + nr_fuzzy
translation = (1.0 - (float(not_displayed) / float(nr_templates))) * 100
text = "%-20s%5.2f%%" % ( "Localized at:", translation)
if int(template_coverage*1000) == int(po_coverage*1000):
print text
else:
print text + ' (previous gramps.pot)'
if int(template_coverage*1000) == int(po_coverage*1000):
print(text)
else:
print(text + ' (previous gramps.pot)')
for c in checks:
c.diag()
for c in checks:
c.diag()
def main():
parser = ArgumentParser( description='This program validates a PO file for GRAMPS.')
parser.add_argument("-s", dest="summary",
choices=[file for file in os.listdir('.') if file.endswith('.po')],
choices=[file for file in os.listdir('.') if file.endswith('.po')],
default=False, help="the summary of check, and if need, it gives details")
args = parser.parse_args()
if args.summary:
files = sys.argv[2:]
try:
pot_msgs = read_msgs( 'gramps.pot' )
nr_templates = len( pot_msgs )
nth = 0
for fname in files:
msgs = read_msgs( fname )
analyze_msgs( files, fname, msgs, nr_templates, nth )
nth += 1
try:
pot_msgs = read_msgs( 'gramps.pot' )
nr_templates = len( pot_msgs )
nth = 0
for fname in files:
msgs = read_msgs( fname )
analyze_msgs( files, fname, msgs, nr_templates, nth )
nth += 1
except CheckException, e:
print 'Oops.', e
print 'Bailing out'
except CheckException as e:
print('Oops.', e)
print('Bailing out')
if __name__ == "__main__":
main()
main()
+8580 -5797
View File
File diff suppressed because it is too large Load Diff
+585 -136
View File
File diff suppressed because it is too large Load Diff
+690 -283
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -47,7 +47,7 @@ if sys.version_info[0] < 3:
import commands
from stat import ST_MODE
VERSION = '4.0.0-alpha2'
VERSION = '4.0.0-alpha3'
ALL_LINGUAS = ('bg', 'ca', 'cs', 'da', 'de', 'el', 'en_GB', 'es', 'fi', 'fr', 'he',
'hr', 'hu', 'it', 'ja', 'lt', 'nb', 'nl', 'nn', 'pl', 'pt_BR',
'pt_PT', 'ru', 'sk', 'sl', 'sq', 'sv', 'uk', 'vi', 'zh_CN')
@@ -244,7 +244,7 @@ def write_const_py(command):
locale_dir = os.path.join(command.install_data, 'share', 'locale')
else:
#in build
if os.access(const_py, os.F_OK):
if 'install' in command.distribution.command_obj:
# Prevent overwriting version created during install
return
locale_dir = os.path.join(command.build_base, 'mo')