diff --git a/data/tests/imp_PhonFax_dfs.ged b/data/tests/imp_PhonFax_dfs.ged
new file mode 100644
index 000000000..05b81b2ba
--- /dev/null
+++ b/data/tests/imp_PhonFax_dfs.ged
@@ -0,0 +1,90 @@
+0 HEAD
+1 SOUR FTM
+2 VERS Family Tree Maker (22.0.0.1410)
+2 NAME Family Tree Maker for Windows
+2 CORP Ancestry.com
+3 ADDR 360 W 4800 N
+4 CONT Provo, UT 84604
+3 PHON (801) 705-7000
+3 PHON (800) 705-7000
+3 FAX (801) 705-7001
+3 EMAIL help@ancestry.com
+3 WWW http://www.ancestry.com
+1 DEST GED55
+1 DATE 01 MAR 2016
+1 CHAR UTF-8
+1 FILE D:\Family Tree Maker\imp_FTM_LINK.ged
+1 SUBM @SUBM@
+1 GEDC
+2 VERS 5.5
+2 FORM LINEAGE-LINKED
+0 @SUBM@ SUBM
+1 NAME The Subm /Tester/
+1 ADDR 123 Main St., Winslow, PA, 12345
+2 ADR1 123 Main St.
+2 CITY Winslow
+2 STAE PA
+2 POST 12345
+1 PHON 440-871-3401
+1 PHON 800-871-3401
+1 EMAIL mrstester@gmail.com
+1 FAX 440-321-4568
+1 WWW http://mrstester.com
+0 @I0@ INDI
+1 NAME The /Tester/
+1 BIRT
+2 DATE 29 DEC 1954
+2 PLAC 123 High St, Cleveland, Cuyahoga, Ohio, USA, 44140
+3 FORM Street, City, County, State, Country, Zip code
+2 PHON 440-871-3400
+2 PHON 800-871-3400
+2 EMAIL thetester@gmail.com
+2 FAX 440-123-4567
+2 WWW http://thetester.com
+0 @I1@ INDI
+1 NAME Mrs /Tester/
+1 ADDR 123 Main St., Winslow, PA, 12345
+2 ADR1 123 Main St.
+2 CITY Winslow
+2 STAE PA
+2 POST 12345
+1 PHON 440-871-3401
+1 PHON 800-871-3401
+1 EMAIL mrstester@gmail.com
+1 FAX 440-321-4568
+1 WWW http://mrstester.com
+1 NOTE Address with PHON,FAX,EMAIL,WWW. attached directly to person
+2 CONC is not legal Gedcom, but allowed here.
+1 RESI
+2 DATE 30 DEC 1954
+2 ADDR 123 Main St., Winslow, PA, 12345
+3 ADR1 123 Main St.
+3 CITY Winslow
+3 STAE PA
+3 POST 12345
+2 NOTE Address as event is legal, with PHON,FAX,EMAIL,WWW
+2 PHON 440-871-3401
+2 EMAIL mrstester@gmail.com
+2 FAX 440-321-4568
+2 WWW http://mrstester.com
+0 @I2@ INDI
+1 NAME Tom /Tester/
+1 RESI
+2 DATE 1964
+2 PHON 440-871-3402
+2 EMAIL tomtester@gmail.com
+2 FAX 440-321-4569
+2 WWW http://tomtester.com
+0 @S6@ SOUR
+1 TITL Ohio Births, 1958-2002
+1 REPO @R1@
+0 @R1@ REPO
+1 NAME Testers Repository
+1 ADDR 123 High St., OSF village, CA, USA
+1 EMAIL tester_repo@osf.com
+1 FAX 987-654-3210
+1 PHON 988-765-4321
+1 PHON 800-765-4321
+1 WWW http://www.tester_repo.com
+1 NOTE The repository record
+0 TRLR
diff --git a/data/tests/imp_PhonFax_dfs.gramps b/data/tests/imp_PhonFax_dfs.gramps
new file mode 100644
index 000000000..c2c341fa6
--- /dev/null
+++ b/data/tests/imp_PhonFax_dfs.gramps
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+ The Subm /Tester/
+ 123 Main St.
+ Winslow
+ PA
+ 12345
+ 440-871-3401
+ mrstester@gmail.com
+
+
+
+
+ Birth
+
+
+
+
+
+
+
+
+
+ Residence
+
+
+
+
+
+
+
+
+
+ Residence
+
+
+
+
+
+
+
+
+
+ U
+
+ The
+ Tester
+
+
+
+
+
+ U
+
+ Mrs
+ Tester
+
+
+
+ 123 Main St.
+ Winslow
+ PA
+ 12345
+
+
+
+
+
+
+
+
+
+
+ U
+
+ Tom
+ Tester
+
+
+
+
+
+
+
+ 2
+
+
+
+ 2
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+ 123 High St, Cleveland, Cuyahoga, Ohio, USA, 44140
+ 44140
+
+
+
+
+ 123 Main St., Winslow, PA, 12345
+
+
+
+
+ USA
+
+
+
+ Ohio, USA
+
+
+
+
+ Cuyahoga, Ohio, USA
+
+
+
+
+ Cleveland, Cuyahoga, Ohio, USA
+
+
+
+
+
+
+ Business that produced the product: Ancestry.com
+ GEDCOM data
+
+ 360 W 4800 N, Provo, UT 84604
+ (801) 705-7000
+
+
+
+
+
+
+ SUBM (Submitter): (@SUBM@) The Subm /Tester/
+ GEDCOM data
+
+ 123 Main St.
+ Winslow
+ PA
+ 12345
+ 440-871-3401
+
+
+
+
+
+
+
+ Testers Repository
+ Library
+
+ 123 High St., OSF village, CA, USA
+ 988-765-4321
+
+
+
+
+
+
+
+
+
+
+ Records not imported into HEAD (header):
+
+Only one phone number supported Line 9: 3 PHON (800) 705-7000
+
+
+
+ Records not imported into SUBM (Submitter): (@SUBM@) The Subm /Tester/:
+
+Only one phone number supported Line 29: 1 PHON 800-871-3401
+
+
+
+ Address with PHON,FAX,EMAIL,WWW. attached directly to person is not legal Gedcom, but allowed here.
+
+
+ Address as event is legal, with PHON,FAX,EMAIL,WWW
+
+
+ The repository record
+
+
+ Records not imported into REPO (repository) Gramps ID R0002:
+
+Only one phone number supported Line 87: 1 PHON 800-765-4321
+
+
+
+
diff --git a/gramps/gen/merge/diff.py b/gramps/gen/merge/diff.py
index 89f5898ff..dac78bcdd 100644
--- a/gramps/gen/merge/diff.py
+++ b/gramps/gen/merge/diff.py
@@ -82,7 +82,7 @@ def parse(string):
retval.append(current)
return retval
-def import_as_dict(filename, user=None):
+def import_as_dict(filename, user=None, skp_imp_adds=True):
"""
Import the filename into a InMemoryDB and return it.
"""
@@ -90,7 +90,7 @@ def import_as_dict(filename, user=None):
user = User()
db = make_database("inmemorydb")
db.load(None)
- db.set_feature("skip-import-additions", True)
+ db.set_feature("skip-import-additions", skp_imp_adds)
dbstate = DbState()
climanager = CLIManager(dbstate, setloader=False, user=user)
climanager.do_reg_plugins(dbstate, None)
diff --git a/gramps/plugins/lib/libgedcom.py b/gramps/plugins/lib/libgedcom.py
index b7d983eb3..fb74beade 100644
--- a/gramps/plugins/lib/libgedcom.py
+++ b/gramps/plugins/lib/libgedcom.py
@@ -261,7 +261,7 @@ TOKEN_LONG = 122
TOKEN_FACT = 123
TOKEN_EMAIL = 124
TOKEN_WWW = 125
-TOKEN_URL = 126
+TOKEN_FAX = 126
TOKEN_ROLE = 127
TOKEN__MAR = 128
TOKEN__MARN = 129
@@ -373,12 +373,14 @@ TOKENS = {
"LONG" : TOKEN_LONG, "_ITALIC" : TOKEN_IGNORE,
"_PLACE" : TOKEN_IGNORE,
"FACT" : TOKEN_FACT, "EMAIL" : TOKEN_EMAIL,
+ "_E-MAIL" : TOKEN_EMAIL, "_EMAIL" : TOKEN_EMAIL,
"EMAI" : TOKEN_EMAIL, "WWW" : TOKEN_WWW,
- "_URL" : TOKEN_URL, "URL" : TOKEN_URL,
+ "_URL" : TOKEN_WWW, "URL" : TOKEN_WWW,
"_MAR" : TOKEN__MAR, "_MARN" : TOKEN__MARN,
"_ADPN" : TOKEN__ADPN, "_FSFTID" : TOKEN__FSFTID,
"_LINK" : TOKEN__LINK, "_PHOTO" : TOKEN__PHOTO,
"_JUST" : TOKEN__JUST, # FTM Citation Quality Justification
+ "FAX" : TOKEN_FAX,
}
ADOPT_NONE = 0
@@ -2031,6 +2033,8 @@ class GedcomParser(UpdateCallback):
TOKEN_ADDR : self.__subm_addr,
TOKEN_PHON : self.__subm_phon,
TOKEN_EMAIL : self.__subm_email,
+ TOKEN_WWW : self.__repo_www,
+ TOKEN_FAX : self.__repo_fax,
# +1 <>
# +1 LANG
# +1 RFN
@@ -2123,11 +2127,13 @@ class GedcomParser(UpdateCallback):
TOKEN_RIN : self.__person_attr,
# +1 <> {0:1}
TOKEN_CHAN : self.__person_chan,
-
+ # The following tags are not part of Gedcom spec but are commonly
+ # found here anyway
TOKEN_ADDR : self.__person_addr,
TOKEN_PHON : self.__person_phon,
+ TOKEN_FAX : self.__person_fax,
TOKEN_EMAIL : self.__person_email,
- TOKEN_URL : self.__person_url,
+ TOKEN_WWW : self.__person_www,
TOKEN__TODO : self.__skip_record,
TOKEN_TITL : self.__person_titl,
TOKEN__PHOTO: self.__person_photo,
@@ -2192,6 +2198,7 @@ class GedcomParser(UpdateCallback):
TOKEN_PHON : self.__repo_phon,
TOKEN_EMAIL : self.__repo_email,
TOKEN_WWW : self.__repo_www,
+ TOKEN_FAX : self.__repo_fax,
}
self.func_list.append(self.repo_parse_tbl)
@@ -2242,6 +2249,7 @@ class GedcomParser(UpdateCallback):
TOKEN_ATTR : self.__event_attr, # FTB for _UID
TOKEN_EMAIL : self.__event_email, # FTB for RESI events
TOKEN_WWW : self.__event_www, # FTB for RESI events
+ TOKEN_FAX : self.__event_fax, # legal...
}
self.func_list.append(self.event_parse_tbl)
@@ -2701,6 +2709,9 @@ class GedcomParser(UpdateCallback):
self.header_corp_addr = {
TOKEN_ADDR : self.__repo_addr,
TOKEN_PHON : self.__repo_phon,
+ TOKEN_FAX : self.__repo_fax,
+ TOKEN_WWW : self.__repo_www,
+ TOKEN_EMAIL : self.__repo_email,
}
self.func_list.append(self.header_corp_addr)
@@ -3523,13 +3534,6 @@ class GedcomParser(UpdateCallback):
addr.set_county(state.res.get_county())
addr.set_phone(state.res.get_phone())
repo.add_address(addr)
-
- if state.res.get_email():
- url = Url()
- url.set_path(state.res.get_email())
- url.set_type(UrlType(UrlType.EMAIL))
- repo.add_url(url)
-
rtype = RepositoryType()
rtype.set((RepositoryType.CUSTOM, _('GEDCOM data')))
repo.set_type(rtype)
@@ -3870,6 +3874,7 @@ class GedcomParser(UpdateCallback):
"""
self.__obje(line, state, state.person)
+
def __person_photo(self, line, state):
"""
This handles the FTM _PHOTO feature, which identifies an OBJE to use
@@ -4136,12 +4141,25 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
- addr = Address()
- addr.set_street("Unknown")
- addr.set_phone(line.data)
- state.person.add_address(addr)
- self.__skip_subordinate_levels(state.level+1, state)
+ url = Url()
+ url.set_path(line.data)
+ url.set_type(UrlType(_('Phone')))
+ state.person.add_url(url)
+ def __person_fax(self, line, state):
+ """
+ O INDI
+ 1 FAX {0:3}
+
+ @param line: The current line in GedLine format
+ @type line: GedLine
+ @param state: The current state
+ @type state: CurrentState
+ """
+ url = Url()
+ url.set_path(line.data)
+ url.set_type(UrlType(_('FAX')))
+ state.person.add_url(url)
def __person_email(self, line, state):
"""
@@ -4158,10 +4176,10 @@ class GedcomParser(UpdateCallback):
url.set_type(UrlType(UrlType.EMAIL))
state.person.add_url(url)
- def __person_url(self, line, state):
+ def __person_www(self, line, state):
"""
O INDI
- 1 URL {0:3}
+ 1 WWW {0:3}
@param line: The current line in GedLine format
@type line: GedLine
@@ -5206,6 +5224,7 @@ class GedcomParser(UpdateCallback):
"""
self.__obje(line, state, state.family)
+
def __family_comm(self, line, state):
"""
@param line: The current line in GedLine format
@@ -5541,6 +5560,7 @@ class GedcomParser(UpdateCallback):
"""
self.__obje(line, state, state.event)
+
def __event_type(self, line, state):
"""
Parses the TYPE line for an event.
@@ -5660,6 +5680,7 @@ class GedcomParser(UpdateCallback):
"""
self.__obje(line, state, state.place)
+
def __event_place_sour(self, line, state):
"""
@param line: The current line in GedLine format
@@ -5801,18 +5822,6 @@ class GedcomParser(UpdateCallback):
else:
return place.get_alternate_locations()[0]
- def __event_phon(self, line, state):
- """
- @param line: The current line in GedLine format
- @type line: GedLine
- @param state: The current state
- @type state: CurrentState
- """
- place = state.place
- if place:
- codes = [place.get_code(), line.data]
- place.set_code(' '.join(code for code in codes if code))
-
def __event_privacy(self, line, state):
"""
@param line: The current line in GedLine format
@@ -5883,6 +5892,30 @@ class GedcomParser(UpdateCallback):
"""
state.event.add_attribute(line.data)
+ def __event_phon(self, line, state):
+ """
+ @param line: The current line in GedLine format
+ @type line: GedLine
+ @param state: The current state
+ @type state: CurrentState
+ """
+ attr = Attribute()
+ attr.set_type(_("Phone"))
+ attr.set_value(line.data)
+ state.event.add_attribute(attr)
+
+ def __event_fax(self, line, state):
+ """
+ @param line: The current line in GedLine format
+ @type line: GedLine
+ @param state: The current state
+ @type state: CurrentState
+ """
+ attr = Attribute()
+ attr.set_type(_("FAX"))
+ attr.set_value(line.data)
+ state.event.add_attribute(attr)
+
def __event_email(self, line, state):
"""
@param line: The current line in GedLine format
@@ -5891,7 +5924,7 @@ class GedcomParser(UpdateCallback):
@type state: CurrentState
"""
attr = Attribute()
- attr.set_type(line.token_text)
+ attr.set_type(_("EMAIL"))
attr.set_value(line.data)
state.event.add_attribute(attr)
@@ -5903,7 +5936,7 @@ class GedcomParser(UpdateCallback):
@type state: CurrentState
"""
attr = Attribute()
- attr.set_type(line.token_text)
+ attr.set_type(_("WWW"))
attr.set_value(line.data)
state.event.add_attribute(attr)
@@ -6345,6 +6378,7 @@ class GedcomParser(UpdateCallback):
"""
self.__obje(line, state, state.citation)
+
def __citation_refn(self, line, state):
"""
Parses the REFN line of an SOUR instance tag
@@ -6484,6 +6518,7 @@ class GedcomParser(UpdateCallback):
"""
self.__obje(line, state, state.source)
+
def __source_chan(self, line, state):
"""
@param line: The current line in GedLine format
@@ -7011,7 +7046,22 @@ class GedcomParser(UpdateCallback):
"""
address_list = state.repo.get_address_list()
if address_list:
- address_list[0].set_phone(line.data)
+ if address_list[0].get_phone():
+ self.__add_msg(_("Only one phone number supported"), line, state)
+ else:
+ address_list[0].set_phone(line.data)
+
+ def __repo_fax(self, line, state):
+ """
+ @param line: The current line in GedLine format
+ @type line: GedLine
+ @param state: The current state
+ @type state: CurrentState
+ """
+ url = Url()
+ url.set_path(line.data)
+ url.set_type(UrlType(_('FAX')))
+ state.repo.add_url(url)
def __repo_www(self, line, state):
"""
@@ -7969,7 +8019,10 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
- state.res.set_phone(line.data)
+ if state.res.get_phone():
+ self.__add_msg(_("Only one phone number supported"), line, state)
+ else:
+ state.res.set_phone(line.data)
def __subm_email(self, line, state):
"""
@@ -7980,7 +8033,10 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
- state.res.set_email(line.data)
+ # only record the first multiple emails for researcher
+ if not state.res.get_email():
+ state.res.set_email(line.data)
+ self.__repo_email(line, state)
#-------------------------------------------------------------------------
#
diff --git a/gramps/plugins/test/test_imports.py b/gramps/plugins/test/test_imports.py
index dae89841e..49011a4df 100644
--- a/gramps/plugins/test/test_imports.py
+++ b/gramps/plugins/test/test_imports.py
@@ -32,6 +32,8 @@ from gramps.gen.simple import SimpleAccess
from gramps.gen.utils.id import set_det_id
from gramps.cli.user import User
from gramps.gen.const import TEMP_DIR, DATA_DIR
+from gramps.gen.utils.config import config
+from gramps.plugins.export.exportxml import XmlWriter
logger = logging.getLogger(__name__)
@@ -179,13 +181,21 @@ def make_tst_function(tstfile, file_name):
fn1 = os.path.join(TEST_DIR, tstfile)
fn2 = os.path.join(TEST_DIR, (file_name + ".gramps"))
fres = os.path.join(TEMP_DIR, (file_name + ".difs"))
+ fout = os.path.join(TEMP_DIR, (file_name + ".gramps"))
+ if "_dfs" in tstfile:
+ config.set('preferences.default-source', True)
+ skp_imp_adds = False
+ else:
+ skp_imp_adds = True
try:
os.remove(fres)
+ os.remove(fout)
except OSError:
pass
logging.info("\n**** %s ****", tstfile)
set_det_id(True)
- self.database1 = import_as_dict(fn1, self.user)
+ self.database1 = import_as_dict(fn1, self.user,
+ skp_imp_adds=skp_imp_adds)
set_det_id(True)
self.database2 = import_as_dict(fn2, self.user)
self.assertIsNotNone(self.database1,
@@ -200,7 +210,12 @@ def make_tst_function(tstfile, file_name):
deltas = self.prepare_result(diffs, added, missing)
# We save a copy of any issues in the users Gramps TEMP_DIR in a file
# with a '.difs' extension, as well as usual unittest report
+ # Also we save the .gramps file from the import so user can perform
+ # Diff himself for better context.
if deltas:
+ writer = XmlWriter(self.database1, self.user,
+ strip_photos=0, compress=0)
+ writer.write(fout)
hres = open(fres, mode='w', encoding='utf-8',
errors='replace')
hres.write(self.msg)