for family_member in family.get_child_elements():
if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
- and family_member.get_value() == individual.get_pointer():
+ and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
@@ -546,19 +546,32 @@
Module gedcom.parser
# Other methods
+ def to_gedcom_string(self, recursive=False):
+ """Formats all elements and optionally all of the sub-elements into a GEDCOM string
+ :type recursive: bool
+ """
+ is_gte_python_3 = version_info[0] >= 3
+ output = '' if is_gte_python_3 else b''
+
+ for element in self.get_root_child_elements():
+ if is_gte_python_3:
+ output += element.to_gedcom_string(recursive)
+ else:
+ output += element.to_gedcom_string(recursive).encode('utf-8-sig')
+
+ return output
+
def print_gedcom(self):
"""Write GEDCOM data to stdout"""
from sys import stdout
self.save_gedcom(stdout)
- def save_gedcom(self, open_file):
+ def save_gedcom(self, open_file, recursive=True):
"""Save GEDCOM data to a file
:type open_file: file
+ :type recursive: bool
"""
- if version_info[0] >= 3:
- open_file.write(self.get_root_element().to_gedcom_string(True))
- else:
- open_file.write(self.get_root_element().to_gedcom_string(True).encode('utf-8-sig'))
+ open_file.write(self.to_gedcom_string(recursive))
@@ -989,7 +1002,7 @@
Ancestors
for family_member in family.get_child_elements():
if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
- and family_member.get_value() == individual.get_pointer():
+ and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
@@ -1071,19 +1084,32 @@
Ancestors
# Other methods
+ def to_gedcom_string(self, recursive=False):
+ """Formats all elements and optionally all of the sub-elements into a GEDCOM string
+ :type recursive: bool
+ """
+ is_gte_python_3 = version_info[0] >= 3
+ output = '' if is_gte_python_3 else b''
+
+ for element in self.get_root_child_elements():
+ if is_gte_python_3:
+ output += element.to_gedcom_string(recursive)
+ else:
+ output += element.to_gedcom_string(recursive).encode('utf-8-sig')
+
+ return output
+
def print_gedcom(self):
"""Write GEDCOM data to stdout"""
from sys import stdout
self.save_gedcom(stdout)
- def save_gedcom(self, open_file):
+ def save_gedcom(self, open_file, recursive=True):
"""Save GEDCOM data to a file
:type open_file: file
+ :type recursive: bool
"""
- if version_info[0] >= 3:
- open_file.write(self.get_root_element().to_gedcom_string(True))
- else:
- open_file.write(self.get_root_element().to_gedcom_string(True).encode('utf-8-sig'))
+ open_file.write(self.to_gedcom_string(recursive))
Methods
@@ -1450,7 +1476,7 @@
Methods
for family_member in family.get_child_elements():
if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
- and family_member.get_value() == individual.get_pointer():
+ and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
@@ -1649,23 +1675,48 @@
Formats all elements and optionally all of the sub-elements into a GEDCOM string
+:type recursive: bool
+
+
+Expand source code
+
+
def to_gedcom_string(self, recursive=False):
+ """Formats all elements and optionally all of the sub-elements into a GEDCOM string
+ :type recursive: bool
+ """
+ is_gte_python_3 = version_info[0] >= 3
+ output = '' if is_gte_python_3 else b''
+
+ for element in self.get_root_child_elements():
+ if is_gte_python_3:
+ output += element.to_gedcom_string(recursive)
+ else:
+ output += element.to_gedcom_string(recursive).encode('utf-8-sig')
+
+ return output
diff --git a/gedcom/parser.py b/gedcom/parser.py
index 4f1f113..473ad9e 100644
--- a/gedcom/parser.py
+++ b/gedcom/parser.py
@@ -435,7 +435,7 @@ def get_parents(self, individual, parent_type="ALL"):
for family_member in family.get_child_elements():
if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
- and family_member.get_value() == individual.get_pointer():
+ and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
@@ -517,16 +517,29 @@ def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
# Other methods
+ def to_gedcom_string(self, recursive=False):
+ """Formats all elements and optionally all of the sub-elements into a GEDCOM string
+ :type recursive: bool
+ """
+ is_gte_python_3 = version_info[0] >= 3
+ output = '' if is_gte_python_3 else b''
+
+ for element in self.get_root_child_elements():
+ if is_gte_python_3:
+ output += element.to_gedcom_string(recursive)
+ else:
+ output += element.to_gedcom_string(recursive).encode('utf-8-sig')
+
+ return output
+
def print_gedcom(self):
"""Write GEDCOM data to stdout"""
from sys import stdout
self.save_gedcom(stdout)
- def save_gedcom(self, open_file):
+ def save_gedcom(self, open_file, recursive=True):
"""Save GEDCOM data to a file
:type open_file: file
+ :type recursive: bool
"""
- if version_info[0] >= 3:
- open_file.write(self.get_root_element().to_gedcom_string(True))
- else:
- open_file.write(self.get_root_element().to_gedcom_string(True).encode('utf-8-sig'))
+ open_file.write(self.to_gedcom_string(recursive))
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 86df008..451a3fa 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -98,6 +98,60 @@ def test_parse_from_string():
assert element_2_children[3].get_value() == '@I84@'
+def test_to_gedcom_string():
+ # From string
+ case_1 = """0 @I5@ INDI
+1 NAME First /Last/
+1 SEX M
+1 BIRT
+2 DATE 1 JAN 1900
+2 PLAC Kirkland, King, Washington, USA
+3 MAP
+4 LATI N47.680663
+4 LONG W122.234319
+"""
+
+ gedcom_parser = Parser()
+ gedcom_parser.parse([(a + '\n').encode('utf-8-sig') for a in case_1.splitlines()])
+
+ case_1_string_array = case_1.splitlines()
+ gedcom_string = gedcom_parser.to_gedcom_string(True)
+ gedcom_string_array = gedcom_string.splitlines()
+
+ # Check number of lines
+ assert len(case_1_string_array) == len(gedcom_string_array) == 9
+
+ # Check each line
+ for i in range(len(case_1_string_array)):
+ assert case_1_string_array[i] == gedcom_string_array[i]
+
+ # Check whole file string
+ assert gedcom_string == case_1
+
+ # From file
+ case_2 = ""
+
+ with open('tests/files/Musterstammbaum.ged', 'rb') as gedcom_stream:
+ for line in gedcom_stream:
+ case_2 += line.decode('utf-8-sig')
+
+ gedcom_parser.parse_file('tests/files/Musterstammbaum.ged')
+
+ case_2_string_array = case_2.splitlines()
+ gedcom_string = gedcom_parser.to_gedcom_string(True)
+ gedcom_string_array = gedcom_string.splitlines()
+
+ # Check number of lines
+ assert len(case_2_string_array) == len(gedcom_string_array) == 396
+
+ # Check each line
+ for i in range(len(case_2_string_array)):
+ assert case_2_string_array[i] == gedcom_string_array[i]
+
+ # Check whole file string
+ assert gedcom_string == case_2
+
+
def test___parse_line():
# @TODO Add appropriate testing cases
pass
From 4cf4cba507be2d05d1a0a5f64045c0ce60a24631 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Thu, 14 May 2020 20:40:03 -0400
Subject: [PATCH 05/23] Add missing 5.5.1 tags and some of the common program
defined ones.
---
gedcom/tags.py | 733 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 709 insertions(+), 24 deletions(-)
diff --git a/gedcom/tags.py b/gedcom/tags.py
index 9efa002..35676f6 100644
--- a/gedcom/tags.py
+++ b/gedcom/tags.py
@@ -2,6 +2,7 @@
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -29,60 +30,295 @@
GEDCOM tags.
"""
-GEDCOM_PROGRAM_DEFINED_TAG_MREL = "_MREL"
-"""Value: `_MREL`
+GEDCOM_PROGRAM_DEFINED_TAG_APID = "_APID"
+"""Value: `_APID`
-Relationship to a mother."""
+Ancestry page id for a citation, points to page in database of record."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE = "_DCAUSE"
+"""Value: `_DCAUSE`
+
+Cause of death."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_DEGREE = "_DEG"
+"""Value: `_DEG`
+
+Degree or recognition of accomplishment received by an individual."""
GEDCOM_PROGRAM_DEFINED_TAG_FREL = "_FREL"
"""Value: `_FREL`
Relationship to a father."""
+GEDCOM_PROGRAM_DEFINED_TAG_FUNERAL = "_FUN"
+"""Value: `_FUN`
+
+Funeral for an individual."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL = "_MDCL"
+"""Value: `_MDCL`
+
+Medical information about an individual."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MILITARY = "_MILT"
+"""Value: `_MILT`
+
+A military related event in the individuals life."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MREL = "_MREL"
+"""Value: `_MREL`
+
+Relationship to a mother."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_PHOTO = "_PHOTO"
+"""Value: `_PHOTO`
+
+Used by some programs to identify the primary multimedia object for an
+individual, the same as _PRIM."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED = "_PREF"
+"""Value: `_PREF`
+
+Indicates a preferred spouse, child or parents."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY = "_PRIM"
+"""Value: `_PRIM`
+
+Primary multimedia object for an individual."""
+
+GEDCOM_TAG_ABBREVIATION = "ABBR"
+"""Value: `ABBR`
+
+A short name of a title, description, or name."""
+
+GEDCOM_TAG_ADDRESS = "ADDR"
+"""Value: `ADDR`
+
+The contemporary place, usually required for postal purposes, of an individual,
+a submitter of information, a repository, a business, a school, or a company."""
+
+GEDCOM_TAG_ADDRESS1 = "ADR1"
+"""Value: `ADR1`
+
+The first line of an address."""
+
+GEDCOM_TAG_ADDRESS2 = "ADR2"
+"""Value: `ADR2`
+
+The second line of an address."""
+
+GEDCOM_TAG_ADOPTION = "ADOP"
+"""Value: `ADOP`
+
+Pertaining to creation of a child-parent relationship that does not exist
+biologically."""
+
+GEDCOM_TAG_AGE = "AFN"
+"""Value: `AFN`
+
+Ancestral File Number, a unique permanent record file number of an individual
+record stored in Ancestral File."""
+
+GEDCOM_TAG_AGE = "AGE"
+"""Value: `AGE`
+
+The age of the individual at the time an event occurred, or the age listed in
+the document."""
+
+GEDCOM_TAG_AGENCY = "AGNC"
+"""Value: `AGNC`
+
+The institution or individual having authority and/or responsibility to manage
+or govern."""
+
+GEDCOM_TAG_ALIAS = "ALIA"
+"""Value: `ALIA`
+
+An indicator to link different record descriptions of a person who may be the
+same person."""
+
+GEDCOM_TAG_ANCESTORS = "ANCE"
+"""Value: `ANCE`
+
+Pertaining to forbearers of an individual."""
+
+GEDCOM_TAG_ANCES_INTEREST = "ANCI"
+"""Value: `ANCI`
+
+Indicates an interest in additional research for ancestors of this individual.
+(See also DESI)"""
+
+GEDCOM_TAG_ANNULMENT = "ANUL"
+"""Value: `ANUL`
+
+Declaring a marriage void from the beginning (never existed)."""
+
+GEDCOM_TAG_ASSOCIATES = "ASSO"
+"""Value: `ASSO`
+
+An indicator to link friends, neighbors, relatives, or associates of an
+individual."""
+
+GEDCOM_TAG_AUTHOR = "AUTH"
+"""Value: `AUTH`
+
+The name of the individual who created or compiled information."""
+
+GEDCOM_TAG_BAPTISM_LDS = "BAPL"
+"""Value: `BAPL`
+
+The event of baptism performed at age eight or later by priesthood authority
+of the LDS Church. (See also BAPM)"""
+
+GEDCOM_TAG_BAPTISM = "BAPM"
+"""Value: `BAPM`
+
+The event of baptism (not LDS), performed in infancy or later."""
+
+GEDCOM_TAG_BAR_MITZVAH = "BARM"
+"""Value: `BARM`
+
+The ceremonial event held when a Jewish boy reaches age 13."""
+
+GEDCOM_TAG_BAS_MITZVAH = "BASM"
+"""Value: `BASM`
+
+The ceremonial event held when a Jewish girl reaches age 13, also known as
+Bat Mitzvah."""
+
GEDCOM_TAG_BIRTH = "BIRT"
"""Value: `BIRT`
The event of entering into life."""
+GEDCOM_TAG_BLESSING = "BLES"
+"""Value: `BLES`
+
+A religious event of bestowing divine care or intercession. Sometimes given
+in connection with a naming ceremony."""
+
GEDCOM_TAG_BURIAL = "BURI"
"""Value: `BURI`
The event of the proper disposing of the mortal remains of a deceased person."""
+GEDCOM_TAG_CALL_NUMBER = "CALN"
+"""Value: `CALN`
+
+The number used by a repository to identify the specific items in its
+collections."""
+
+GEDCOM_TAG_CASTE = "CAST"
+"""Value: `CAST`
+
+The name of an individual's rank or status in society, based on racial or
+religious differences, or differences in wealth, inherited rank, profession,
+occupation, etc."""
+
+GEDCOM_TAG_CAUSE = "CAUSE"
+"""Value: `CAUS`
+
+A description of the cause of the associated event or fact, such as the cause
+of death."""
+
GEDCOM_TAG_CENSUS = "CENS"
"""Value: `CENS`.
-The event of the periodic count of the population for a designated locality, such as a national or state Census."""
+The event of the periodic count of the population for a designated locality,
+such as a national or state Census."""
GEDCOM_TAG_CHANGE = "CHAN"
"""Value: `CHAN`
Indicates a change, correction, or modification. Typically used in connection
-with a `gedcom.tags.GEDCOM_TAG_DATE` to specify when a change in information occurred."""
+with a `gedcom.tags.GEDCOM_TAG_DATE` to specify when a change in information
+occurred."""
+
+GEDCOM_TAG_CHARACTER = "CHAR"
+"""Value: `CHAR`
+
+An indicator of the character set used in writing this automated information."""
GEDCOM_TAG_CHILD = "CHIL"
"""Value: `CHIL`
The natural, adopted, or sealed (LDS) child of a father and a mother."""
+GEDCOM_TAG_CHRISTENING = "CHR"
+"""Value: `CHR`
+
+The religious event (not LDS) of baptizing and/or naming a child."""
+
+GEDCOM_TAG_ADULT_CHRISTENING = "CHRA"
+"""Value: `CHRA`
+
+The religious event (not LDS) of baptizing and/or naming an adult person."""
+
+GEDCOM_TAG_CITY = "CITY"
+"""Value: `CITY`
+
+A lower level jurisdictional unit. Normally an incorporated municipal unit."""
+
GEDCOM_TAG_CONCATENATION = "CONC"
"""Value: `CONC`
-An indicator that additional data belongs to the superior value. The information from the `CONC` value is to
-be connected to the value of the superior preceding line without a space and without a carriage return and/or
-new line character. Values that are split for a `CONC` tag must always be split at a non-space. If the value is
-split on a space the space will be lost when concatenation takes place. This is because of the treatment that
-spaces get as a GEDCOM delimiter, many GEDCOM values are trimmed of trailing spaces and some systems look for
-the first non-space starting after the tag to determine the beginning of the value."""
+An indicator that additional data belongs to the superior value. The information
+from the `CONC` value is to be connected to the value of the superior preceding
+line without a space and without a carriage return and/or new line character.
+Values that are split for a `CONC` tag must always be split at a non-space. If
+the value is split on a space the space will be lost when concatenation takes
+place. This is because of the treatment that spaces get as a GEDCOM delimiter,
+many GEDCOM values are trimmed of trailing spaces and some systems look for
+the first non-space starting after the tag to determine the beginning of the
+value."""
+
+GEDCOM_TAG_CONFIRMATION = "CONF"
+"""Value: `CONF`
+
+The religious event (not LDS) of conferring the gift of the Holy Ghost and,
+among protestants, full church membership."""
+
+GEDCOM_TAG_CONFIRMATION_L = "CONL"
+"""Value: `CONL`
+
+The religious event by which a person receives membership in the LDS Church."""
GEDCOM_TAG_CONTINUED = "CONT"
"""Value: `CONT`
-An indicator that additional data belongs to the superior value. The information from the `CONT` value is to be
-connected to the value of the superior preceding line with a carriage return and/or new line character.
-Leading spaces could be important to the formatting of the resultant text. When importing values from `CONT` lines
-the reader should assume only one delimiter character following the `CONT` tag. Assume that the rest of the leading
-spaces are to be a part of the value."""
+An indicator that additional data belongs to the superior value. The information
+from the `CONT` value is to be connected to the value of the superior preceding
+line with a carriage return and/or new line character. Leading spaces could be
+important to the formatting of the resultant text. When importing values from
+`CONT` lines the reader should assume only one delimiter character following
+the `CONT` tag. Assume that the rest of the leading spaces are to be a part
+of the value."""
+
+GEDCOM_TAG_COPYRIGHT = "COPR"
+"""Value: `COPR`
+
+A statement that accompanies data to protect it from unlawful duplication
+and distribution."""
+
+GEDCOM_TAG_COPPORATE = "CORP"
+"""Value: `CORP`
+
+A name of an institution, agency, corporation, or company."""
+
+GEDCOM_TAG_CREMATION = "CREM"
+"""Value: `CREM`
+
+Disposal of the remains of a person's body by fire."""
+
+GEDCOM_TAG_COUNTRY = "CTRY"
+"""Value: `CTRY`
+
+The name or code of a country."""
+
+GEDCOM_TAG_DATA = "DATA"
+"""Value: `DATA`
+
+Pertaining to stored automation information."""
GEDCOM_TAG_DATE = "DATE"
"""Value: `DATE`
@@ -94,90 +330,539 @@
The event when mortal life terminates."""
+GEDCOM_TAG_DESCENDANTS = "DESC"
+"""Value: `DESC`
+
+Pertaining to offspring of an individual."""
+
+GEDCOM_TAG_DESCENDANTS_INT = "DESI"
+"""Value: `DESI`
+
+Indicates an interest in research to identify additional descendants of this
+individual. (See also ANCI)"""
+
+GEDCOM_TAG_DESTINATION = "DEST"
+"""Value: `DEST`
+
+A system receiving data."""
+
+GEDCOM_TAG_DIVORCE = "DIV"
+"""Value: `DIV`
+
+The event of disolving a marriage through civil action."""
+
+GEDCOM_TAG_DIVORCE_FILED = "DIVF"
+"""Value: `DIVF`
+
+An event of filing for a divorce by a spouse."""
+
+GEDCOM_TAG_PHY_DESCRIPTION = "DSCR"
+"""Value: `DSCR`
+
+The physical characteristics of a person, place, or thing."""
+
+GEDCOM_TAG_EDUCATION = "EDUC"
+"""Value: `EDUC`
+
+Indicator of a level of education attained."""
+
+GEDCOM_TAG_EMAIL = "EMAIL"
+"""Value: `EMAIL`
+
+An electronic address that can be used for contact such as an email address..."""
+
+GEDCOM_TAG_EMIGRATION = "EMIG"
+"""Value: `EMIG`
+
+An event of leaving one's homeland with the intent of residing elsewhere."""
+
+GEDCOM_TAG_ENDOWMENT = "ENDL"
+"""Value: `ENDL`
+
+A religious event where an endowment ordinance for an individual was performed
+by priesthood authority in an LDS temple."""
+
+GEDCOM_TAG_ENGAGEMENT = "ENGA"
+"""Value: `ENGA`
+
+An event of recording or announcing an agreement between two people to become
+married."""
+
+GEDCOM_TAG_EVENT = "EVEN"
+"""Value: `EVEN`
+
+A noteworthy happening related to an individual, a group, or an organization."""
+
+GEDCOM_TAG_FACT = "FACT"
+"""Value: `FACT`
+
+Pertaining to a noteworthy attribute or fact concerning an individual, a group,
+or an organization. A FACT structure is usually qualified or classified by a
+subordinate use of the TYPE tag."""
+
GEDCOM_TAG_FAMILY = "FAM"
"""Value: `FAM`.
-Identifies a legal, common law, or other customary relationship of man and woman and their children,
-if any, or a family created by virtue of the birth of a child to its biological father and mother."""
+Identifies a legal, common law, or other customary relationship of man and woman
+and their children, if any, or a family created by virtue of the birth of a
+child to its biological father and mother."""
GEDCOM_TAG_FAMILY_CHILD = "FAMC"
"""Value: `FAMC`
Identifies the family in which an individual appears as a child."""
+GEDCOM_TAG_FAMILY_FILE = "FAMF"
+"""Value: `FAMF`
+
+Pertaining to, or the name of, a family file. Names stored in a file that are
+assigned to a family for doing temple ordinance work."""
+
GEDCOM_TAG_FAMILY_SPOUSE = "FAMS"
"""Value: `FAMS`
Identifies the family in which an individual appears as a spouse."""
+GEDCOM_TAG_FAX = "FAX"
+"""Value: `FAX`
+
+A FAX telephone number appropriate for sending data facsimiles."""
+
+GEDCOM_TAG_FIRST_COMMUNION = "FCOM"
+"""Value: `FCOM`
+
+A religious rite, the first act of sharing in the Lord's supper as part of
+church worship."""
+
GEDCOM_TAG_FILE = "FILE"
"""Value: `FILE`
-An information storage place that is ordered and arranged for preservation and reference."""
+An information storage place that is ordered and arranged for preservation and
+reference."""
+
+GEDCOM_TAG_PHONETIC = "FONE"
+"""Value: `FONE`
+
+A phonetic variation of a superior text string."""
+
+GEDCOM_TAG_FORMAT = "FORM"
+"""Value: `FORM`
+
+An assigned name given to a consistent format in which information can be
+conveyed."""
+
+GEDCOM_TAG_GEDCOM = "GEDC"
+"""Value: `GEDC`
+
+Information about the use of GEDCOM in a transmission."""
GEDCOM_TAG_GIVEN_NAME = "GIVN"
"""Value: `GIVN`
A given or earned name used for official identification of a person."""
+GEDCOM_TAG_GRADUATION = "GRAD"
+"""Value: `GRAD`
+
+An event of awarding educational diplomas or degrees to individuals."""
+
+GEDCOM_TAG_HEADER = "HEAD"
+"""Value: `HEAD`
+
+Identifies information pertaining to an entire GEDCOM transmission."""
+
GEDCOM_TAG_HUSBAND = "HUSB"
"""Value: `HUSB`
An individual in the family role of a married man or father."""
+GEDCOM_TAG_IDENT_NUMBER = "IDNO"
+"""Value: `IDNO`
+
+A number assigned to identify a person within some significant external system."""
+
+GEDCOM_TAG_IMMIGRATION = "IMMI"
+"""Value: `IMMI`
+
+An event of entering into a new locality witht he intent of residing there."""
+
GEDCOM_TAG_INDIVIDUAL = "INDI"
"""Value: `INDI`
A person."""
+GEDCOM_TAG_LANGUAGE = "LANG"
+"""Value: `LANG`
+
+The name of the language used in a communication or transmission of information."""
+
+GEDCOM_TAG_LATITUDE = "LATI"
+"""Value: `LATI`
+
+A value indicating a coordinate position on a line, plane, or space."""
+
+GEDCOM_TAG_LEGATEE = "LEGA"
+"""Value: `LEGA`
+
+A role of an individual acting as a person receiving a bequest or legal devise."""
+
+GEDCOM_TAG_LONGITUDE = "LONG"
+"""Value: `LONG`
+
+A value indicating a coordinate position on a line, plane, or space."""
+
+GEDCOM_TAG_MAP = "MAP"
+"""Value: `MAP`
+
+Pertains to a representation of measurements usually presented in a graphical
+form."""
+
+GEDCOM_TAG_MARRIAGE_BANN = "MARB"
+"""Value: `MARB`.
+
+An event of an official public notice given that two people intend to marry."""
+
+GEDCOM_TAG_MARR_CONTRACT = "MARC"
+"""Value: `MARC`.
+
+An event of recording a formal agreement of marriage, including the prenuptial
+agreement in which marriage partners reach agreement about the property rights
+of one or both, securing property to their children."""
+
+GEDCOM_TAG_MARR_LICENSE = "MARL"
+"""Value: `MARL`.
+
+An event of obtaining a legal license to marry."""
+
GEDCOM_TAG_MARRIAGE = "MARR"
"""Value: `MARR`.
-A legal, common-law, or customary event of creating a family unit of a man and a woman as husband and wife."""
+A legal, common-law, or customary event of creating a family unit of a man and
+a woman as husband and wife."""
+
+GEDCOM_TAG_MARR_SETTLEMENT = "MARS"
+"""Value: `MARS`.
+
+An event of creating an agreement between two people contemplating marriage,
+at which time they agree to release or modify property rights that would
+otherwise arise from the marriage."""
+
+GEDCOM_TAG_MEDIA = "MEDI"
+"""Value: `MEDI`.
+
+Identifies information about the media or having to do with the medium in which
+information is stored."""
GEDCOM_TAG_NAME = "NAME"
"""Value: `NAME`.
-A word or combination of words used to help identify an individual, title, or other item.
-More than one NAME line should be used for people who were known by multiple names."""
+A word or combination of words used to help identify an individual, title, or
+other item. More than one NAME line should be used for people who were known
+by multiple names."""
+
+GEDCOM_TAG_NATIONALITY = "NATI"
+"""Value: `NATI`
+
+The national heritage of an individual."""
+
+GEDCOM_TAG_NATURALIZATION = "NATU"
+"""Value: `NATU`
+
+The event of obtaining citizenship."""
+
+GEDCOM_TAG_CHILDREN_COUNT = "NCHI"
+"""Value: `NCHI`
+
+The number of children that this person is known to be the parent of (all
+marriages) when subordinate to an individual, or that belong to this family
+when subordinate to a FAM_RECORD."""
+
+GEDCOM_TAG_NICKNAME = "NICK"
+"""Value: `NICK`
+
+A descriptive or familiar that is used instead of, or in addition to, one's
+proper name."""
+
+GEDCOM_TAG_MARRIAGE_COUNT = "NMR"
+"""Value: `NMR`
+
+The number of times this person has participated in a family as a spouse or
+parent."""
+
+GEDCOM_TAG_NOTE = "NOTE"
+"""Value: `NOTE`
+
+Additional information provided by the submitter for understanding the
+enclosing data."""
+
+GEDCOM_TAG_NAME_PREFIX = "NPFX"
+"""Value: `NPFX`
+
+Text which appears on a name line before the given and surname parts of a name.
+i.e. ( Lt. Cmndr. ) Joseph /Allen/ jr. In this example Lt. Cmndr. is considered
+as the name prefix portion."""
+
+GEDCOM_TAG_NAME_SUFFIX = "NSFX"
+"""Value: `NSFX`
+
+Text which appears on a name line after or behind the given and surname parts
+of a name. i.e. Lt. Cmndr. Joseph /Allen/ ( jr. ) In this example jr. is
+considered as the name suffix portion."""
GEDCOM_TAG_OBJECT = "OBJE"
"""Value: `OBJE`
-Pertaining to a grouping of attributes used in describing something. Usually referring to the data required
-to represent a multimedia object, such an audio recording, a photograph of a person, or an image of a document."""
+Pertaining to a grouping of attributes used in describing something. Usually
+referring to the data required to represent a multimedia object, such an audio
+recording, a photograph of a person, or an image of a document."""
GEDCOM_TAG_OCCUPATION = "OCCU"
"""Value: `OCCU`
The type of work or profession of an individual."""
+GEDCOM_TAG_ORDINANCE = "ORDI"
+"""Value: `ORDI`
+
+Pertaining to a religious ordinance in general."""
+
+GEDCOM_TAG_ORDINATION = "ORDN"
+"""Value: `ORDN`
+
+A religious event of receiving authority to act in religious matters."""
+
+GEDCOM_TAG_PAGE = "PAGE"
+"""Value: `PAGE`
+
+A number or description to identify where information can be found in a
+referenced work."""
+
+GEDCOM_TAG_PEDIGREE = "PEDI"
+"""Value: `PEDI`
+
+Information pertaining to an individual to parent lineage chart."""
+
+GEDCOM_TAG_PHONE = "PHON"
+"""Value: `PHON`
+
+A unique number assigned to access a specific telephone."""
+
GEDCOM_TAG_PLACE = "PLAC"
"""Value: `PLAC`
A jurisdictional name to identify the place or location of an event."""
+GEDCOM_TAG_POSTAL_CODE = "POST"
+"""Value: `POST`
+
+A code used by a postal service to identify an area to facilitate mail handling."""
+
GEDCOM_TAG_PRIVATE = "PRIV"
"""Value: `PRIV`
Flag for private address or event."""
+GEDCOM_TAG_PROBATE = "PROB"
+"""Value: `PROB`
+
+An event of judicial determination of the validity of a will. May indicate
+several related court activities over several dates."""
+
+GEDCOM_TAG_PROPERTY = "PROP"
+"""Value: `PROP`
+
+Pertaining to possessions such as real estate or other property of interest."""
+
+GEDCOM_TAG_PUBLICATION = "PUBL"
+"""Value: `PUBL`
+
+Refers to when and/or were a work was published or created."""
+
+GEDCOM_TAG_QUALITY_OF_DATA = "QUAY"
+"""Value: `QUAY`
+
+An assessment of the certainty of the evidence to support the conclusion drawn
+from evidence."""
+
+GEDCOM_TAG_REFERENCE = "REFN"
+"""Value: `REFN`
+
+A description or number used to identify an item for filing, storage, or other
+reference purposes."""
+
+GEDCOM_TAG_RELATIONSHIP = "RELA"
+"""Value: `RELA`
+
+A relationship value between the indicated contexts."""
+
+GEDCOM_TAG_RELIGION = "RELI"
+"""Value: `RELI`
+
+A religious denomination to which a person is affiliated or for which a record
+applies."""
+
+GEDCOM_TAG_REPOSITORY = "REPO"
+"""Value: `REPO`
+
+An institution or person that has the specified item as part of their
+collection(s)."""
+
+GEDCOM_TAG_RESIDENCE = "RESI"
+"""Value: `RESI`
+
+The act of dwelling at a place for a period of time."""
+
+GEDCOM_TAG_RESTRICTION = "RESN"
+"""Value: `RESN`
+
+A processing indicator signifying access to information has been denied or
+otherwise restricted."""
+
+GEDCOM_TAG_RETIREMENT = "RETI"
+"""Value: `RETI`
+
+An event of exiting an occupational relationship with an employer after a
+qualifying time period."""
+
+GEDCOM_TAG_REC_FILE_NUMBER = "RFN"
+"""Value: `RFN`
+
+A permanent number assigned to a record that uniquely identifies it within a
+known file."""
+
+GEDCOM_TAG_REC_ID_NUMBER = "RIN"
+"""Value: `RIN`
+
+A number assigned to a record by an originating automated system that can be
+used by a receiving system to report results pertaining to that record."""
+
+GEDCOM_TAG_ROLE = "ROLE"
+"""Value: `ROLE`
+
+A name given to a role played by an individual in connection with an event."""
+
+GEDCOM_TAG_ROMANIZED = "ROMN"
+"""Value: `ROMN`
+
+A romanized variation of a superior text string."""
+
GEDCOM_TAG_SEX = "SEX"
"""Value: `SEX`
Indicates the sex of an individual--male or female."""
+GEDCOM_TAG_SEALING_CHILD = "SLGC"
+"""Value: `SLGC`
+
+A religious event pertaining to the sealing of a child to his or her parents in
+an LDS temple ceremony."""
+
+GEDCOM_TAG_SEALING_SPOUSE = "SLGS"
+"""Value: `SLGS`
+
+A religious event pertaining to the sealing of a husband and wife in an LDS
+temple ceremony."""
+
GEDCOM_TAG_SOURCE = "SOUR"
"""Value: `SOUR`
The initial or original material from which information was obtained."""
+GEDCOM_TAG_SURN_PREFIX = "SPFX"
+"""Value: `SPFX`
+
+A name piece used as a non-indexing pre-part of a surname."""
+
+GEDCOM_TAG_SOC_SEC_NUMBER = "SSN"
+"""Value: `SSN`
+
+A number assigned by the United States Social Security Administration. Used for
+tax identification purposes."""
+
+GEDCOM_TAG_STATE = "STAE"
+"""Value: `STAE`
+
+A geographical division of a larger jurisdictional area, such as a State within
+the United States of America."""
+
+GEDCOM_TAG_STATUS = "STAT"
+"""Value: `STAT`
+
+An assessment of the state or condition of something."""
+
+GEDCOM_TAG_SUBMITTER = "SUBM"
+"""Value: `SUBM`
+
+An individual or organization who contributes genealogical data to a file or
+transfers it to someone else."""
+
+GEDCOM_TAG_SUBMISSION = "SUBN"
+"""Value: `SUBN`
+
+Pertains to a collection of data issued for processing."""
+
GEDCOM_TAG_SURNAME = "SURN"
"""Value: `SURN`
A family name passed on or used by members of a family."""
+GEDCOM_TAG_TEMPLE = "TEMP"
+"""Value: `TEMP`
+
+The name or code that represents the name a temple of the LDS Church."""
+
+GEDCOM_TAG_TEXT = "TEXT"
+"""Value: `TEXT`
+
+The exact wording found in an original source document."""
+
+GEDCOM_TAG_TIME = "TIME"
+"""Value: `TIME`
+
+A time value in a 24-hour clock format, including hours, minutes, and optional
+seconds, separated by a colon (:). Fractions of seconds are shown in decimal
+notation."""
+
+GEDCOM_TAG_TITLE = "TITL"
+"""Value: `TITL`
+
+A description of a specific writing or other work, such as the title of a book
+when used in a source context, or a formal designation used by an individual
+in connection with positions of royalty or other social status, such as Grand
+Duke."""
+
+GEDCOM_TAG_TRAILER = "TRLR"
+"""Value: `TRLR`
+
+At level 0, specifies the end of a GEDCOM transmission."""
+
+GEDCOM_TAG_TYPE = "TYPE"
+"""Value: `TYPE`
+
+A further qualification to the meaning of the associated superior tag. The value
+does not have any computer processing reliability. It is more in the form of a
+short one or two word note that should be displayed any time the associated data
+is displayed."""
+
+GEDCOM_TAG_VERSION = "VERS"
+"""Value: `VERS`
+
+Indicates which version of a product, item, or publication is being used or
+referenced."""
+
GEDCOM_TAG_WIFE = "WIFE"
"""Value: `WIFE`
An individual in the role as a mother and/or married woman."""
+
+GEDCOM_TAG_WEB = "WWW"
+"""Value: `WWW`
+
+World Wide Web home page."""
+
+GEDCOM_TAG_WILL = "WILL"
+"""Value: `WILL`
+
+A legal document treated as an event, by which a person disposes of his or her
+estate, to take effect after death. The event date is the date the will was
+signed while the person was alive. (See also PROBate)"""
From 8c01b6262808d7de1218a550e5e649628cf9a308 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sat, 16 May 2020 00:09:30 -0400
Subject: [PATCH 06/23] ci(manifest.in): fix missing files in the MANIFEST
check
---
MANIFEST.in | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index 88e92a9..52d3e78 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -15,6 +15,4 @@ exclude logo.png
exclude docs
recursive-exclude docs *
recursive-exclude gedcom *.md
-
-# Include GEDCOM test files
-include tests/files/*.ged
+recursive-exclude tests *
From 953a1cdf74645d5d54c9604194e1a541f6058763 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sat, 16 May 2020 00:21:49 -0400
Subject: [PATCH 07/23] feat(tags.py): add missing 5.5.1 tags plus other
program defined ones
---
gedcom/tags.py | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/gedcom/tags.py b/gedcom/tags.py
index 35676f6..1f95a18 100644
--- a/gedcom/tags.py
+++ b/gedcom/tags.py
@@ -74,7 +74,7 @@
"""Value: `_PHOTO`
Used by some programs to identify the primary multimedia object for an
-individual, the same as _PRIM."""
+individual, the same as `gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY`."""
GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED = "_PREF"
"""Value: `_PREF`
@@ -146,7 +146,7 @@
"""Value: `ANCI`
Indicates an interest in additional research for ancestors of this individual.
-(See also DESI)"""
+(See also `gedcom.tags.GEDCOM_TAG_DESCENDANTS_INT`)"""
GEDCOM_TAG_ANNULMENT = "ANUL"
"""Value: `ANUL`
@@ -168,7 +168,7 @@
"""Value: `BAPL`
The event of baptism performed at age eight or later by priesthood authority
-of the LDS Church. (See also BAPM)"""
+of the LDS Church. (See also `gedcom.tags.GEDCOM_TAG_BAPTISM`)"""
GEDCOM_TAG_BAPTISM = "BAPM"
"""Value: `BAPM`
@@ -339,7 +339,7 @@
"""Value: `DESI`
Indicates an interest in research to identify additional descendants of this
-individual. (See also ANCI)"""
+individual. (See also `gedcom.tags.GEDCOM_TAG_ANCES_INTEREST`)"""
GEDCOM_TAG_DESTINATION = "DEST"
"""Value: `DEST`
@@ -369,7 +369,7 @@
GEDCOM_TAG_EMAIL = "EMAIL"
"""Value: `EMAIL`
-An electronic address that can be used for contact such as an email address..."""
+An electronic address that can be used for contact such as an email address."""
GEDCOM_TAG_EMIGRATION = "EMIG"
"""Value: `EMIG`
@@ -397,8 +397,8 @@
"""Value: `FACT`
Pertaining to a noteworthy attribute or fact concerning an individual, a group,
-or an organization. A FACT structure is usually qualified or classified by a
-subordinate use of the TYPE tag."""
+or an organization. A `FACT` structure is usually qualified or classified by a
+subordinate use of the `gedcom.tags.GEDCOM_TAG_TYPE` tag."""
GEDCOM_TAG_FAMILY = "FAM"
"""Value: `FAM`.
@@ -557,7 +557,7 @@
"""Value: `NAME`.
A word or combination of words used to help identify an individual, title, or
-other item. More than one NAME line should be used for people who were known
+other item. More than one `NAME` line should be used for people who were known
by multiple names."""
GEDCOM_TAG_NATIONALITY = "NATI"
@@ -575,7 +575,7 @@
The number of children that this person is known to be the parent of (all
marriages) when subordinate to an individual, or that belong to this family
-when subordinate to a FAM_RECORD."""
+when subordinate to a `gedcom.tags.GEDCOM_TAG_FAMILY` record."""
GEDCOM_TAG_NICKNAME = "NICK"
"""Value: `NICK`
@@ -865,4 +865,4 @@
A legal document treated as an event, by which a person disposes of his or her
estate, to take effect after death. The event date is the date the will was
-signed while the person was alive. (See also PROBate)"""
+signed while the person was alive. (See also `gedcom.tags.GEDCOM_TAG_PROBATE`)"""
From c6a2b701708a804a6dc713eca882f0d67ec03034 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sat, 16 May 2020 00:21:49 -0400
Subject: [PATCH 08/23] feat(tags.py): add missing 5.5.1 tags plus other
program defined ones
---
gedcom/tags.py | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/gedcom/tags.py b/gedcom/tags.py
index 35676f6..1f95a18 100644
--- a/gedcom/tags.py
+++ b/gedcom/tags.py
@@ -74,7 +74,7 @@
"""Value: `_PHOTO`
Used by some programs to identify the primary multimedia object for an
-individual, the same as _PRIM."""
+individual, the same as `gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY`."""
GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED = "_PREF"
"""Value: `_PREF`
@@ -146,7 +146,7 @@
"""Value: `ANCI`
Indicates an interest in additional research for ancestors of this individual.
-(See also DESI)"""
+(See also `gedcom.tags.GEDCOM_TAG_DESCENDANTS_INT`)"""
GEDCOM_TAG_ANNULMENT = "ANUL"
"""Value: `ANUL`
@@ -168,7 +168,7 @@
"""Value: `BAPL`
The event of baptism performed at age eight or later by priesthood authority
-of the LDS Church. (See also BAPM)"""
+of the LDS Church. (See also `gedcom.tags.GEDCOM_TAG_BAPTISM`)"""
GEDCOM_TAG_BAPTISM = "BAPM"
"""Value: `BAPM`
@@ -339,7 +339,7 @@
"""Value: `DESI`
Indicates an interest in research to identify additional descendants of this
-individual. (See also ANCI)"""
+individual. (See also `gedcom.tags.GEDCOM_TAG_ANCES_INTEREST`)"""
GEDCOM_TAG_DESTINATION = "DEST"
"""Value: `DEST`
@@ -369,7 +369,7 @@
GEDCOM_TAG_EMAIL = "EMAIL"
"""Value: `EMAIL`
-An electronic address that can be used for contact such as an email address..."""
+An electronic address that can be used for contact such as an email address."""
GEDCOM_TAG_EMIGRATION = "EMIG"
"""Value: `EMIG`
@@ -397,8 +397,8 @@
"""Value: `FACT`
Pertaining to a noteworthy attribute or fact concerning an individual, a group,
-or an organization. A FACT structure is usually qualified or classified by a
-subordinate use of the TYPE tag."""
+or an organization. A `FACT` structure is usually qualified or classified by a
+subordinate use of the `gedcom.tags.GEDCOM_TAG_TYPE` tag."""
GEDCOM_TAG_FAMILY = "FAM"
"""Value: `FAM`.
@@ -557,7 +557,7 @@
"""Value: `NAME`.
A word or combination of words used to help identify an individual, title, or
-other item. More than one NAME line should be used for people who were known
+other item. More than one `NAME` line should be used for people who were known
by multiple names."""
GEDCOM_TAG_NATIONALITY = "NATI"
@@ -575,7 +575,7 @@
The number of children that this person is known to be the parent of (all
marriages) when subordinate to an individual, or that belong to this family
-when subordinate to a FAM_RECORD."""
+when subordinate to a `gedcom.tags.GEDCOM_TAG_FAMILY` record."""
GEDCOM_TAG_NICKNAME = "NICK"
"""Value: `NICK`
@@ -865,4 +865,4 @@
A legal document treated as an event, by which a person disposes of his or her
estate, to take effect after death. The event date is the date the will was
-signed while the person was alive. (See also PROBate)"""
+signed while the person was alive. (See also `gedcom.tags.GEDCOM_TAG_PROBATE`)"""
From 441a3d760bd3bcadd499cfe4bd00f8842d2d8301 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 00:26:27 -0400
Subject: [PATCH 09/23] feat: add parsing for all records and substructures and
handle ansel
Removed FileElement as duplicates role of ObjectElement. Added Source, Repository, Note, Header,
Submission, and Submitter elements to handle all the defined record types in the standard. Add
subparsers for all of the substructures defined in the standard. Added get_record method to all
record elements to parse the full record structure and return it as a dictionary. Before processing
file added encoding check to identify type. If Python Ansel module is installed use it so can now
decode Ansel Gedcoms. Verify encoding found matches encoding claimed. Get version number. Validate
if 5.5.5 and if so reject it as that standard requires as no strict 5.5.5 reader exists yet. Added
standards.py with references to the different standards and use where needed. Added Reader object to
wrap the Parser and provide get_records_by_type and get_all_records methods.
---
README.md | 4 +
gedcom/__init__.py | 5 +
gedcom/detect.py | 143 ++++++
gedcom/element/__init__.py | 9 +-
gedcom/element/family.py | 102 +++-
gedcom/element/header.py | 159 +++++++
gedcom/element/individual.py | 245 +++++++---
gedcom/element/note.py | 74 +++
gedcom/element/object.py | 84 +++-
gedcom/element/repository.py | 84 ++++
gedcom/element/source.py | 137 ++++++
gedcom/element/submission.py | 83 ++++
gedcom/element/submitter.py | 94 ++++
gedcom/errors.py | 59 +++
gedcom/gedcom.md | 1 +
gedcom/parser.py | 444 ++++--------------
gedcom/reader.py | 123 +++++
gedcom/{element/file.py => standards.py} | 23 +-
gedcom/subparsers/__init__.py | 45 ++
gedcom/subparsers/address_structure.py | 81 ++++
gedcom/subparsers/association_structure.py | 54 +++
gedcom/subparsers/change_date.py | 52 ++
gedcom/subparsers/child_to_family_link.py | 53 +++
gedcom/subparsers/event_detail.py | 85 ++++
gedcom/subparsers/family_event_detail.py | 50 ++
gedcom/subparsers/family_event_structure.py | 59 +++
.../individual_attribute_structure.py | 63 +++
gedcom/subparsers/individual_event_detail.py | 41 ++
.../subparsers/individual_event_structure.py | 104 ++++
gedcom/subparsers/lds_individual_ordinance.py | 89 ++++
gedcom/subparsers/lds_spouse_sealing.py | 80 ++++
gedcom/subparsers/multimedia_link.py | 71 +++
gedcom/subparsers/note_structure.py | 42 ++
gedcom/subparsers/personal_name_pieces.py | 70 +++
gedcom/subparsers/personal_name_structure.py | 63 +++
gedcom/subparsers/place_structure.py | 84 ++++
gedcom/subparsers/source_citation.py | 93 ++++
.../subparsers/source_repository_citation.py | 56 +++
gedcom/subparsers/spouse_to_family_link.py | 43 ++
gedcom/subparsers/user_reference_number.py | 42 ++
gedcom/tags.py | 91 +++-
tests/element/test_file.py | 9 -
tests/element/test_header.py | 9 +
tests/element/test_note.py | 9 +
tests/element/test_repository.py | 9 +
tests/element/test_source.py | 9 +
tests/element/test_submission.py | 9 +
tests/element/test_submitter.py | 9 +
48 files changed, 2992 insertions(+), 455 deletions(-)
create mode 100644 gedcom/detect.py
create mode 100644 gedcom/element/header.py
create mode 100644 gedcom/element/note.py
create mode 100644 gedcom/element/repository.py
create mode 100644 gedcom/element/source.py
create mode 100644 gedcom/element/submission.py
create mode 100644 gedcom/element/submitter.py
create mode 100644 gedcom/errors.py
create mode 100644 gedcom/reader.py
rename gedcom/{element/file.py => standards.py} (63%)
create mode 100644 gedcom/subparsers/__init__.py
create mode 100644 gedcom/subparsers/address_structure.py
create mode 100644 gedcom/subparsers/association_structure.py
create mode 100644 gedcom/subparsers/change_date.py
create mode 100644 gedcom/subparsers/child_to_family_link.py
create mode 100644 gedcom/subparsers/event_detail.py
create mode 100644 gedcom/subparsers/family_event_detail.py
create mode 100644 gedcom/subparsers/family_event_structure.py
create mode 100644 gedcom/subparsers/individual_attribute_structure.py
create mode 100644 gedcom/subparsers/individual_event_detail.py
create mode 100644 gedcom/subparsers/individual_event_structure.py
create mode 100644 gedcom/subparsers/lds_individual_ordinance.py
create mode 100644 gedcom/subparsers/lds_spouse_sealing.py
create mode 100644 gedcom/subparsers/multimedia_link.py
create mode 100644 gedcom/subparsers/note_structure.py
create mode 100644 gedcom/subparsers/personal_name_pieces.py
create mode 100644 gedcom/subparsers/personal_name_structure.py
create mode 100644 gedcom/subparsers/place_structure.py
create mode 100644 gedcom/subparsers/source_citation.py
create mode 100644 gedcom/subparsers/source_repository_citation.py
create mode 100644 gedcom/subparsers/spouse_to_family_link.py
create mode 100644 gedcom/subparsers/user_reference_number.py
delete mode 100644 tests/element/test_file.py
create mode 100644 tests/element/test_header.py
create mode 100644 tests/element/test_note.py
create mode 100644 tests/element/test_repository.py
create mode 100644 tests/element/test_source.py
create mode 100644 tests/element/test_submission.py
create mode 100644 tests/element/test_submitter.py
diff --git a/README.md b/README.md
index 4be15cb..e18505a 100644
--- a/README.md
+++ b/README.md
@@ -72,11 +72,15 @@ was licensed under the GPL v2 and then continued by
The project was taken over by [Nicklas Reincke](https://github.com/nickreynke) in 2018.
Together with [Damon Brodie](https://github.com/nomadyow) a lot of changes were made and the parser was optimized.
+Ansel support, additional tags, and extensive record and substructure level parsing support were added by
+[Christopher Horn](https://github.com/cdhorn) in 2020.
+
## License
Licensed under the [GNU General Public License v2](http://www.gnu.org/licenses/gpl-2.0.html)
**Python GEDCOM Parser**
+ Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
Copyright (C) 2016 Andreas Oberritter
diff --git a/gedcom/__init__.py b/gedcom/__init__.py
index 386a74b..6fee00a 100644
--- a/gedcom/__init__.py
+++ b/gedcom/__init__.py
@@ -34,8 +34,13 @@
__all__ = [
# Subpackages
"element",
+ "subparsers",
# Modules
+ "errors",
"helpers",
+ "detect",
"parser",
+ "reader",
+ "standards",
"tags"
]
diff --git a/gedcom/detect.py b/gedcom/detect.py
new file mode 100644
index 0000000..9034ca6
--- /dev/null
+++ b/gedcom/detect.py
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Functions to detect GEDCOM encoding and version.
+"""
+
+import chardet
+
+import gedcom.standards as standards
+
+from gedcom.errors import GedcomFormatViolationError
+from gedcom.errors import GedcomCharacterSetUnsupportedError
+
+try:
+ import ansel
+ ansel.register()
+ ANSEL_AVAILABLE = True
+except ModuleNotFoundError:
+ ANSEL_AVAILABLE = False
+
+def validate_encoding(file_path, codec):
+ """Check the encoding is compatible with the encoding reported
+ :type file_path: str
+ :type codec: str
+ """
+ with open(file_path, 'r', encoding=codec) as gedcom_data:
+ for line in gedcom_data:
+ if 'CHAR' in line:
+ character_set = line.split(' ')[2].lower().strip()
+ break
+
+ if character_set == 'ansel' and codec == 'gedcom':
+ return
+
+ if character_set == 'ascii' and codec == 'utf-8':
+ return
+
+ if character_set not in codec:
+ errmsg = "A " + codec + " encoding was detected but the GEDCOM reports using " + \
+ "a " + character_set + " encoding.\n" + \
+ "Processing aborted as unsure how to properly proceed.\n" + \
+ "See: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomCharacterSetUnsupportedError(errmsg)
+
+def get_encoding(file_path):
+ """Examines file to determine encoding to use and then validates it
+ :type file_path: str
+ :rtype: str
+ """
+ with open(file_path, 'rb') as gedcom_data:
+ sample_data = gedcom_data.read(262144)
+
+ # Note chardet reports Ansel as ISO-8859-1 or ISO-8859-2 at this time
+ # depending on sample size, and could be making a faulty assumption here
+ # by treating it as Ansel. The ansel module supports both ansel and a
+ # gedcom codec with some gedcom specific extensions so we use that.
+ codec = 'unknown'
+ probe = chardet.detect(sample_data)
+ if probe['encoding'] == 'utf-8':
+ codec = 'utf-8-sig'
+ elif probe['encoding'] == 'utf-16':
+ codec = 'utf-16'
+ elif probe['encoding'] == 'ascii':
+ codec = 'ascii'
+ elif probe['encoding'] == 'ansel':
+ codec = 'ansel'
+ elif 'ISO-8859' in probe['encoding']:
+ if ANSEL_AVAILABLE:
+ codec = 'gedcom'
+ else:
+ errmsg = "This parser supports ANSEL but the Python ansel module is not " + \
+ "available at this time.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomCharacterSetUnsupportedError(errmsg)
+
+ if codec == 'unknown':
+ errmsg = "Unable to properly identify a supported GEDCOM character encoding for" + \
+ "the file.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomCharacterSetUnsupportedError(errmsg)
+
+ validate_encoding(file_path, codec)
+ return codec
+
+def get_version(file_path, codec):
+ """Probes Gedcom to identify version used, should expand this in future
+ Returns probed version, reported version, reported format
+ :type file_path: str
+ :type encoding: str
+ :rtype: str, str, str
+ """
+ in_gedc_tag = False
+ gedcom_version = None
+ gedcom_format = None
+ with open(file_path, 'r', encoding=codec) as gedcom_data:
+ for line in gedcom_data:
+ if '1 GEDC' in line:
+ in_gedc_tag = True
+ continue
+ if in_gedc_tag:
+ if '2 VERS' in line:
+ gedcom_version = line.split(' ')[2].strip()
+ continue
+ if '2 FORM' in line:
+ gedcom_format = line.split(' ')[2].strip()
+ break
+
+ if gedcom_version is None or gedcom_format is None:
+ errmsg = "Malformed GEDCOM file, the required version number or format were" + \
+ " not found as expected.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
+
+ real_version = gedcom_version
+
+ # UTF came in the 5.5.1 specification
+ if gedcom_version == '5.5' and 'utf' in codec:
+ real_version = gedcom_version
+
+ return real_version, gedcom_version, gedcom_format
diff --git a/gedcom/element/__init__.py b/gedcom/element/__init__.py
index 34eaac5..4360a26 100644
--- a/gedcom/element/__init__.py
+++ b/gedcom/element/__init__.py
@@ -33,8 +33,13 @@
__all__ = [
"element",
"family",
- "file",
+ "header",
"individual",
+ "note",
"object",
- "root"
+ "repository",
+ "root",
+ "source",
+ "submission",
+ "submitter"
]
diff --git a/gedcom/element/family.py b/gedcom/element/family.py
index c91b5a9..c5f92ff 100644
--- a/gedcom/element/family.py
+++ b/gedcom/element/family.py
@@ -2,6 +2,7 @@
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -25,17 +26,104 @@
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""GEDCOM element consisting of tag `gedcom.tags.GEDCOM_TAG_FAMILY`"""
+"""
+GEDCOM element for a `FAM_RECORD` family record identified by the
+`gedcom.tags.GEDCOM_TAG_FAMILY` tag.
+"""
+import gedcom.tags as tags
from gedcom.element.element import Element
-import gedcom.tags
-
-
-class NotAnActualFamilyError(Exception):
- pass
+from gedcom.subparsers.family_event_structure import family_event_structure
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.lds_spouse_sealing import lds_spouse_sealing
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.multimedia_link import multimedia_link
+from gedcom.subparsers.user_reference_number import user_reference_number
+FAMILY_SINGLE_TAGS = {
+ tags.GEDCOM_TAG_WIFE: 'key_to_wife',
+ tags.GEDCOM_TAG_HUSBAND: 'key_to_husband',
+ tags.GEDCOM_TAG_CHILDREN_COUNT: 'number_of_children',
+ tags.GEDCOM_TAG_RESTRICTION: 'restriction',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id'
+}
class FamilyElement(Element):
+ """Element associated with a `FAM_RECORD`"""
def get_tag(self):
- return gedcom.tags.GEDCOM_TAG_FAMILY
+ return tags.GEDCOM_TAG_FAMILY
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': self.get_pointer(),
+ 'restriction': '',
+ 'events': family_event_structure(self),
+ 'key_to_husband': '',
+ 'key_to_wife': '',
+ 'children': [],
+ 'number_of_children': '',
+ 'submitters': [],
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ lds_events = lds_spouse_sealing(self)
+ if len(lds_events) > 0:
+ for event in lds_events:
+ record['events'].append(event)
+
+ for child in self.get_child_elements():
+ if child.get_tag() in FAMILY_SINGLE_TAGS:
+ record[FAMILY_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHILD:
+ entry = {
+ 'key_to_child': child.get_value(),
+ 'relationship_to_father': '',
+ 'relationship_to_mother': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
+ entry['relationship_to_father'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
+ entry['relationship_to_mother'] = gchild.get_value()
+
+ record['children'].append(entry)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SUBMITTER:
+ record['submitters'].append(child.get_value())
+ continue
+
+ return record
diff --git a/gedcom/element/header.py b/gedcom/element/header.py
new file mode 100644
index 0000000..943ea9b
--- /dev/null
+++ b/gedcom/element/header.py
@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `HEADER` header record identified by the
+`gedcom.tags.GEDCOM_TAG_HEADER` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+
+HEADER_TAGS = {
+ tags.GEDCOM_TAG_DESTINATION: 'destination',
+ tags.GEDCOM_TAG_SUBMITTER: 'key_to_submitter',
+ tags.GEDCOM_TAG_SUBMISSION: 'key_to_submission',
+ tags.GEDCOM_TAG_FILE: 'file',
+ tags.GEDCOM_TAG_COPYRIGHT: 'copyright',
+ tags.GEDCOM_TAG_LANGUAGE: 'language',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON: 'key_to_home_person'
+}
+
+class HeaderElement(Element):
+ """Element associated with a `HEADER`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_HEADER
+
+ def get_record(self):
+ """Parse and return the full record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'source': '',
+ 'product': {
+ 'version': '',
+ 'name': '',
+ 'corporation': '',
+ 'address': {}
+ },
+ 'data': {
+ 'source_data': '',
+ 'published': '',
+ 'copyright': ''
+ },
+ 'destination': '',
+ 'transmission_date': '',
+ 'transmission_time': '',
+ 'key_to_submitter': '',
+ 'key_to_submission': '',
+ 'file': '',
+ 'copyright': '',
+ 'gedcom': {
+ 'version': '',
+ 'format': '',
+ },
+ 'character_set': '',
+ 'character_set_version': '',
+ 'language': '',
+ 'place_hierarchy': '',
+ 'key_to_home_person': '',
+ 'notes': []
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['source'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_VERSION:
+ record['product']['version'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['product']['name'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_CORPORATE:
+ record['product']['corporation'] = gchild.get_value()
+
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['product']['address'] = address_structure(gchild)
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATA:
+ record['data']['source_data'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['data']['published'] = ggchild.get_value()
+ continue
+
+ if ggchild.get_tag() == tags.GEDCOM_TAG_COPYRIGHT:
+ record['data']['copyright'] = ggchild.get_multi_line_value()
+ continue
+ continue
+
+ if child.get_tag() in HEADER_TAGS:
+ record[HEADER_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['transmission_date'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TIME:
+ record['transmission_time'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_GEDCOM:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_VERSION:
+ record['gedcom']['version'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['gedcom']['format'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHARACTER:
+ record['character_set'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_VERSION:
+ record['character_set_version'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PLACE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['place_hierarchy'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
diff --git a/gedcom/element/individual.py b/gedcom/element/individual.py
index da61d08..d9e2b40 100644
--- a/gedcom/element/individual.py
+++ b/gedcom/element/individual.py
@@ -2,6 +2,7 @@
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -25,29 +26,138 @@
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""GEDCOM element consisting of tag `gedcom.tags.GEDCOM_TAG_INDIVIDUAL`"""
+"""
+GEDCOM element for a `INDIVIDUAL_RECORD` individual record identified by the
+`gedcom.tags.GEDCOM_TAG_INDIVIDUAL` tag.
+"""
import re as regex
+import gedcom.tags as tags
from gedcom.element.element import Element
+from gedcom.subparsers.personal_name_structure import personal_name_structure
+from gedcom.subparsers.individual_event_structure import individual_event_structure
+from gedcom.subparsers.individual_attribute_structure import individual_attribute_structure
+from gedcom.subparsers.lds_individual_ordinance import lds_individual_ordinance
+from gedcom.subparsers.child_to_family_link import child_to_family_link
+from gedcom.subparsers.spouse_to_family_link import spouse_to_family_link
+from gedcom.subparsers.association_structure import association_structure
+from gedcom.subparsers.user_reference_number import user_reference_number
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.multimedia_link import multimedia_link
from gedcom.helpers import deprecated
-import gedcom.tags
-
-
-class NotAnActualIndividualError(Exception):
- pass
+INDIVIDUAL_SINGLE_TAGS = {
+ tags.GEDCOM_TAG_RESTRICTION: 'restriction',
+ tags.GEDCOM_TAG_SEX: 'sex',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id',
+ tags.GEDCOM_TAG_REC_FILE_NUMBER: 'permanent_file_number',
+ tags.GEDCOM_TAG_AFN: 'ancestral_file_number'
+}
class IndividualElement(Element):
+ """Element associated with an `INDIVIDUAL_RECORD`"""
def get_tag(self):
- return gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ return tags.GEDCOM_TAG_INDIVIDUAL
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': self.get_pointer(),
+ 'restriction': '',
+ 'names': [],
+ 'sex': 'U',
+ 'events': individual_event_structure(self),
+ 'attributes': individual_attribute_structure(self),
+ 'child_to_family': [],
+ 'spouse_to_family': [],
+ 'submitters': [],
+ 'associates': [],
+ 'aliases': [],
+ 'ancestors_interest': [],
+ 'descendants_interest': [],
+ 'permanent_file_number': '',
+ 'ancestral_file_number': '',
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ lds_events = lds_individual_ordinance(self)
+ if len(lds_events) > 0:
+ for event in lds_events:
+ record['events'].append(event)
+
+ for child in self.get_child_elements():
+ if child.get_tag() in INDIVIDUAL_SINGLE_TAGS:
+ record[INDIVIDUAL_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['names'].append(personal_name_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['child_to_family'].append(child_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_SPOUSE:
+ record['spouse_to_family'].append(spouse_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SUBMITTER:
+ record['submitters'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ASSOCIATES:
+ record['associates'].append(association_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ALIAS:
+ record['aliases'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ANCES_INTEREST:
+ record['ancestors_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DESCENDANTS_INT:
+ record['descendants_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['changed'] = change_date(child)
+
+ return record
def is_deceased(self):
"""Checks if this individual is deceased
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
return True
return False
@@ -59,7 +169,7 @@ def is_child(self):
found_child = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
found_child = True
return found_child
@@ -69,7 +179,7 @@ def is_private(self):
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
+ if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
private = child.get_value()
if private == 'Y':
return True
@@ -83,13 +193,14 @@ def get_name(self):
given_name = ""
surname = ""
- # Return the first gedcom.tags.GEDCOM_TAG_NAME that is found.
- # Alternatively as soon as we have both the gedcom.tags.GEDCOM_TAG_GIVEN_NAME and _SURNAME return those.
+ # Return the first tags.GEDCOM_TAG_NAME that is found.
+ # Alternatively as soon as we have both the tags.GEDCOM_TAG_GIVEN_NAME
+ # and _SURNAME return those.
found_given_name = False
found_surname_name = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_NAME:
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
# Some GEDCOM files don't use child tags but instead
# place the name in the value of the NAME tag.
if child.get_value() != "":
@@ -102,14 +213,14 @@ def get_name(self):
return given_name, surname
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
- given_name = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
+ given_name = gchild.get_value()
found_given_name = True
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
- surname = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
+ surname = gchild.get_value()
found_surname_name = True
if found_given_name and found_surname_name:
@@ -119,7 +230,8 @@ def get_name(self):
return given_name, surname
def get_all_names(self):
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == gedcom.tags.GEDCOM_TAG_NAME]
+ """Return all names"""
+ return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
def surname_match(self, surname_to_match):
"""Matches a string with the surname of an individual
@@ -153,13 +265,14 @@ def get_gender(self):
gender = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_SEX:
+ if child.get_tag() == tags.GEDCOM_TAG_SEX:
gender = child.get_value()
return gender
def get_birth_data(self):
- """Returns the birth data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
+ """Returns the birth data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
:rtype: tuple
"""
date = ""
@@ -167,17 +280,17 @@ def get_birth_data(self):
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -188,10 +301,10 @@ def get_birth_year(self):
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -210,14 +323,14 @@ def get_death_data(self):
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -228,10 +341,10 @@ def get_death_year(self):
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -258,17 +371,17 @@ def get_burial_data(self):
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BURIAL:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -287,22 +400,22 @@ def get_census_data(self):
census = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
+ if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
date = ''
place = ''
sources = []
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
census.append((date, place, sources))
@@ -315,10 +428,10 @@ def get_last_change_date(self):
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CHANGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
return date
@@ -329,7 +442,7 @@ def get_occupation(self):
occupation = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
+ if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
occupation = child.get_value()
return occupation
diff --git a/gedcom/element/note.py b/gedcom/element/note.py
new file mode 100644
index 0000000..bf4da62
--- /dev/null
+++ b/gedcom/element/note.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `NOTE_RECORD` note record identified by the
+`gedcom.tags.GEDCOM_TAG_NOTE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.user_reference_number import user_reference_number
+
+class NoteElement(Element):
+ """Element associated with a `NOTE_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_NOTE
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_note': self.get_pointer(),
+ 'note': self.get_multi_line_value(),
+ 'references': [],
+ 'record_id': '',
+ 'citations': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
diff --git a/gedcom/element/object.py b/gedcom/element/object.py
index 0090e2f..e1be7fa 100644
--- a/gedcom/element/object.py
+++ b/gedcom/element/object.py
@@ -2,6 +2,7 @@
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -25,20 +26,83 @@
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""GEDCOM element consisting of tag `gedcom.tags.GEDCOM_TAG_OBJECT`"""
+"""
+GEDCOM element for a `MULTIMEDIA_RECORD` media record identified by the
+`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
+"""
+import gedcom.tags as tags
from gedcom.element.element import Element
-import gedcom.tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.user_reference_number import user_reference_number
+class ObjectElement(Element):
+ """Element associated with a `MULTIMEDIA_RECORD`"""
-class NotAnActualObjectError(Exception):
- pass
+ def get_tag(self):
+ return tags.GEDCOM_TAG_OBJECT
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_object': self.get_pointer(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'references': [],
+ 'record_id': '',
+ 'citations': [],
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
-class ObjectElement(Element):
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
- def is_object(self):
- """Checks if this element is an actual object
- :rtype: bool
- """
- return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_TITLE:
+ record['title'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
diff --git a/gedcom/element/repository.py b/gedcom/element/repository.py
new file mode 100644
index 0000000..9136818
--- /dev/null
+++ b/gedcom/element/repository.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `REPOSITORY_RECORD` repository record identified by the
+`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.user_reference_number import user_reference_number
+
+class RepositoryElement(Element):
+ """Element associated with a `REPOSITORY_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_REPOSITORY
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_repository': self.get_pointer(),
+ 'name': '',
+ 'address': {},
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': []
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['name'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(self)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
diff --git a/gedcom/element/source.py b/gedcom/element/source.py
new file mode 100644
index 0000000..dce1581
--- /dev/null
+++ b/gedcom/element/source.py
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `SOURCE_RECORD` source record identified by the
+`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.multimedia_link import multimedia_link
+from gedcom.subparsers.user_reference_number import user_reference_number
+from gedcom.subparsers.source_repository_citation import source_repository_citation
+
+SOURCE_PLURAL_TAGS = {
+ tags.GEDCOM_TAG_AUTHOR: 'author',
+ tags.GEDCOM_TAG_TITLE: 'title',
+ tags.GEDCOM_TAG_PUBLICATION: 'publication',
+ tags.GEDCOM_TAG_TEXT: 'text'
+}
+
+SOURCE_SINGLE_TAGS = {
+ tags.GEDCOM_TAG_ABBREVIATION: 'abbreviation',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_APID: 'apid'
+}
+
+class SourceElement(Element):
+ """Element associated with a SOURCE_RECORD"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_SOURCE
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_source': self.get_pointer(),
+ 'data': {
+ 'events': '',
+ 'date': '',
+ 'place': '',
+ 'agency': '',
+ 'notes': []
+ },
+ 'author': '',
+ 'title': '',
+ 'abbreviation': '',
+ 'publication': '',
+ 'text': '',
+ 'repository': {},
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'media': [],
+ 'apid': ''
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() in SOURCE_PLURAL_TAGS:
+ record[SOURCE_PLURAL_TAGS[child.get_tag()]] = child.get_multi_line_value()
+ continue
+
+ if child.get_tag() in SOURCE_SINGLE_TAGS:
+ record[SOURCE_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REPOSITORY:
+ record['repository'] = source_repository_citation(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATA:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_EVENT:
+ record['data']['events'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['data']['date'] = ggchild.get_value()
+ continue
+
+ if ggchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ record['data']['place'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGENCY:
+ record['data']['agency'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['data']['notes'].append(note_structure(gchild))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+ continue
+
+ return record
diff --git a/gedcom/element/submission.py b/gedcom/element/submission.py
new file mode 100644
index 0000000..9cb01f6
--- /dev/null
+++ b/gedcom/element/submission.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `SUBMISSION_RECORD` submission record identified by the
+`gedcom.tags.GEDCOM_TAG_SUBMISSION` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.change_date import change_date
+
+SUBMISSION_TAGS = {
+ tags.GEDCOM_TAG_SUBMITTER: 'key_to_submitter',
+ tags.GEDCOM_TAG_FAMILY_FILE: 'family_file',
+ tags.GEDCOM_TAG_TEMPLE: 'temple',
+ tags.GEDCOM_TAG_ANCESTORS: 'generations_of_ancestors',
+ tags.GEDCOM_TAG_DESCENDANTS: 'generations_of_decendants',
+ tags.GEDCOM_TAG_ORDINANCE: 'ordinance_process_flag',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id'
+}
+
+class SubmissionElement(Element):
+ """Element associated with a `SUBMISSION_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_SUBMISSION
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_submission': self.get_pointer(),
+ 'key_to_submitter': '',
+ 'family_file': '',
+ 'temple': '',
+ 'generations_of_ancestors': '',
+ 'generations_of_descendants': '',
+ 'ordinance_process_flag': '',
+ 'record_id': '',
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() in SUBMISSION_TAGS:
+ record[SUBMISSION_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
diff --git a/gedcom/element/submitter.py b/gedcom/element/submitter.py
new file mode 100644
index 0000000..44261f9
--- /dev/null
+++ b/gedcom/element/submitter.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `SUBMITTER_RECORD` submitter record identified by the
+`gedcom.tags.GEDCOM_TAG_SUBMITTER` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.multimedia_link import multimedia_link
+
+class SubmitterElement(Element):
+ """Element associated with a `SUBMITTER_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_SUBMITTER
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_submitter': self.get_pointer(),
+ 'name': '',
+ 'address': {},
+ 'media': [],
+ 'language': '',
+ 'registered_file_number': '',
+ 'record_id': '',
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['name'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(self)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_LANGUAGE:
+ record['language'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_FILE_NUMBER:
+ record['registered_file_number'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
diff --git a/gedcom/errors.py b/gedcom/errors.py
new file mode 100644
index 0000000..95529c0
--- /dev/null
+++ b/gedcom/errors.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Module containing the exception handling classes.
+"""
+
+class GedcomFormatViolationError(Exception):
+ """Raised when the document format does not appear to conform
+ to the standard and strict parsing required.
+ """
+
+class GedcomStructureViolationError(Exception):
+ """Raised when the structure of a record does not conform to
+ the standard.
+ """
+
+class GedcomCharacterSetUnsupportedError(Exception):
+ """Raised when a Gedcom appears to contain a character set
+ the parser is not yet able to support.
+ """
+
+class GedcomVersionUnsupportedError(Exception):
+ """Raised when a particular Gedcom version is not supported
+ by the parser and the standard for the version requires the
+ parser to reject it.
+ """
+
+class GedcomFormatUnsupportedError(Exception):
+ """Raised if the GEDCOM format is not recognized by the
+ parser. Note some misspellings as documented on page 148
+ in the 5.5.5 standard are treated as LINEAGE-LINKED and
+ allowed.
+ """
diff --git a/gedcom/gedcom.md b/gedcom/gedcom.md
index 56076be..e09365a 100644
--- a/gedcom/gedcom.md
+++ b/gedcom/gedcom.md
@@ -82,6 +82,7 @@ Disabling strict parsing will allow the parser to gracefully handle the followin
Licensed under the [GNU General Public License v2](http://www.gnu.org/licenses/gpl-2.0.html)
**Python GEDCOM Parser**
+ Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
Copyright (C) 2016 Andreas Oberritter
diff --git a/gedcom/parser.py b/gedcom/parser.py
index 473ad9e..f0bbcf7 100644
--- a/gedcom/parser.py
+++ b/gedcom/parser.py
@@ -2,6 +2,7 @@
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -26,35 +27,51 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Module containing the actual `gedcom.parser.Parser` used to generate elements - out of each line -
-which can in return be manipulated.
+Module containing the actual `gedcom.parser.Parser` used to generate elements
+out of each line - which can in return be manipulated.
"""
import re as regex
-from sys import version_info
+
+import gedcom.tags as tags
+import gedcom.standards as standards
+
+from gedcom.detect import get_encoding, get_version
from gedcom.element.element import Element
-from gedcom.element.family import FamilyElement, NotAnActualFamilyError
-from gedcom.element.file import FileElement
-from gedcom.element.individual import IndividualElement, NotAnActualIndividualError
+from gedcom.element.header import HeaderElement
+from gedcom.element.family import FamilyElement
+from gedcom.element.individual import IndividualElement
+from gedcom.element.note import NoteElement
from gedcom.element.object import ObjectElement
+from gedcom.element.source import SourceElement
+from gedcom.element.submission import SubmissionElement
+from gedcom.element.submitter import SubmitterElement
+from gedcom.element.repository import RepositoryElement
from gedcom.element.root import RootElement
-import gedcom.tags
-
-FAMILY_MEMBERS_TYPE_ALL = "ALL"
-FAMILY_MEMBERS_TYPE_CHILDREN = gedcom.tags.GEDCOM_TAG_CHILD
-FAMILY_MEMBERS_TYPE_HUSBAND = gedcom.tags.GEDCOM_TAG_HUSBAND
-FAMILY_MEMBERS_TYPE_PARENTS = "PARENTS"
-FAMILY_MEMBERS_TYPE_WIFE = gedcom.tags.GEDCOM_TAG_WIFE
-
-class GedcomFormatViolationError(Exception):
- pass
-
-
-class Parser(object):
+from gedcom.errors import GedcomVersionUnsupportedError
+from gedcom.errors import GedcomFormatUnsupportedError
+from gedcom.errors import GedcomFormatViolationError
+
+ERROR_TEMPLATE = "Line <{0}:{1}> of document violates GEDCOM format {2}\nSee: {3}"
+
+RECORD_ELEMENTS = {
+ tags.GEDCOM_TAG_HEADER: HeaderElement,
+ tags.GEDCOM_TAG_INDIVIDUAL: IndividualElement,
+ tags.GEDCOM_TAG_FAMILY: FamilyElement,
+ tags.GEDCOM_TAG_NOTE: NoteElement,
+ tags.GEDCOM_TAG_OBJECT: ObjectElement,
+ tags.GEDCOM_TAG_SOURCE: SourceElement,
+ tags.GEDCOM_TAG_SUBMISSION: SubmissionElement,
+ tags.GEDCOM_TAG_SUBMITTER: SubmitterElement,
+ tags.GEDCOM_TAG_REPOSITORY: RepositoryElement
+}
+
+class Parser():
"""Parses and manipulates GEDCOM 5.5 format data
- For documentation of the GEDCOM 5.5 format, see: http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
+ For documentation of the GEDCOM 5.5 format, see:
+ http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
This parser reads and parses a GEDCOM file.
@@ -70,8 +87,9 @@ def __init__(self):
self.__root_element = RootElement()
def invalidate_cache(self):
- """Empties the element list and dictionary to cause `gedcom.parser.Parser.get_element_list()`
- and `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
+ """Empties the element list and dictionary to cause
+ `gedcom.parser.Parser.get_element_list()` and
+ `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
The update gets deferred until each of the methods actually gets called.
"""
@@ -84,10 +102,11 @@ def get_element_list(self):
By default elements are in the same order as they appeared in the file.
This list gets generated on-the-fly, but gets cached. If the database
- was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once to let this
- method return updated data.
+ was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once
+ to let this method return updated data.
- Consider using `gedcom.parser.Parser.get_root_element()` or `gedcom.parser.Parser.get_root_child_elements()` to access
+ Consider using `gedcom.parser.Parser.get_root_element()` or
+ `gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
:rtype: list of Element
@@ -98,7 +117,8 @@ def get_element_list(self):
return self.__element_list
def get_element_dictionary(self):
- """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file
+ """Returns a dictionary containing all elements, identified by a pointer,
+ from within the GEDCOM file
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -111,7 +131,8 @@ def get_element_dictionary(self):
"""
if not self.__element_dictionary:
self.__element_dictionary = {
- element.get_pointer(): element for element in self.get_root_child_elements() if element.get_pointer()
+ element.get_pointer():
+ element for element in self.get_root_child_elements() if element.get_pointer()
}
return self.__element_dictionary
@@ -139,7 +160,21 @@ def parse_file(self, file_path, strict=True):
:type file_path: str
:type strict: bool
"""
- with open(file_path, 'rb') as gedcom_stream:
+ codec = get_encoding(file_path)
+ real_version, reported_version, reported_format = get_version(file_path, codec)
+
+ if reported_version == '5.5.5':
+ errmsg = "This parser does not properly support the GEDCOM " + reported_version + \
+ " standard at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomVersionUnsupportedError(errmsg)
+
+ if reported_format not in ['LINEAGE-LINKED', 'LINEAGE_LINKED',
+ 'LINAGE-LINKED', 'Lineage - Linked']:
+ errmsg = "This parser does not recognize the GEDCOM format " + reported_format + \
+ " at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomFormatUnsupportedError(errmsg)
+
+ with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
def parse(self, gedcom_stream, strict=True):
@@ -154,7 +189,7 @@ def parse(self, gedcom_stream, strict=True):
last_element = self.get_root_element()
for line in gedcom_stream:
- last_element = self.__parse_line(line_number, line.decode('utf-8-sig'), last_element, strict)
+ last_element = self.__parse_line(line_number, line, last_element, strict)
line_number += 1
# Private methods
@@ -190,43 +225,43 @@ def __parse_line(line_number, line, last_element, strict=True):
end_of_line_regex = '([\r\n]{1,2})'
# Complete regex
- gedcom_line_regex = level_regex + pointer_regex + tag_regex + value_regex + end_of_line_regex
+ gedcom_line_regex = level_regex + pointer_regex + tag_regex + \
+ value_regex + end_of_line_regex
regex_match = regex.match(gedcom_line_regex, line)
if regex_match is None:
if strict:
- error_message = ("Line <%d:%s> of document violates GEDCOM format 5.5" % (line_number, line)
- + "\nSee: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdf")
- raise GedcomFormatViolationError(error_message)
+ errmsg = ERROR_TEMPLATE.format(line_number, line, '5.5.1', standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
+
+ # Quirk check - see if this is a line without a CRLF (which could be the last line)
+ last_line_regex = level_regex + pointer_regex + tag_regex + value_regex
+ regex_match = regex.match(last_line_regex, line)
+ if regex_match is not None:
+ line_parts = regex_match.groups()
+
+ level = int(line_parts[0])
+ pointer = line_parts[1].rstrip(' ')
+ tag = line_parts[2]
+ value = line_parts[3][1:]
+ crlf = '\n'
else:
- # Quirk check - see if this is a line without a CRLF (which could be the last line)
- last_line_regex = level_regex + pointer_regex + tag_regex + value_regex
- regex_match = regex.match(last_line_regex, line)
- if regex_match is not None:
- line_parts = regex_match.groups()
-
- level = int(line_parts[0])
- pointer = line_parts[1].rstrip(' ')
- tag = line_parts[2]
- value = line_parts[3][1:]
- crlf = '\n'
- else:
- # Quirk check - Sometimes a gedcom has a text field with a CR.
- # This creates a line without the standard level and pointer.
- # If this is detected then turn it into a CONC or CONT.
- line_regex = '([^\n\r]*|)'
- cont_line_regex = line_regex + end_of_line_regex
- regex_match = regex.match(cont_line_regex, line)
- line_parts = regex_match.groups()
- level = last_element.get_level()
- tag = last_element.get_tag()
- pointer = None
- value = line_parts[0][1:]
- crlf = line_parts[1]
- if tag != gedcom.tags.GEDCOM_TAG_CONTINUED and tag != gedcom.tags.GEDCOM_TAG_CONCATENATION:
- # Increment level and change this line to a CONC
- level += 1
- tag = gedcom.tags.GEDCOM_TAG_CONCATENATION
+ # Quirk check - Sometimes a gedcom has a text field with a CR.
+ # This creates a line without the standard level and pointer.
+ # If this is detected then turn it into a CONC or CONT.
+ line_regex = '([^\n\r]*|)'
+ cont_line_regex = line_regex + end_of_line_regex
+ regex_match = regex.match(cont_line_regex, line)
+ line_parts = regex_match.groups()
+ level = last_element.get_level()
+ tag = last_element.get_tag()
+ pointer = None
+ value = line_parts[0][1:]
+ crlf = line_parts[1]
+ if tag not in [tags.GEDCOM_TAG_CONTINUED, tags.GEDCOM_TAG_CONCATENATION]:
+ # Increment level and change this line to a CONC
+ level += 1
+ tag = tags.GEDCOM_TAG_CONCATENATION
else:
line_parts = regex_match.groups()
@@ -238,20 +273,14 @@ def __parse_line(line_number, line, last_element, strict=True):
# Check level: should never be more than one higher than previous line.
if level > last_element.get_level() + 1:
- error_message = ("Line %d of document violates GEDCOM format 5.5" % line_number
- + "\nLines must be no more than one level higher than previous line."
- + "\nSee: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdf")
- raise GedcomFormatViolationError(error_message)
+ errmsg = "Line {0} of document violates GEDCOM format 5.5.1\n".format(line_number) + \
+ "Lines must be no more than one level higher than previous line.\n" + \
+ "See: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
# Create element. Store in list and dict, create children and parents.
- if tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
- element = IndividualElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_FAMILY:
- element = FamilyElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_FILE:
- element = FileElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
- element = ObjectElement(level, pointer, tag, value, crlf, multi_line=False)
+ if tag in RECORD_ELEMENTS:
+ element = RECORD_ELEMENTS[tag](level, pointer, tag, value, crlf, multi_line=False)
else:
element = Element(level, pointer, tag, value, crlf, multi_line=False)
@@ -274,272 +303,3 @@ def __build_list(self, element, element_list):
element_list.append(element)
for child in element.get_child_elements():
self.__build_list(child, element_list)
-
- # Methods for analyzing individuals and relationships between individuals
-
- def get_marriages(self, individual):
- """Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
- :type individual: IndividualElement
- :rtype: tuple
- """
- marriages = []
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
- # Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
- for family in families:
- for family_data in family.get_child_elements():
- if family_data.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
- date = ''
- place = ''
- for marriage_data in family_data.get_child_elements():
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = marriage_data.get_value()
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = marriage_data.get_value()
- marriages.append((date, place))
- return marriages
-
- def get_marriage_years(self, individual):
- """Returns a list of marriage years (as integers) for an individual
- :type individual: IndividualElement
- :rtype: list of int
- """
- dates = []
-
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- # Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
- for family in families:
- for child in family.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value().split()[-1]
- try:
- dates.append(int(date))
- except ValueError:
- pass
- return dates
-
- def marriage_year_match(self, individual, year):
- """Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
- :type individual: IndividualElement
- :type year: int
- :rtype: bool
- """
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- years = self.get_marriage_years(individual)
- return year in years
-
- def marriage_range_match(self, individual, from_year, to_year):
- """Check if one of the marriage years of an individual is in a given range. Years are integers.
- :type individual: IndividualElement
- :type from_year: int
- :type to_year: int
- :rtype: bool
- """
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- years = self.get_marriage_years(individual)
- for year in years:
- if from_year <= year <= to_year:
- return True
- return False
-
- def get_families(self, individual, family_type=gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE):
- """Return family elements listed for an individual
-
- family_type can be `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
-
- :type individual: IndividualElement
- :type family_type: str
- :rtype: list of FamilyElement
- """
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- families = []
- element_dictionary = self.get_element_dictionary()
-
- for child_element in individual.get_child_elements():
- is_family = (child_element.get_tag() == family_type
- and child_element.get_value() in element_dictionary
- and element_dictionary[child_element.get_value()].is_family())
- if is_family:
- families.append(element_dictionary[child_element.get_value()])
-
- return families
-
- def get_ancestors(self, individual, ancestor_type="ALL"):
- """Return elements corresponding to ancestors of an individual
-
- Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
- used to specify only natural (genetic) ancestors.
-
- :type individual: IndividualElement
- :type ancestor_type: str
- :rtype: list of Element
- """
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- parents = self.get_parents(individual, ancestor_type)
- ancestors = []
- ancestors.extend(parents)
-
- for parent in parents:
- ancestors.extend(self.get_ancestors(parent))
-
- return ancestors
-
- def get_parents(self, individual, parent_type="ALL"):
- """Return elements corresponding to parents of an individual
-
- Optional parent_type. Default "ALL" returns all parents. "NAT" can be
- used to specify only natural (genetic) parents.
-
- :type individual: IndividualElement
- :type parent_type: str
- :rtype: list of IndividualElement
- """
- if not isinstance(individual, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- parents = []
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_CHILD)
-
- for family in families:
- if parent_type == "NAT":
- for family_member in family.get_child_elements():
-
- if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
- and family_member.get_value() == individual.get_pointer():
-
- for child in family_member.get_child_elements():
- if child.get_value() == "Natural":
- if child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_WIFE)
- elif child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_HUSBAND)
- else:
- parents += self.get_family_members(family, "PARENTS")
-
- return parents
-
- def find_path_to_ancestor(self, descendant, ancestor, path=None):
- """Return path from descendant to ancestor
- :rtype: object
- """
- if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
- raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
- )
-
- if not path:
- path = [descendant]
-
- if path[-1].get_pointer() == ancestor.get_pointer():
- return path
- else:
- parents = self.get_parents(descendant, "NAT")
- for parent in parents:
- potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
- if potential_path is not None:
- return potential_path
-
- return None
-
- def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
- """Return array of family members: individual, spouse, and children
-
- Optional argument `members_type` can be used to return specific subsets:
-
- "FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
- "FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
- "FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
- "FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
- "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
-
- :type family: FamilyElement
- :type members_type: str
- :rtype: list of IndividualElement
- """
- if not isinstance(family, FamilyElement):
- raise NotAnActualFamilyError(
- "Operation only valid for element with %s tag." % gedcom.tags.GEDCOM_TAG_FAMILY
- )
-
- family_members = []
- element_dictionary = self.get_element_dictionary()
-
- for child_element in family.get_child_elements():
- # Default is ALL
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD)
-
- if members_type == FAMILY_MEMBERS_TYPE_PARENTS:
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE)
- elif members_type == FAMILY_MEMBERS_TYPE_HUSBAND:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- elif members_type == FAMILY_MEMBERS_TYPE_WIFE:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
- elif members_type == FAMILY_MEMBERS_TYPE_CHILDREN:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD
-
- if is_family and child_element.get_value() in element_dictionary:
- family_members.append(element_dictionary[child_element.get_value()])
-
- return family_members
-
- # Other methods
-
- def to_gedcom_string(self, recursive=False):
- """Formats all elements and optionally all of the sub-elements into a GEDCOM string
- :type recursive: bool
- """
- is_gte_python_3 = version_info[0] >= 3
- output = '' if is_gte_python_3 else b''
-
- for element in self.get_root_child_elements():
- if is_gte_python_3:
- output += element.to_gedcom_string(recursive)
- else:
- output += element.to_gedcom_string(recursive).encode('utf-8-sig')
-
- return output
-
- def print_gedcom(self):
- """Write GEDCOM data to stdout"""
- from sys import stdout
- self.save_gedcom(stdout)
-
- def save_gedcom(self, open_file, recursive=True):
- """Save GEDCOM data to a file
- :type open_file: file
- :type recursive: bool
- """
- open_file.write(self.to_gedcom_string(recursive))
diff --git a/gedcom/reader.py b/gedcom/reader.py
new file mode 100644
index 0000000..20483ab
--- /dev/null
+++ b/gedcom/reader.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Module containing a `gedcom.reader.Reader` with higher order methods than the
+base `gedcom.parser.Parser`
+"""
+
+from gedcom.parser import Parser
+from gedcom.element.header import HeaderElement
+from gedcom.element.individual import IndividualElement
+from gedcom.element.family import FamilyElement
+from gedcom.element.note import NoteElement
+from gedcom.element.object import ObjectElement
+from gedcom.element.source import SourceElement
+from gedcom.element.submission import SubmissionElement
+from gedcom.element.submitter import SubmitterElement
+from gedcom.element.repository import RepositoryElement
+
+ELEMENT_TYPES = {
+ 'header': HeaderElement,
+ 'individual': IndividualElement,
+ 'family': FamilyElement,
+ 'note': NoteElement,
+ 'media': ObjectElement,
+ 'source': SourceElement,
+ 'submission': SubmissionElement,
+ 'submitter': SubmitterElement,
+ 'repository': RepositoryElement
+}
+
+RECORD_KEYS = {
+ 'header': None,
+ 'individual': 'key_to_individual',
+ 'family': 'key_to_family',
+ 'media': 'key_to_object',
+ 'note': 'key_to_note',
+ 'source': 'key_to_source',
+ 'submission': 'key_to_submission',
+ 'submitter': 'key_to_submitter',
+ 'repository': 'key_to_repository'
+}
+
+class Reader(Parser):
+ """Simple wrapper class around the core parser with simple methods for
+ extracting parsed records as structured data.
+ """
+
+ def get_records_by_type(self, record_type, output='list'):
+ """Return either a list or dictionary with all the requested records
+ :type: record_type: str
+ :type: output: str
+ :rtype: list or dict
+ """
+ record_list = []
+ record_dict = {}
+
+ for element in self.get_root_child_elements():
+ if isinstance(element, ELEMENT_TYPES[record_type]):
+ record = element.get_record()
+ if output == 'list':
+ record_list.append(record)
+ else:
+ if RECORD_KEYS[record_type] is not None:
+ record_dict.update({record[RECORD_KEYS[record_type]]: record})
+ else:
+ record_dict.update({'@HEAD@': record})
+
+ if output == 'list':
+ return record_list
+
+ return record_dict
+
+ def get_all_records(self, entries='list'):
+ """Return a dictionary with all the requested records
+ :type: entries: str
+ :rtype: dict
+ """
+ record_dict = {}
+ for key in RECORD_KEYS:
+ if entries == 'list':
+ record_dict.update({key: []})
+ else:
+ record_dict.update({key: {}})
+
+ for element in self.get_root_child_elements():
+ for key in ELEMENT_TYPES:
+ if isinstance(element, ELEMENT_TYPES[key]):
+ record = element.get_record()
+ if entries == 'list':
+ record_dict[key].append(record)
+ else:
+ if key != 'header':
+ record_dict[key].update({record[RECORD_KEYS[key]]: record})
+ else:
+ record_dict['header'].update({'@HEAD@': record})
+
+ return record_dict
diff --git a/gedcom/element/file.py b/gedcom/standards.py
similarity index 63%
rename from gedcom/element/file.py
rename to gedcom/standards.py
index d02e8eb..43dabfd 100644
--- a/gedcom/element/file.py
+++ b/gedcom/standards.py
@@ -2,6 +2,7 @@
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -25,17 +26,17 @@
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""GEDCOM element consisting of tag `gedcom.tags.GEDCOM_TAG_FILE`"""
+"""The official FamilySearch 5.5 standard"""
+GEDCOM_5_5 = "https://edge.fscdn.org/assets/img/documents/" + \
+ "gedcom55-82e1509bd8dbe7477e3b500e4f62c240.pdf"
-from gedcom.element.element import Element
-import gedcom.tags
+"""The official FamilySearch 5.5.1 standard"""
+GEDCOM_5_5_1 = "https://edge.fscdn.org/assets/img/documents/" + \
+ "ged551-5bac5e57fe88dd37df0e153d9c515335.pdf"
+"""The GEDCOM-L working group 5.5.1 addendum"""
+GEDCOM_5_5_1_GEDCOM_L_ADDENDUM = "https://genealogy.net/GEDCOM/" + \
+ "GEDCOM551%20GEDCOM-L%20Addendum-R1.pdf"
-class NotAnActualFileError(Exception):
- pass
-
-
-class FileElement(Element):
-
- def get_tag(self):
- return gedcom.tags.GEDCOM_TAG_FILE
+"""The gedcom.org 5.5.5 specification with annotations"""
+GEDCOM_5_5_5 = "https://www.gedcom.org/specs/GEDCOM555.zip"
diff --git a/gedcom/subparsers/__init__.py b/gedcom/subparsers/__init__.py
new file mode 100644
index 0000000..c170727
--- /dev/null
+++ b/gedcom/subparsers/__init__.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+__all__ = [
+ "address_structure",
+ "association_structure",
+ "change_date",
+ "child_to_family_link",
+ "event_detail",
+ "family_event_detail",
+ "family_event_structure",
+ "individual_attribute_structure",
+ "individual_event_detail",
+ "individual_event_structure",
+ "lds_individual_ordinance",
+ "lds_spouse_sealing",
+ "multimedia_link",
+ "note_structure",
+ "personal_name_pieces",
+ "personal_name_structure",
+ "place_structure",
+ "source_citation",
+ "source_repository_citation",
+ "spouse_to_family_link",
+ "user_reference_number"
+]
diff --git a/gedcom/subparsers/address_structure.py b/gedcom/subparsers/address_structure.py
new file mode 100644
index 0000000..cb53fbb
--- /dev/null
+++ b/gedcom/subparsers/address_structure.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the ADDRESS_STRUCTURE embedded record.
+
+Note this is usually referenced as part of a larger structure and the
+`gedcom.tags.GEDCOM_TAG_ADDRESS` tag is at the same level as some of
+the other parts of this structure.
+"""
+
+import gedcom.tags as tags
+
+ADDRESS_TAGS = {
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE: 'addresse',
+ tags.GEDCOM_TAG_ADDRESS1: 'address1',
+ tags.GEDCOM_TAG_ADDRESS2: 'address2',
+ tags.GEDCOM_TAG_ADDRESS3: 'address3',
+ tags.GEDCOM_TAG_CITY: 'city',
+ tags.GEDCOM_TAG_STATE: 'state',
+ tags.GEDCOM_TAG_POSTAL_CODE: 'postal_code',
+ tags.GEDCOM_TAG_COUNTRY: 'country'
+}
+
+CONTACT_TAGS = {
+ tags.GEDCOM_TAG_PHONE: 'phone',
+ tags.GEDCOM_TAG_EMAIL: 'email',
+ tags.GEDCOM_TAG_FAX: 'fax',
+ tags.GEDCOM_TAG_WWW: 'www'
+}
+
+def address_structure(element):
+ """Parses and extracts the ADDRESS_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'address': '',
+ 'addresse': '',
+ 'address1': '',
+ 'address2': '',
+ 'address3': '',
+ 'city': '',
+ 'state': '',
+ 'postal_code': '',
+ 'country': '',
+ 'phone': [],
+ 'email': [],
+ 'fax': [],
+ 'www': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = child.get_multi_line_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in ADDRESS_TAGS:
+ record[ADDRESS_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if child.get_tag() in CONTACT_TAGS:
+ record[CONTACT_TAGS[child.get_tag()]].append(child.get_value())
+
+ return record
diff --git a/gedcom/subparsers/association_structure.py b/gedcom/subparsers/association_structure.py
new file mode 100644
index 0000000..44e3cf8
--- /dev/null
+++ b/gedcom/subparsers/association_structure.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the ASSOCIATION_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_ASSOCIATION` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+def association_structure(element):
+ """Parses and extracts the ASSOCIATION_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': element.get_value(),
+ 'relationship': '',
+ 'citations': [],
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_RELATIONSHIP:
+ record['relationship'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+
+ return record
diff --git a/gedcom/subparsers/change_date.py b/gedcom/subparsers/change_date.py
new file mode 100644
index 0000000..530a3e3
--- /dev/null
+++ b/gedcom/subparsers/change_date.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the CHANGE_DATE record identified by the
+`gedcom.tags.GEDCOM_TAG_CHANGE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+def change_date(element):
+ """Parses and extracts the CHANGE_DATE
+ :rtype: dict
+ """
+ record = {
+ 'date': '',
+ 'time': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['date'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TIME:
+ record['time'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
diff --git a/gedcom/subparsers/child_to_family_link.py b/gedcom/subparsers/child_to_family_link.py
new file mode 100644
index 0000000..8365a12
--- /dev/null
+++ b/gedcom/subparsers/child_to_family_link.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the CHILD_TO_FAMILY_LINK record identified by the
+`gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+def child_to_family_link(element):
+ """Parses and extracts the CHILD_TO_FAMILY_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': element.get_value(),
+ 'pedigree': '',
+ 'status': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_PEDIGREE:
+ record['pedigree'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
diff --git a/gedcom/subparsers/event_detail.py b/gedcom/subparsers/event_detail.py
new file mode 100644
index 0000000..48950e5
--- /dev/null
+++ b/gedcom/subparsers/event_detail.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the EVENT_DETAIL embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.place_structure import place_structure
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.multimedia_link import multimedia_link
+
+EVENT_TAGS = {
+ tags.GEDCOM_TAG_TYPE: 'type',
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_AGENCY: 'responsible_agency',
+ tags.GEDCOM_TAG_RELIGION: 'religious_affiliation',
+ tags.GEDCOM_TAG_CAUSE: 'cause_of_event',
+ tags.GEDCOM_TAG_RESTRICTION: 'restriction'
+}
+
+def event_detail(element):
+ """Parses and extracts the EVENT_DETAIL
+ :rtype: dict
+ """
+ record = {
+ 'type': '',
+ 'date': '',
+ 'place': {},
+ 'address': {},
+ 'responsible_agency': '',
+ 'religious_affiliation': '',
+ 'cause_of_event': '',
+ 'restriction_notice': '',
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() in EVENT_TAGS:
+ record[EVENT_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PLACE:
+ record['place'] = place_structure(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(element)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+
+ return record
diff --git a/gedcom/subparsers/family_event_detail.py b/gedcom/subparsers/family_event_detail.py
new file mode 100644
index 0000000..27e8818
--- /dev/null
+++ b/gedcom/subparsers/family_event_detail.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.event_detail import event_detail
+
+def family_event_detail(element):
+ """Parses and extracts the FAMILY_EVENT_DETAIL
+ :rtype: dict
+ """
+ record = event_detail(element)
+ record['husband_age'] = ''
+ record['wife_age'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_HUSBAND:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['husband_age'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_WIFE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['wife_age'] = gchild.get_value()
+
+ return record
diff --git a/gedcom/subparsers/family_event_structure.py b/gedcom/subparsers/family_event_structure.py
new file mode 100644
index 0000000..60e41f7
--- /dev/null
+++ b/gedcom/subparsers/family_event_structure.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.family_event_detail import family_event_detail
+
+EVENT_TAGS = {
+ tags.GEDCOM_TAG_ANNULMENT: 'annulment',
+ tags.GEDCOM_TAG_CENSUS: 'census',
+ tags.GEDCOM_TAG_DIVORCE: 'divorce',
+ tags.GEDCOM_TAG_DIVORCE_FILED: 'divorce_filed',
+ tags.GEDCOM_TAG_ENGAGEMENT: 'engagement',
+ tags.GEDCOM_TAG_MARRIAGE: 'marriage',
+ tags.GEDCOM_TAG_MARRIAGE_BANN: 'marriage_bann',
+ tags.GEDCOM_TAG_MARR_CONTRACT: 'marriage_contract',
+ tags.GEDCOM_TAG_MARR_LICENSE: 'marriage_license',
+ tags.GEDCOM_TAG_MARR_SETTLEMENT: 'marriage_settlement',
+ tags.GEDCOM_TAG_RESIDENCE: 'residence',
+ tags.GEDCOM_TAG_EVENT: 'event'
+}
+
+def family_event_structure(element):
+ """Parses and extracts the FAMILY_EVENT_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in EVENT_TAGS:
+ record = family_event_detail(child)
+ record['description'] = child.get_multi_line_value()
+ record['tag'] = child.get_tag()
+ record['event'] = EVENT_TAGS[child.get_tag()]
+ records.append(record)
+
+ return records
diff --git a/gedcom/subparsers/individual_attribute_structure.py b/gedcom/subparsers/individual_attribute_structure.py
new file mode 100644
index 0000000..5ce0ddd
--- /dev/null
+++ b/gedcom/subparsers/individual_attribute_structure.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record. As
+this is referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.individual_event_detail import individual_event_detail
+
+ATTRIBUTE_TAGS = {
+ tags.GEDCOM_TAG_CASTE: 'caste',
+ tags.GEDCOM_TAG_PHY_DESCRIPTION: 'physical_description',
+ tags.GEDCOM_TAG_EDUCATION: 'eduction',
+ tags.GEDCOM_TAG_IDENT_NUMBER: 'identity_number',
+ tags.GEDCOM_TAG_NATIONALITY: 'nationality',
+ tags.GEDCOM_TAG_CHILDREN_COUNT: 'number_of_children',
+ tags.GEDCOM_TAG_MARRIAGE_COUNT: 'number_of_marriages',
+ tags.GEDCOM_TAG_OCCUPATION: 'occupation',
+ tags.GEDCOM_TAG_PROPERTY: 'property',
+ tags.GEDCOM_TAG_RELIGION: 'religion',
+ tags.GEDCOM_TAG_RESIDENCE: 'residence',
+ tags.GEDCOM_TAG_SOC_SEC_NUMBER: 'social_security_number',
+ tags.GEDCOM_TAG_TITLE: 'title',
+ tags.GEDCOM_TAG_FACT: 'fact',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE: 'cause_of_death'
+}
+
+def individual_attribute_structure(element):
+ """Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in ATTRIBUTE_TAGS:
+ record = individual_event_detail(child)
+ record['description'] = child.get_multi_line_value()
+ record['tag'] = child.get_tag()
+ record['attribute'] = ATTRIBUTE_TAGS[child.get_tag()]
+ records.append(record)
+ continue
+
+ return records
diff --git a/gedcom/subparsers/individual_event_detail.py b/gedcom/subparsers/individual_event_detail.py
new file mode 100644
index 0000000..d99a6c5
--- /dev/null
+++ b/gedcom/subparsers/individual_event_detail.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the INDIVIDUAL_EVENT_DETAIL emdedded record. As this
+is referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.event_detail import event_detail
+
+def individual_event_detail(element):
+ """Parses and extracts INDIVIDUAL_EVENT_DETAIL
+ :rtype: dict
+ """
+ record = event_detail(element)
+ record['age'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['age'] = child.get_value()
+
+ return record
diff --git a/gedcom/subparsers/individual_event_structure.py b/gedcom/subparsers/individual_event_structure.py
new file mode 100644
index 0000000..457006e
--- /dev/null
+++ b/gedcom/subparsers/individual_event_structure.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the INDIVIDUAL_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.individual_event_detail import individual_event_detail
+
+EVENT_TAGS = {
+ tags.GEDCOM_TAG_DEATH: 'death',
+ tags.GEDCOM_TAG_BURIAL: 'burial',
+ tags.GEDCOM_TAG_CREMATION: 'cremation',
+ tags.GEDCOM_TAG_BAPTISM: 'baptism',
+ tags.GEDCOM_TAG_BAR_MITZVAH: 'bar_mitzvah',
+ tags.GEDCOM_TAG_BAS_MITZVAH: 'bas_mitzvah',
+ tags.GEDCOM_TAG_BLESSING: 'blessing',
+ tags.GEDCOM_TAG_ADULT_CHRISTENING: 'adult_christening',
+ tags.GEDCOM_TAG_CONFIRMATION: 'confirmation',
+ tags.GEDCOM_TAG_FIRST_COMMUNION: 'first_communion',
+ tags.GEDCOM_TAG_ORDINATION: 'ordination',
+ tags.GEDCOM_TAG_NATURALIZATION: 'naturalization',
+ tags.GEDCOM_TAG_EMIGRATION: 'emmigration',
+ tags.GEDCOM_TAG_IMMIGRATION: 'immigration',
+ tags.GEDCOM_TAG_CENSUS: 'census',
+ tags.GEDCOM_TAG_PROBATE: 'probate',
+ tags.GEDCOM_TAG_WILL: 'will',
+ tags.GEDCOM_TAG_GRADUATION: 'graduation',
+ tags.GEDCOM_TAG_RETIREMENT: 'retirement',
+ tags.GEDCOM_TAG_EVENT: 'event',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_DEGREE: 'degree',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_FUNERAL: 'funeral',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL: 'medical',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_MILITARY: 'military'
+}
+
+BIRTH_EVENT_TAGS = {
+ tags.GEDCOM_TAG_BIRTH: 'birth',
+ tags.GEDCOM_TAG_CHRISTENING: 'christening'
+}
+
+def individual_event_structure(element):
+ """Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in BIRTH_EVENT_TAGS:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = BIRTH_EVENT_TAGS[child.get_tag()]
+ record['description'] = child.get_multi_line_value()
+ record['family'] = ''
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['family'] = gchild.get_value()
+ records.append(record)
+ continue
+
+ if child.get_tag() in EVENT_TAGS:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = EVENT_TAGS[child.get_tag()]
+ record['description'] = child.get_multi_line_value()
+ records.append(record)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADOPTION:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = 'adoption'
+ record['description'] = child.get_multi_line_value()
+ record['family'] = ''
+ record['parent'] = ''
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['family'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_ADOPTION:
+ record['parent'] = ggchild.get_value()
+ records.append(record)
+
+ return records
diff --git a/gedcom/subparsers/lds_individual_ordinance.py b/gedcom/subparsers/lds_individual_ordinance.py
new file mode 100644
index 0000000..ff197b6
--- /dev/null
+++ b/gedcom/subparsers/lds_individual_ordinance.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the LDS_INDIVIDUAL_ORDINANCE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+ORDINANCE_TAGS = {
+ tags.GEDCOM_TAG_BAPTISM_LDS: 'lds_baptism',
+ tags.GEDCOM_TAG_CONFIRMATION_L: 'lds_confirmation',
+ tags.GEDCOM_TAG_ENDOWMENT: 'lds_endowment',
+ tags.GEDCOM_TAG_SEALING_CHILD: 'lds_sealing_child'
+}
+
+ORDINANCE_ATTRIBUTE_TAGS = {
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_TEMPLE: 'temple',
+ tags.GEDCOM_TAG_PLACE: 'place',
+ tags.GEDCOM_TAG_FAMILY_CHILD: 'key_to_family'
+}
+
+def lds_individual_ordinance(element):
+ """Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in ORDINANCE_TAGS:
+ record = {
+ 'date': '',
+ 'temple': '',
+ 'place': '',
+ 'status': '',
+ 'status_change': '',
+ 'notes': [],
+ 'citations': [],
+ 'tag': child.get_tag(),
+ 'event': ORDINANCE_TAGS[child.get_tag()]
+ }
+ if child.get_tag() == tags.GEDCOM_TAG_SEALING_CHILD:
+ record.update({'key_to_family': ''})
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in ORDINANCE_ATTRIBUTE_TAGS:
+ record[ORDINANCE_ATTRIBUTE_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['status_change'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ records.append(record)
+ continue
+
+ return records
diff --git a/gedcom/subparsers/lds_spouse_sealing.py b/gedcom/subparsers/lds_spouse_sealing.py
new file mode 100644
index 0000000..2a7bedf
--- /dev/null
+++ b/gedcom/subparsers/lds_spouse_sealing.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+SEALING_TAGS = {
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_TEMPLE: 'temple',
+ tags.GEDCOM_TAG_PLACE: 'place',
+ tags.GEDCOM_TAG_FAMILY_CHILD: 'key_to_family'
+}
+
+def lds_spouse_sealing(element):
+ """Parses and extracts the LDS_SPOUSE_SEALING
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_SEALING_SPOUSE:
+ record = {
+ 'date': '',
+ 'temple': '',
+ 'place': '',
+ 'status': '',
+ 'status_change': '',
+ 'notes': [],
+ 'citations': [],
+ 'tag': tags.GEDCOM_TAG_SEALING_SPOUSE,
+ 'event': 'lds_spouse_sealing'
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in SEALING_TAGS:
+ record[SEALING_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['status_change'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ records.append(record)
+ continue
+
+ return records
diff --git a/gedcom/subparsers/multimedia_link.py b/gedcom/subparsers/multimedia_link.py
new file mode 100644
index 0000000..3e70e83
--- /dev/null
+++ b/gedcom/subparsers/multimedia_link.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the MULTIMEDIA_LINK record identified by the
+`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
+"""
+
+import gedcom.tags as tags
+
+MEDIA_TAGS = {
+ tags.GEDCOM_TAG_FILE: 'file',
+ tags.GEDCOM_TAG_FORMAT: 'format',
+ tags.GEDCOM_TAG_MEDIA: 'type',
+ tags.GEDCOM_TAG_TITLE: 'title',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_PHOTO: 'preferred',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY: 'preferred'
+}
+
+def multimedia_link(element):
+ """Parse and extract a MULTIMEDIA_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_object': element.get_value(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'preferred': ''
+ }
+ if record['key_to_object'] not in [None, '']:
+ if '@' in record['key_to_object']:
+ return record
+
+ record['key_to_object'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
+ for ggchild in ggchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['type'] = ggchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() in MEDIA_TAGS:
+ record[MEDIA_TAGS[child.get_tag()]] = child.get_value()
+
+ return record
diff --git a/gedcom/subparsers/note_structure.py b/gedcom/subparsers/note_structure.py
new file mode 100644
index 0000000..31ed0c4
--- /dev/null
+++ b/gedcom/subparsers/note_structure.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the NOTE_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_NOTE` tag.
+"""
+
+def note_structure(element):
+ """Parse and extract a NOTE_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'key_to_note': element.get_value(),
+ 'note': ''
+ }
+ if record['key_to_note'] not in [None, '']:
+ if '@' in record['key_to_note']:
+ return record
+ record['key_to_note'] = ''
+ record['note'] = element.get_multi_line_value()
+
+ return record
diff --git a/gedcom/subparsers/personal_name_pieces.py b/gedcom/subparsers/personal_name_pieces.py
new file mode 100644
index 0000000..b38a0cc
--- /dev/null
+++ b/gedcom/subparsers/personal_name_pieces.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
+referenced in place in part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+NAME_TAGS = {
+ tags.GEDCOM_TAG_NAME_PREFIX: 'prefix',
+ tags.GEDCOM_TAG_GIVEN_NAME: 'given',
+ tags.GEDCOM_TAG_NICKNAME: 'nick',
+ tags.GEDCOM_TAG_SURN_PREFIX: 'surname_prefix',
+ tags.GEDCOM_TAG_SURNAME: 'surname',
+ tags.GEDCOM_TAG_NAME_SUFFIX: 'suffix',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME: 'rufname'
+}
+
+def personal_name_pieces(element):
+ """Parse and extract PERSONAL_NAME_PIECES
+ :rtype: dict
+ """
+ record = {
+ 'prefix': '',
+ 'given': '',
+ 'nick': '',
+ 'surname_prefix': '',
+ 'surname': '',
+ 'suffix': '',
+ 'rufname': '',
+ 'notes': [],
+ 'citations': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() in NAME_TAGS:
+ record[NAME_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ return record
diff --git a/gedcom/subparsers/personal_name_structure.py b/gedcom/subparsers/personal_name_structure.py
new file mode 100644
index 0000000..4225a54
--- /dev/null
+++ b/gedcom/subparsers/personal_name_structure.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the PERSONAL_NAME_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_NAME` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.personal_name_pieces import personal_name_pieces
+
+def extract_name(element):
+ """Parse and extract name record in a PERSONAL_NAME_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'name': '',
+ 'type': '',
+ 'pieces': {}
+ }
+ record['name'] = element.get_value()
+ record['pieces'] = personal_name_pieces(element)
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ return record
+
+def personal_name_structure(element):
+ """Parse and extract a PERSONAL_NAME_STRUCTURE
+ :rtype: dict
+ """
+ record = extract_name(element)
+ record['phonetic'] = []
+ record['romanized'] = []
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_PHONETIC:
+ record['phonetic'].append(extract_name(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED:
+ record['romanized'].append(extract_name(child))
+ continue
+
+ return record
diff --git a/gedcom/subparsers/place_structure.py b/gedcom/subparsers/place_structure.py
new file mode 100644
index 0000000..57c65cd
--- /dev/null
+++ b/gedcom/subparsers/place_structure.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the PLACE_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_PLACE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+def place_structure(element):
+ """Parse and extract a PLACE_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'name': element.get_value(),
+ 'hierarchy': '',
+ 'phonetic': [],
+ 'romanized': [],
+ 'latitude': '',
+ 'longitude': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['hierarchy'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PHONETIC:
+ subrecord = {
+ 'name': child.get_value(),
+ 'type': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ subrecord['type'] = gchild.get_value()
+ record['phonetic'].append(subrecord)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED:
+ subrecord = {
+ 'name': child.get_value(),
+ 'type': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ subrecord['type'] = gchild.get_value()
+ record['romanized'].append(subrecord)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MAP:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_LATITUDE:
+ record['latitude'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_LONGITUDE:
+ record['longitude'] = gchild.get_value()
+
+ return record
diff --git a/gedcom/subparsers/source_citation.py b/gedcom/subparsers/source_citation.py
new file mode 100644
index 0000000..0ad3e7d
--- /dev/null
+++ b/gedcom/subparsers/source_citation.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the SOURCE_CITATION record identified by the
+`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.multimedia_link import multimedia_link
+from gedcom.subparsers.note_structure import note_structure
+
+CITATION_TAGS = {
+ tags.GEDCOM_TAG_PAGE: 'page',
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_QUALITY_OF_DATA: 'quality',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_APID: 'apid'
+}
+
+def source_citation(element):
+ """Parse and extract a SOURCE_CITATION
+ :rtype: dict
+ """
+ record = {
+ 'key_to_source': element.get_value(),
+ 'source': '',
+ 'page': '',
+ 'event': '',
+ 'role': '',
+ 'date': '',
+ 'text': '',
+ 'media': [],
+ 'notes': [],
+ 'quality': '',
+ 'apid': ''
+ }
+ if record['key_to_source'] not in [None, '']:
+ if '@' not in record['key_to_source']:
+ record['key_to_source'] = ''
+ record['source'] = element.get_multi_line_value()
+
+ for child in element.get_child_elements():
+ if child.get_tag() in CITATION_TAGS:
+ record[CITATION_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_EVENT:
+ record['event'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_ROLE:
+ record['role'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATA:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['date'] = gchild.get_value()
+ continue
+ if gchild.get_tag() == tags.GEDCOM_TAG_TEXT:
+ record['text'] = gchild.get_multi_line_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TEXT:
+ record['text'] = child.get_multi_line_value()
+
+ return record
diff --git a/gedcom/subparsers/source_repository_citation.py b/gedcom/subparsers/source_repository_citation.py
new file mode 100644
index 0000000..5d088d4
--- /dev/null
+++ b/gedcom/subparsers/source_repository_citation.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the SOURCE_REPOSITORY_CITATION record identified by the
+`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+def source_repository_citation(element):
+ """Parse and extract a SOURCE_REPOSITORY_CITATION
+ :rtype: dict
+ """
+ record = {
+ 'key_to_repository': element.get_value(),
+ 'call_number': '',
+ 'media_type': '',
+ 'notes': []
+ }
+ if record['key_to_repository'] not in [None, '']:
+ if '@' not in record['key_to_repository']:
+ record['key_to_repository'] = ''
+
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CALL_NUMBER:
+ record['call_number'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media_type'] = gchild.get_value()
+
+ return record
diff --git a/gedcom/subparsers/spouse_to_family_link.py b/gedcom/subparsers/spouse_to_family_link.py
new file mode 100644
index 0000000..7e28ac7
--- /dev/null
+++ b/gedcom/subparsers/spouse_to_family_link.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the SPOUSE_TO_FAMILY_LINK record identified by the
+`gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+def spouse_to_family_link(element):
+ """Parse and extract a SPOUSE_TO_FAMILY_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': element.get_value(),
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
diff --git a/gedcom/subparsers/user_reference_number.py b/gedcom/subparsers/user_reference_number.py
new file mode 100644
index 0000000..5e76bf1
--- /dev/null
+++ b/gedcom/subparsers/user_reference_number.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Parser for a USER_REFERENCE_NUMBER structure identified by the top level
+`gedcom.tags.GEDCOM_TAG_REFERENCE` tag.
+"""
+
+import gedcom.tags as tags
+
+def user_reference_number(element):
+ """Parse and extract USER_REFERENCE_NUMBER
+ :rtype: dict
+ """
+ record = {
+ 'reference': element.get_value(),
+ 'type': ''
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+
+ return record
diff --git a/gedcom/tags.py b/gedcom/tags.py
index 1f95a18..9bee8d2 100644
--- a/gedcom/tags.py
+++ b/gedcom/tags.py
@@ -2,7 +2,7 @@
# Python GEDCOM Parser
#
-# Copyright (C) 2020 Christopher Horn
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -27,13 +27,21 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-GEDCOM tags.
+Standard GEDCOM tags and some common program defined extensions
"""
+GEDCOM_PROGRAM_DEFINED_TAG_ADMINISTRATIVE_ID = "_AIDN"
+"""Value: `_AIDN`
+
+Identifier for a location with the intention of an administrative authority,
+e.g. community identifier. GEDCOM-L Addendum."""
+
GEDCOM_PROGRAM_DEFINED_TAG_APID = "_APID"
"""Value: `_APID`
-Ancestry page id for a citation, points to page in database of record."""
+Ancestry page identifier. For a citation, points to the page in a Ancestry
+database for the record supporting the citation. For a source record it
+points to the database as a whole."""
GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE = "_DCAUSE"
"""Value: `_DCAUSE`
@@ -45,6 +53,12 @@
Degree or recognition of accomplishment received by an individual."""
+GEDCOM_PROGRAM_DEFINED_TAG_DEMOGRAPHIC_DATA = "_DMGD"
+"""Value: `_DMGD`
+
+A number of ojects, during an ascertainment, e.g. the count of households.
+GEDCOM-L Addendum"""
+
GEDCOM_PROGRAM_DEFINED_TAG_FREL = "_FREL"
"""Value: `_FREL`
@@ -55,6 +69,33 @@
Funeral for an individual."""
+GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT = "_GOV"
+"""Value: `_GOV`
+
+The official government id of the object in the Historical Place Register /
+Historic Gazeteer. GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT_TYPE = "_GOVTYPE"
+"""Value: `_GOVTYPE`
+
+An integer positive number as defined in the GOV system.
+See http://gov.genealogy.net.net/type/list. GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON = "_HME"
+"""Value: `_HME`
+
+Home person in the tree."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_LOCATION = "_LOC"
+"""Value: `_LOC`
+
+Location data record. GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MAIDENHEAD = "_MAIDENHEAD"
+"""Value: `_MAIDENHEAD`
+
+The maidenhead code. GEDCOM-L Addendum."""
+
GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL = "_MDCL"
"""Value: `_MDCL`
@@ -70,12 +111,24 @@
Relationship to a mother."""
+GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE = "_NAME"
+"""Value: `_NAME`
+
+Name of addresse in a `gedcom.tags.GEDCOM_TAG_ADDRESS` structure.
+GEDCOM-L Addendum."""
+
GEDCOM_PROGRAM_DEFINED_TAG_PHOTO = "_PHOTO"
"""Value: `_PHOTO`
-Used by some programs to identify the primary multimedia object for an
+Used by some programs to identify the primary multimedia object for an
individual, the same as `gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY`."""
+GEDCOM_PROGRAM_DEFINED_TAG_POSTAL_CODE = "_POST"
+"""Value: `_POST`
+
+The official zip code, called ADDRESS_POSTAL_CODE in the standard.
+GEDCOM-L Addendum."""
+
GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED = "_PREF"
"""Value: `_PREF`
@@ -86,6 +139,23 @@
Primary multimedia object for an individual."""
+GEDCOM_PROGRAM_DEFINED_TAG_SCHEMA = "_SCHEMA"
+"""Value: `_SCHEMA`
+
+Schema substructure extension to describe user defined tags. GEDCOM-L
+Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME = "_RUFNAME"
+"""Value: `_RUFNAME`
+
+An official given name of a German individual used in legal documents.
+GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_UUID = "_UID"
+"""Value: `_UID`
+
+Universal identification number. GEDCOM-L Addendum."""
+
GEDCOM_TAG_ABBREVIATION = "ABBR"
"""Value: `ABBR`
@@ -107,13 +177,18 @@
The second line of an address."""
+GEDCOM_TAG_ADDRESS3 = "ADR3"
+"""Value: `ADR3`
+
+The third line of an address."""
+
GEDCOM_TAG_ADOPTION = "ADOP"
"""Value: `ADOP`
Pertaining to creation of a child-parent relationship that does not exist
biologically."""
-GEDCOM_TAG_AGE = "AFN"
+GEDCOM_TAG_AFN = "AFN"
"""Value: `AFN`
Ancestral File Number, a unique permanent record file number of an individual
@@ -300,7 +375,7 @@
A statement that accompanies data to protect it from unlawful duplication
and distribution."""
-GEDCOM_TAG_COPPORATE = "CORP"
+GEDCOM_TAG_CORPORATE = "CORP"
"""Value: `CORP`
A name of an institution, agency, corporation, or company."""
@@ -704,7 +779,7 @@
GEDCOM_TAG_REPOSITORY = "REPO"
"""Value: `REPO`
-An institution or person that has the specified item as part of their
+An institution or person that has the specified item as part of their
collection(s)."""
GEDCOM_TAG_RESIDENCE = "RESI"
@@ -855,7 +930,7 @@
An individual in the role as a mother and/or married woman."""
-GEDCOM_TAG_WEB = "WWW"
+GEDCOM_TAG_WWW = "WWW"
"""Value: `WWW`
World Wide Web home page."""
diff --git a/tests/element/test_file.py b/tests/element/test_file.py
deleted file mode 100644
index fc13189..0000000
--- a/tests/element/test_file.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from gedcom.element.element import Element
-from gedcom.element.file import FileElement
-import gedcom.tags
-
-
-def test_initialization():
- file_element = FileElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_FILE, value="")
- assert isinstance(file_element, Element)
- assert isinstance(file_element, FileElement)
diff --git a/tests/element/test_header.py b/tests/element/test_header.py
new file mode 100644
index 0000000..a212af7
--- /dev/null
+++ b/tests/element/test_header.py
@@ -0,0 +1,9 @@
+from gedcom.element.element import Element
+from gedcom.element.header import HeaderElement
+import gedcom.tags
+
+
+def test_initialization():
+ header_element = HeaderElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_HEADER, value="")
+ assert isinstance(header_element, Element)
+ assert isinstance(header_element, HeaderElement)
diff --git a/tests/element/test_note.py b/tests/element/test_note.py
new file mode 100644
index 0000000..92cd521
--- /dev/null
+++ b/tests/element/test_note.py
@@ -0,0 +1,9 @@
+from gedcom.element.element import Element
+from gedcom.element.note import NoteElement
+import gedcom.tags
+
+
+def test_initialization():
+ note_element = NoteElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_NOTE, value="")
+ assert isinstance(note_element, Element)
+ assert isinstance(note_element, NoteElement)
diff --git a/tests/element/test_repository.py b/tests/element/test_repository.py
new file mode 100644
index 0000000..6d7bfaf
--- /dev/null
+++ b/tests/element/test_repository.py
@@ -0,0 +1,9 @@
+from gedcom.element.element import Element
+from gedcom.element.repository import RepositoryElement
+import gedcom.tags
+
+
+def test_initialization():
+ repository_element = RepositoryElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_REPOSITORY, value="")
+ assert isinstance(repository_element, Element)
+ assert isinstance(repository_element, RepositoryElement)
diff --git a/tests/element/test_source.py b/tests/element/test_source.py
new file mode 100644
index 0000000..2373695
--- /dev/null
+++ b/tests/element/test_source.py
@@ -0,0 +1,9 @@
+from gedcom.element.element import Element
+from gedcom.element.source import SourceElement
+import gedcom.tags
+
+
+def test_initialization():
+ source_element = SourceElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_SOURCE, value="")
+ assert isinstance(source_element, Element)
+ assert isinstance(source_element, SourceElement)
diff --git a/tests/element/test_submission.py b/tests/element/test_submission.py
new file mode 100644
index 0000000..1155dff
--- /dev/null
+++ b/tests/element/test_submission.py
@@ -0,0 +1,9 @@
+from gedcom.element.element import Element
+from gedcom.element.submission import SubmissionElement
+import gedcom.tags
+
+
+def test_initialization():
+ submission_element = SubmissionElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_SUBMISSION, value="")
+ assert isinstance(submission_element, Element)
+ assert isinstance(submission_element, SubmissionElement)
diff --git a/tests/element/test_submitter.py b/tests/element/test_submitter.py
new file mode 100644
index 0000000..bd661c9
--- /dev/null
+++ b/tests/element/test_submitter.py
@@ -0,0 +1,9 @@
+from gedcom.element.element import Element
+from gedcom.element.submitter import SubmitterElement
+import gedcom.tags
+
+
+def test_initialization():
+ submitter_element = SubmitterElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_SUBMITTER, value="")
+ assert isinstance(submitter_element, Element)
+ assert isinstance(submitter_element, SourceElement)
From 817929043346dd1f843d57e796d0d7ef6a2400e8 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 00:32:19 -0400
Subject: [PATCH 10/23] fix: fix typo in SubmitterElement test
---
tests/element/test_submitter.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/element/test_submitter.py b/tests/element/test_submitter.py
index bd661c9..f949d6d 100644
--- a/tests/element/test_submitter.py
+++ b/tests/element/test_submitter.py
@@ -6,4 +6,4 @@
def test_initialization():
submitter_element = SubmitterElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_SUBMITTER, value="")
assert isinstance(submitter_element, Element)
- assert isinstance(submitter_element, SourceElement)
+ assert isinstance(submitter_element, SubmitterElement)
From 6c606d6e5557e5d057022ef330959cc0957d4868 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 00:47:55 -0400
Subject: [PATCH 11/23] style: make pep e302 compliant
---
gedcom/detect.py | 3 +++
gedcom/element/family.py | 1 +
gedcom/element/header.py | 3 ++-
gedcom/element/individual.py | 1 +
gedcom/element/note.py | 1 +
gedcom/element/object.py | 1 +
gedcom/element/repository.py | 1 +
gedcom/element/source.py | 1 +
gedcom/element/submission.py | 1 +
gedcom/element/submitter.py | 1 +
gedcom/errors.py | 5 +++++
gedcom/parser.py | 1 +
gedcom/reader.py | 1 +
gedcom/subparsers/address_structure.py | 1 +
gedcom/subparsers/association_structure.py | 1 +
gedcom/subparsers/change_date.py | 1 +
gedcom/subparsers/child_to_family_link.py | 1 +
gedcom/subparsers/event_detail.py | 1 +
gedcom/subparsers/family_event_detail.py | 1 +
gedcom/subparsers/family_event_structure.py | 1 +
gedcom/subparsers/individual_attribute_structure.py | 1 +
gedcom/subparsers/individual_event_detail.py | 1 +
gedcom/subparsers/individual_event_structure.py | 1 +
gedcom/subparsers/lds_individual_ordinance.py | 1 +
gedcom/subparsers/lds_spouse_sealing.py | 1 +
gedcom/subparsers/multimedia_link.py | 3 ++-
gedcom/subparsers/note_structure.py | 1 +
gedcom/subparsers/personal_name_pieces.py | 1 +
gedcom/subparsers/personal_name_structure.py | 2 ++
gedcom/subparsers/place_structure.py | 1 +
gedcom/subparsers/source_citation.py | 1 +
gedcom/subparsers/source_repository_citation.py | 1 +
gedcom/subparsers/spouse_to_family_link.py | 1 +
gedcom/subparsers/user_reference_number.py | 1 +
34 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/gedcom/detect.py b/gedcom/detect.py
index 9034ca6..37463d6 100644
--- a/gedcom/detect.py
+++ b/gedcom/detect.py
@@ -44,6 +44,7 @@
except ModuleNotFoundError:
ANSEL_AVAILABLE = False
+
def validate_encoding(file_path, codec):
"""Check the encoding is compatible with the encoding reported
:type file_path: str
@@ -68,6 +69,7 @@ def validate_encoding(file_path, codec):
"See: {0}".format(standards.GEDCOM_5_5_1)
raise GedcomCharacterSetUnsupportedError(errmsg)
+
def get_encoding(file_path):
"""Examines file to determine encoding to use and then validates it
:type file_path: str
@@ -106,6 +108,7 @@ def get_encoding(file_path):
validate_encoding(file_path, codec)
return codec
+
def get_version(file_path, codec):
"""Probes Gedcom to identify version used, should expand this in future
Returns probed version, reported version, reported format
diff --git a/gedcom/element/family.py b/gedcom/element/family.py
index c5f92ff..712c887 100644
--- a/gedcom/element/family.py
+++ b/gedcom/element/family.py
@@ -49,6 +49,7 @@
tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id'
}
+
class FamilyElement(Element):
"""Element associated with a `FAM_RECORD`"""
diff --git a/gedcom/element/header.py b/gedcom/element/header.py
index 943ea9b..45cb8ac 100644
--- a/gedcom/element/header.py
+++ b/gedcom/element/header.py
@@ -45,7 +45,8 @@
tags.GEDCOM_TAG_LANGUAGE: 'language',
tags.GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON: 'key_to_home_person'
}
-
+
+
class HeaderElement(Element):
"""Element associated with a `HEADER`"""
diff --git a/gedcom/element/individual.py b/gedcom/element/individual.py
index d9e2b40..e137c2e 100644
--- a/gedcom/element/individual.py
+++ b/gedcom/element/individual.py
@@ -56,6 +56,7 @@
tags.GEDCOM_TAG_AFN: 'ancestral_file_number'
}
+
class IndividualElement(Element):
"""Element associated with an `INDIVIDUAL_RECORD`"""
diff --git a/gedcom/element/note.py b/gedcom/element/note.py
index bf4da62..4966552 100644
--- a/gedcom/element/note.py
+++ b/gedcom/element/note.py
@@ -37,6 +37,7 @@
from gedcom.subparsers.change_date import change_date
from gedcom.subparsers.user_reference_number import user_reference_number
+
class NoteElement(Element):
"""Element associated with a `NOTE_RECORD`"""
diff --git a/gedcom/element/object.py b/gedcom/element/object.py
index e1be7fa..924356f 100644
--- a/gedcom/element/object.py
+++ b/gedcom/element/object.py
@@ -38,6 +38,7 @@
from gedcom.subparsers.change_date import change_date
from gedcom.subparsers.user_reference_number import user_reference_number
+
class ObjectElement(Element):
"""Element associated with a `MULTIMEDIA_RECORD`"""
diff --git a/gedcom/element/repository.py b/gedcom/element/repository.py
index 9136818..7f14db5 100644
--- a/gedcom/element/repository.py
+++ b/gedcom/element/repository.py
@@ -38,6 +38,7 @@
from gedcom.subparsers.change_date import change_date
from gedcom.subparsers.user_reference_number import user_reference_number
+
class RepositoryElement(Element):
"""Element associated with a `REPOSITORY_RECORD`"""
diff --git a/gedcom/element/source.py b/gedcom/element/source.py
index dce1581..e58a6f2 100644
--- a/gedcom/element/source.py
+++ b/gedcom/element/source.py
@@ -52,6 +52,7 @@
tags.GEDCOM_PROGRAM_DEFINED_TAG_APID: 'apid'
}
+
class SourceElement(Element):
"""Element associated with a SOURCE_RECORD"""
diff --git a/gedcom/element/submission.py b/gedcom/element/submission.py
index 9cb01f6..78399a9 100644
--- a/gedcom/element/submission.py
+++ b/gedcom/element/submission.py
@@ -46,6 +46,7 @@
tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id'
}
+
class SubmissionElement(Element):
"""Element associated with a `SUBMISSION_RECORD`"""
diff --git a/gedcom/element/submitter.py b/gedcom/element/submitter.py
index 44261f9..f89c818 100644
--- a/gedcom/element/submitter.py
+++ b/gedcom/element/submitter.py
@@ -38,6 +38,7 @@
from gedcom.subparsers.change_date import change_date
from gedcom.subparsers.multimedia_link import multimedia_link
+
class SubmitterElement(Element):
"""Element associated with a `SUBMITTER_RECORD`"""
diff --git a/gedcom/errors.py b/gedcom/errors.py
index 95529c0..7ed1d31 100644
--- a/gedcom/errors.py
+++ b/gedcom/errors.py
@@ -30,27 +30,32 @@
Module containing the exception handling classes.
"""
+
class GedcomFormatViolationError(Exception):
"""Raised when the document format does not appear to conform
to the standard and strict parsing required.
"""
+
class GedcomStructureViolationError(Exception):
"""Raised when the structure of a record does not conform to
the standard.
"""
+
class GedcomCharacterSetUnsupportedError(Exception):
"""Raised when a Gedcom appears to contain a character set
the parser is not yet able to support.
"""
+
class GedcomVersionUnsupportedError(Exception):
"""Raised when a particular Gedcom version is not supported
by the parser and the standard for the version requires the
parser to reject it.
"""
+
class GedcomFormatUnsupportedError(Exception):
"""Raised if the GEDCOM format is not recognized by the
parser. Note some misspellings as documented on page 148
diff --git a/gedcom/parser.py b/gedcom/parser.py
index f0bbcf7..c1d72e4 100644
--- a/gedcom/parser.py
+++ b/gedcom/parser.py
@@ -67,6 +67,7 @@
tags.GEDCOM_TAG_REPOSITORY: RepositoryElement
}
+
class Parser():
"""Parses and manipulates GEDCOM 5.5 format data
diff --git a/gedcom/reader.py b/gedcom/reader.py
index 20483ab..e52bca2 100644
--- a/gedcom/reader.py
+++ b/gedcom/reader.py
@@ -66,6 +66,7 @@
'repository': 'key_to_repository'
}
+
class Reader(Parser):
"""Simple wrapper class around the core parser with simple methods for
extracting parsed records as structured data.
diff --git a/gedcom/subparsers/address_structure.py b/gedcom/subparsers/address_structure.py
index cb53fbb..bc18eea 100644
--- a/gedcom/subparsers/address_structure.py
+++ b/gedcom/subparsers/address_structure.py
@@ -48,6 +48,7 @@
tags.GEDCOM_TAG_WWW: 'www'
}
+
def address_structure(element):
"""Parses and extracts the ADDRESS_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/association_structure.py b/gedcom/subparsers/association_structure.py
index 44e3cf8..3e389de 100644
--- a/gedcom/subparsers/association_structure.py
+++ b/gedcom/subparsers/association_structure.py
@@ -29,6 +29,7 @@
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
+
def association_structure(element):
"""Parses and extracts the ASSOCIATION_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/change_date.py b/gedcom/subparsers/change_date.py
index 530a3e3..d40b771 100644
--- a/gedcom/subparsers/change_date.py
+++ b/gedcom/subparsers/change_date.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.note_structure import note_structure
+
def change_date(element):
"""Parses and extracts the CHANGE_DATE
:rtype: dict
diff --git a/gedcom/subparsers/child_to_family_link.py b/gedcom/subparsers/child_to_family_link.py
index 8365a12..1ced20a 100644
--- a/gedcom/subparsers/child_to_family_link.py
+++ b/gedcom/subparsers/child_to_family_link.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.note_structure import note_structure
+
def child_to_family_link(element):
"""Parses and extracts the CHILD_TO_FAMILY_LINK
:rtype: dict
diff --git a/gedcom/subparsers/event_detail.py b/gedcom/subparsers/event_detail.py
index 48950e5..00333ad 100644
--- a/gedcom/subparsers/event_detail.py
+++ b/gedcom/subparsers/event_detail.py
@@ -41,6 +41,7 @@
tags.GEDCOM_TAG_RESTRICTION: 'restriction'
}
+
def event_detail(element):
"""Parses and extracts the EVENT_DETAIL
:rtype: dict
diff --git a/gedcom/subparsers/family_event_detail.py b/gedcom/subparsers/family_event_detail.py
index 27e8818..ef17927 100644
--- a/gedcom/subparsers/family_event_detail.py
+++ b/gedcom/subparsers/family_event_detail.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.event_detail import event_detail
+
def family_event_detail(element):
"""Parses and extracts the FAMILY_EVENT_DETAIL
:rtype: dict
diff --git a/gedcom/subparsers/family_event_structure.py b/gedcom/subparsers/family_event_structure.py
index 60e41f7..b243115 100644
--- a/gedcom/subparsers/family_event_structure.py
+++ b/gedcom/subparsers/family_event_structure.py
@@ -43,6 +43,7 @@
tags.GEDCOM_TAG_EVENT: 'event'
}
+
def family_event_structure(element):
"""Parses and extracts the FAMILY_EVENT_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/individual_attribute_structure.py b/gedcom/subparsers/individual_attribute_structure.py
index 5ce0ddd..920ede4 100644
--- a/gedcom/subparsers/individual_attribute_structure.py
+++ b/gedcom/subparsers/individual_attribute_structure.py
@@ -46,6 +46,7 @@
tags.GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE: 'cause_of_death'
}
+
def individual_attribute_structure(element):
"""Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/individual_event_detail.py b/gedcom/subparsers/individual_event_detail.py
index d99a6c5..09e4cfe 100644
--- a/gedcom/subparsers/individual_event_detail.py
+++ b/gedcom/subparsers/individual_event_detail.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.event_detail import event_detail
+
def individual_event_detail(element):
"""Parses and extracts INDIVIDUAL_EVENT_DETAIL
:rtype: dict
diff --git a/gedcom/subparsers/individual_event_structure.py b/gedcom/subparsers/individual_event_structure.py
index 457006e..ffa01e2 100644
--- a/gedcom/subparsers/individual_event_structure.py
+++ b/gedcom/subparsers/individual_event_structure.py
@@ -60,6 +60,7 @@
tags.GEDCOM_TAG_CHRISTENING: 'christening'
}
+
def individual_event_structure(element):
"""Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/lds_individual_ordinance.py b/gedcom/subparsers/lds_individual_ordinance.py
index ff197b6..35c0aae 100644
--- a/gedcom/subparsers/lds_individual_ordinance.py
+++ b/gedcom/subparsers/lds_individual_ordinance.py
@@ -43,6 +43,7 @@
tags.GEDCOM_TAG_FAMILY_CHILD: 'key_to_family'
}
+
def lds_individual_ordinance(element):
"""Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
:rtype: dict
diff --git a/gedcom/subparsers/lds_spouse_sealing.py b/gedcom/subparsers/lds_spouse_sealing.py
index 2a7bedf..69a8657 100644
--- a/gedcom/subparsers/lds_spouse_sealing.py
+++ b/gedcom/subparsers/lds_spouse_sealing.py
@@ -36,6 +36,7 @@
tags.GEDCOM_TAG_FAMILY_CHILD: 'key_to_family'
}
+
def lds_spouse_sealing(element):
"""Parses and extracts the LDS_SPOUSE_SEALING
:rtype: dict
diff --git a/gedcom/subparsers/multimedia_link.py b/gedcom/subparsers/multimedia_link.py
index 3e70e83..cc4ccc9 100644
--- a/gedcom/subparsers/multimedia_link.py
+++ b/gedcom/subparsers/multimedia_link.py
@@ -36,6 +36,7 @@
tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY: 'preferred'
}
+
def multimedia_link(element):
"""Parse and extract a MULTIMEDIA_LINK
:rtype: dict
@@ -59,7 +60,7 @@ def multimedia_link(element):
for gchild in child.get_child_elements():
if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
record['format'] = gchild.get_value()
- for ggchild in ggchild.get_child_elements():
+ for ggchild in gchild.get_child_elements():
if ggchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
record['type'] = ggchild.get_value()
continue
diff --git a/gedcom/subparsers/note_structure.py b/gedcom/subparsers/note_structure.py
index 31ed0c4..0ce65cd 100644
--- a/gedcom/subparsers/note_structure.py
+++ b/gedcom/subparsers/note_structure.py
@@ -25,6 +25,7 @@
`gedcom.tags.GEDCOM_TAG_NOTE` tag.
"""
+
def note_structure(element):
"""Parse and extract a NOTE_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/personal_name_pieces.py b/gedcom/subparsers/personal_name_pieces.py
index b38a0cc..1745450 100644
--- a/gedcom/subparsers/personal_name_pieces.py
+++ b/gedcom/subparsers/personal_name_pieces.py
@@ -39,6 +39,7 @@
tags.GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME: 'rufname'
}
+
def personal_name_pieces(element):
"""Parse and extract PERSONAL_NAME_PIECES
:rtype: dict
diff --git a/gedcom/subparsers/personal_name_structure.py b/gedcom/subparsers/personal_name_structure.py
index 4225a54..ec63a9b 100644
--- a/gedcom/subparsers/personal_name_structure.py
+++ b/gedcom/subparsers/personal_name_structure.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.personal_name_pieces import personal_name_pieces
+
def extract_name(element):
"""Parse and extract name record in a PERSONAL_NAME_STRUCTURE
:rtype: dict
@@ -44,6 +45,7 @@ def extract_name(element):
record['type'] = child.get_value()
return record
+
def personal_name_structure(element):
"""Parse and extract a PERSONAL_NAME_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/place_structure.py b/gedcom/subparsers/place_structure.py
index 57c65cd..94b02ad 100644
--- a/gedcom/subparsers/place_structure.py
+++ b/gedcom/subparsers/place_structure.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.note_structure import note_structure
+
def place_structure(element):
"""Parse and extract a PLACE_STRUCTURE
:rtype: dict
diff --git a/gedcom/subparsers/source_citation.py b/gedcom/subparsers/source_citation.py
index 0ad3e7d..8069960 100644
--- a/gedcom/subparsers/source_citation.py
+++ b/gedcom/subparsers/source_citation.py
@@ -36,6 +36,7 @@
tags.GEDCOM_PROGRAM_DEFINED_TAG_APID: 'apid'
}
+
def source_citation(element):
"""Parse and extract a SOURCE_CITATION
:rtype: dict
diff --git a/gedcom/subparsers/source_repository_citation.py b/gedcom/subparsers/source_repository_citation.py
index 5d088d4..4a897b9 100644
--- a/gedcom/subparsers/source_repository_citation.py
+++ b/gedcom/subparsers/source_repository_citation.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.note_structure import note_structure
+
def source_repository_citation(element):
"""Parse and extract a SOURCE_REPOSITORY_CITATION
:rtype: dict
diff --git a/gedcom/subparsers/spouse_to_family_link.py b/gedcom/subparsers/spouse_to_family_link.py
index 7e28ac7..1142191 100644
--- a/gedcom/subparsers/spouse_to_family_link.py
+++ b/gedcom/subparsers/spouse_to_family_link.py
@@ -28,6 +28,7 @@
import gedcom.tags as tags
from gedcom.subparsers.note_structure import note_structure
+
def spouse_to_family_link(element):
"""Parse and extract a SPOUSE_TO_FAMILY_LINK
:rtype: dict
diff --git a/gedcom/subparsers/user_reference_number.py b/gedcom/subparsers/user_reference_number.py
index 5e76bf1..ae6e8c4 100644
--- a/gedcom/subparsers/user_reference_number.py
+++ b/gedcom/subparsers/user_reference_number.py
@@ -27,6 +27,7 @@
import gedcom.tags as tags
+
def user_reference_number(element):
"""Parse and extract USER_REFERENCE_NUMBER
:rtype: dict
From 4405346bebd72b82cd8f732921ba666b229b9773 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 01:20:36 -0400
Subject: [PATCH 12/23] build: add dependency on chardet to detect encoding
---
Pipfile | 1 +
Pipfile.lock | 204 ++++++++++++++++++++++++++++++++++++---------------
2 files changed, 147 insertions(+), 58 deletions(-)
diff --git a/Pipfile b/Pipfile
index 59b90df..a30b2bf 100644
--- a/Pipfile
+++ b/Pipfile
@@ -11,6 +11,7 @@ tox = "*"
pdoc3 = "*"
[packages]
+chardet = "*"
[requires]
python_version = "3.5"
diff --git a/Pipfile.lock b/Pipfile.lock
index 6e99c0c..bd3c135 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "ff4ffecf922d35b96c175b7a2a6e76ba732f698d575beb753c2742046c2da00d"
+ "sha256": "84143c137ae9e2186b45e36a41936a9d4d3d07568627cad373a3f1bbf30f3c68"
},
"pipfile-spec": 6,
"requires": {
@@ -15,36 +15,103 @@
}
]
},
- "default": {},
+ "default": {
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "index": "pypi",
+ "version": "==3.0.4"
+ }
+ },
"develop": {
"appdirs": {
"hashes": [
- "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
- "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
+ "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
+ "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
],
- "version": "==1.4.3"
+ "version": "==1.4.4"
},
"bleach": {
"hashes": [
- "sha256:53165a6596e7899c4338d847315fec508110a53bd6fd15c127c2e0d0860264e3",
- "sha256:f8dfd8a7e26443e986c4e44df31870da8e906ea61096af06ba5d5cc2d519842a"
+ "sha256:2bce3d8fab545a6528c8fa5d9f9ae8ebc85a56da365c7f85180bfe96a35ef22f",
+ "sha256:3c4c520fdb9db59ef139915a5db79f8b51bc2a7257ea0389f30c846883430a4b"
],
- "version": "==3.1.3"
+ "version": "==3.1.5"
},
"certifi": {
"hashes": [
- "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
- "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
+ "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
+ "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
+ ],
+ "version": "==2020.4.5.1"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff",
+ "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b",
+ "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac",
+ "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0",
+ "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384",
+ "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26",
+ "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6",
+ "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b",
+ "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e",
+ "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd",
+ "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2",
+ "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66",
+ "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc",
+ "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8",
+ "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55",
+ "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4",
+ "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5",
+ "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d",
+ "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78",
+ "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa",
+ "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793",
+ "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f",
+ "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a",
+ "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f",
+ "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30",
+ "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f",
+ "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3",
+ "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"
],
- "version": "==2019.11.28"
+ "version": "==1.14.0"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
+ "index": "pypi",
"version": "==3.0.4"
},
+ "cryptography": {
+ "hashes": [
+ "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6",
+ "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b",
+ "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5",
+ "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf",
+ "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e",
+ "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b",
+ "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae",
+ "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b",
+ "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0",
+ "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b",
+ "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d",
+ "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229",
+ "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3",
+ "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365",
+ "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55",
+ "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270",
+ "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e",
+ "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785",
+ "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"
+ ],
+ "version": "==2.9.2"
+ },
"distlib": {
"hashes": [
"sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"
@@ -74,19 +141,26 @@
},
"importlib-metadata": {
"hashes": [
- "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302",
- "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"
+ "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f",
+ "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"
],
"markers": "python_version < '3.8'",
- "version": "==1.5.0"
+ "version": "==1.6.0"
},
- "importlib-resources": {
+ "jeepney": {
"hashes": [
- "sha256:4019b6a9082d8ada9def02bece4a76b131518866790d58fdda0b5f8c603b36c2",
- "sha256:dd98ceeef3f5ad2ef4cc287b8586da4ebad15877f351e9688987ad663a0a29b8"
+ "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e",
+ "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf"
],
- "markers": "python_version < '3.7'",
- "version": "==1.4.0"
+ "markers": "sys_platform == 'linux'",
+ "version": "==0.4.3"
+ },
+ "keyring": {
+ "hashes": [
+ "sha256:3401234209015144a5d75701e71cb47239e552b0882313e9f51e8976f9e27843",
+ "sha256:c53e0e5ccde3ad34284a40ce7976b5b3a3d6de70344c3f8ee44364cc340976ec"
+ ],
+ "version": "==21.2.1"
},
"mako": {
"hashes": [
@@ -97,10 +171,10 @@
},
"markdown": {
"hashes": [
- "sha256:90fee683eeabe1a92e149f7ba74e5ccdc81cd397bd6c516d93a8da0ef90b6902",
- "sha256:e4795399163109457d4c5af2183fbe6b60326c17cfdf25ce6e7474c6624f725d"
+ "sha256:1fafe3f1ecabfb514a5285fca634a53c1b32a81cb0feb154264d55bf2ff22c17",
+ "sha256:c467cd6233885534bf0fe96e62e3cf46cfc1605112356c4f9981512b8174de59"
],
- "version": "==3.2.1"
+ "version": "==3.2.2"
},
"markupsafe": {
"hashes": [
@@ -142,17 +216,17 @@
},
"packaging": {
"hashes": [
- "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
- "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
+ "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8",
+ "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"
],
- "version": "==20.3"
+ "version": "==20.4"
},
"pdoc3": {
"hashes": [
- "sha256:ebca75b7fcf23f3b4320abe23339834d3f08c28517718e9d29e555fc38eeb33c"
+ "sha256:d7b56e67b5e049d53dcde94245a28040b640b2e06c344fc58ab2bdf2d91dc00f"
],
"index": "pypi",
- "version": "==0.7.5"
+ "version": "==0.8.1"
},
"pkginfo": {
"hashes": [
@@ -175,6 +249,13 @@
],
"version": "==1.8.1"
},
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "version": "==2.20"
+ },
"pygments": {
"hashes": [
"sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
@@ -184,17 +265,17 @@
},
"pyparsing": {
"hashes": [
- "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
- "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
+ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
+ "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
- "version": "==2.4.6"
+ "version": "==2.4.7"
},
"readme-renderer": {
"hashes": [
- "sha256:1b6d8dd1673a0b293766b4106af766b6eff3654605f9c4f239e65de6076bc222",
- "sha256:e67d64242f0174a63c3b727801a2fff4c1f38ebe5d71d95ff7ece081945a6cd4"
+ "sha256:cbe9db71defedd2428a1589cdc545f9bd98e59297449f69d721ef8f1cfced68d",
+ "sha256:cc4957a803106e820d05d14f71033092537a22daa4f406dfbdd61177e0936376"
],
- "version": "==25.0"
+ "version": "==26.0"
},
"requests": {
"hashes": [
@@ -210,56 +291,64 @@
],
"version": "==0.9.1"
},
+ "secretstorage": {
+ "hashes": [
+ "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6",
+ "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b"
+ ],
+ "markers": "sys_platform == 'linux'",
+ "version": "==3.1.2"
+ },
"six": {
"hashes": [
- "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
- "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
+ "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
- "version": "==1.14.0"
+ "version": "==1.15.0"
},
"toml": {
"hashes": [
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
- "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
+ "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
],
- "version": "==0.10.0"
+ "version": "==0.10.1"
},
"tox": {
"hashes": [
- "sha256:0cbe98369081fa16bd6f1163d3d0b2a62afa29d402ccfad2bd09fb2668be0956",
- "sha256:676f1e3e7de245ad870f956436b84ea226210587d1f72c8dfb8cd5ac7b6f0e70"
+ "sha256:322dfdf007d7d53323f767badcb068a5cfa7c44d8aabb698d131b28cf44e62c4",
+ "sha256:8c9ad9b48659d291c5bc78bcabaa4d680d627687154b812fa52baedaa94f9f83"
],
"index": "pypi",
- "version": "==3.14.5"
+ "version": "==3.15.1"
},
"tqdm": {
"hashes": [
- "sha256:0d8b5afb66e23d80433102e9bd8b5c8b65d34c2a2255b2de58d97bd2ea8170fd",
- "sha256:f35fb121bafa030bd94e74fcfd44f3c2830039a2ddef7fc87ef1c2d205237b24"
+ "sha256:4733c4a10d0f2a4d098d801464bdaf5240c7dadd2a7fde4ee93b0a0efd9fb25e",
+ "sha256:acdafb20f51637ca3954150d0405ff1a7edde0ff19e38fb99a80a66210d2a28f"
],
- "version": "==4.43.0"
+ "version": "==4.46.0"
},
"twine": {
"hashes": [
- "sha256:630fadd6e342e725930be6c696537e3f9ccc54331742b16245dab292a17d0460",
- "sha256:a3d22aab467b4682a22de4a422632e79d07eebd07ff2a7079effb13f8a693787"
+ "sha256:c1af8ca391e43b0a06bbc155f7f67db0bf0d19d284bfc88d1675da497a946124",
+ "sha256:d561a5e511f70275e5a485a6275ff61851c16ffcb3a95a602189161112d9f160"
],
"index": "pypi",
- "version": "==1.15.0"
+ "version": "==3.1.1"
},
"urllib3": {
"hashes": [
- "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
- "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
+ "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
+ "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
],
- "version": "==1.25.8"
+ "version": "==1.25.9"
},
"virtualenv": {
"hashes": [
- "sha256:87831f1070534b636fea2241dd66f3afe37ac9041bcca6d0af3215cdcfbf7d82",
- "sha256:f3128d882383c503003130389bf892856341c1da12c881ae24d6358c82561b55"
+ "sha256:a116629d4e7f4d03433b8afa27f43deba09d48bc48f5ecefa4f015a178efb6cf",
+ "sha256:a730548b27366c5e6cbdf6f97406d861cccece2e22275e8e1a757aeff5e00c70"
],
- "version": "==20.0.13"
+ "version": "==20.0.21"
},
"webencodings": {
"hashes": [
@@ -278,11 +367,10 @@
},
"zipp": {
"hashes": [
- "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1",
- "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"
+ "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
+ "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
],
- "markers": "python_version < '3.8'",
- "version": "==1.2.0"
+ "version": "==3.1.0"
}
}
}
From 1fc92662e00a5b7ea4d3658af35624a9b74a7064 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 01:21:32 -0400
Subject: [PATCH 13/23] test: add chardet to dependencies to install for
testing
---
tox.ini | 1 +
1 file changed, 1 insertion(+)
diff --git a/tox.ini b/tox.ini
index 8cca615..1eadc32 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,6 +13,7 @@ basepython =
py37: python3.7
py38: python3.8
deps =
+ chardet
check-manifest
flake8
pytest
From 070a92b938823e8c6eba844ea474779e5783b277 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 01:22:27 -0400
Subject: [PATCH 14/23] fix: remove FileElement and add all the new ones
---
gedcom/element/element.py | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/gedcom/element/element.py b/gedcom/element/element.py
index 3428e3c..3bc3520 100644
--- a/gedcom/element/element.py
+++ b/gedcom/element/element.py
@@ -206,19 +206,34 @@ def new_child_element(self, tag, pointer="", value=""):
:rtype: Element
"""
from gedcom.element.family import FamilyElement
- from gedcom.element.file import FileElement
from gedcom.element.individual import IndividualElement
+ from gedcom.element.note import NoteElement
from gedcom.element.object import ObjectElement
+ from gedcom.element.repository import RepositoryElement
+ from gedcom.element.source import SourceElement
+ from gedcom.element.submitter import SubmitterElement
+ from gedcom.element.submission import SubmissionElement
+ from gedcom.element.header import HeaderElement
# Differentiate between the type of the new child element
if tag == gedcom.tags.GEDCOM_TAG_FAMILY:
child_element = FamilyElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
- elif tag == gedcom.tags.GEDCOM_TAG_FILE:
- child_element = FileElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
child_element = IndividualElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_NOTE:
+ child_element = NoteElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
child_element = ObjectElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_REPOSITORY:
+ child_element = RepositoryElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_SOURCE:
+ child_element = SourceElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_SUBMITTER:
+ child_element = SubmitterElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_SUBMISSION:
+ child_element = SubmissionElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_HEADER:
+ child_element = HeaderElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
else:
child_element = Element(self.get_level() + 1, pointer, tag, value, self.__crlf)
From df40aff899b86d359c0eb26a1e2e7acb720f0deb Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 01:34:52 -0400
Subject: [PATCH 15/23] fix: fix non-ansel checks and handle UTF-8-SIG
---
gedcom/detect.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/gedcom/detect.py b/gedcom/detect.py
index 37463d6..6de1b11 100644
--- a/gedcom/detect.py
+++ b/gedcom/detect.py
@@ -84,19 +84,19 @@ def get_encoding(file_path):
# gedcom codec with some gedcom specific extensions so we use that.
codec = 'unknown'
probe = chardet.detect(sample_data)
- if probe['encoding'] == 'utf-8':
+ if probe['encoding'] in ['UTF-8', 'UTF-8-SIG']:
codec = 'utf-8-sig'
- elif probe['encoding'] == 'utf-16':
+ elif probe['encoding'] == 'UTF-16':
codec = 'utf-16'
- elif probe['encoding'] == 'ascii':
+ elif probe['encoding'] == 'ASCII':
codec = 'ascii'
- elif probe['encoding'] == 'ansel':
+ elif probe['encoding'] == 'ANSEL':
codec = 'ansel'
elif 'ISO-8859' in probe['encoding']:
if ANSEL_AVAILABLE:
codec = 'gedcom'
else:
- errmsg = "This parser supports ANSEL but the Python ansel module is not " + \
+ errmsg = "This parser can support ANSEL but the Python ansel module is not " + \
"available at this time.\nSee: {0}".format(standards.GEDCOM_5_5_1)
raise GedcomCharacterSetUnsupportedError(errmsg)
From 91533e12e3d40a8df88e4f93c766070eb3a36d3c Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 11:32:40 -0400
Subject: [PATCH 16/23] fix: add back missing exceptions and methods
---
gedcom/errors.py | 46 +++++++-
gedcom/parser.py | 269 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 310 insertions(+), 5 deletions(-)
diff --git a/gedcom/errors.py b/gedcom/errors.py
index 7ed1d31..4522de0 100644
--- a/gedcom/errors.py
+++ b/gedcom/errors.py
@@ -33,24 +33,24 @@
class GedcomFormatViolationError(Exception):
"""Raised when the document format does not appear to conform
- to the standard and strict parsing required.
+ to the GEDCOM standard and strict parsing required.
"""
class GedcomStructureViolationError(Exception):
"""Raised when the structure of a record does not conform to
- the standard.
+ the GEDCOM standard.
"""
class GedcomCharacterSetUnsupportedError(Exception):
- """Raised when a Gedcom appears to contain a character set
- the parser is not yet able to support.
+ """Raised when a GEDCOM appears to contain a character set
+ the standard or the parser does not support.
"""
class GedcomVersionUnsupportedError(Exception):
- """Raised when a particular Gedcom version is not supported
+ """Raised when a particular GEDCOM version is not supported
by the parser and the standard for the version requires the
parser to reject it.
"""
@@ -62,3 +62,39 @@ class GedcomFormatUnsupportedError(Exception):
in the 5.5.5 standard are treated as LINEAGE-LINKED and
allowed.
"""
+
+
+class NotAnActualIndividualError(Exception):
+ """Raised if record does not appear to be an `INDIVIDUAL_RECORD`"""
+
+
+class NotAnActualFamilyError(Exception):
+ """Raised if record does not appear to be a `FAM_RECORD`"""
+
+
+class NotAnActualSourceError(Exception):
+ """Raised if record does not appear to be a `SOURCE_RECORD`"""
+
+
+class NotAnActualRepositoryError(Exception):
+ """Raised if record does not appear to be a `REPOSITORY_RECORD`"""
+
+
+class NotAnActualNoteError(Exception):
+ """Raised if record does not appear to be a `NOTE_RECORD`"""
+
+
+class NotAnActualObjectError(Exception):
+ """Raised if record does not appear to be a `MULTIMEDIA_RECORD`"""
+
+
+class NotAnActualHeaderError(Exception):
+ """Raised if record does not appear to be a `HEADER`"""
+
+
+class NotAnActualSubmitterError(Exception):
+ """Raised if record does not appear to be a `SUBMITTER_RECORD`"""
+
+
+class NotAnActualSubmissionError(Exception):
+ """Raised if record does not appear to be a `SUBMISSION_RECORD`"""
diff --git a/gedcom/parser.py b/gedcom/parser.py
index c1d72e4..b4a7848 100644
--- a/gedcom/parser.py
+++ b/gedcom/parser.py
@@ -32,6 +32,7 @@
"""
import re as regex
+from sys import version_info
import gedcom.tags as tags
import gedcom.standards as standards
@@ -52,6 +53,8 @@
from gedcom.errors import GedcomVersionUnsupportedError
from gedcom.errors import GedcomFormatUnsupportedError
from gedcom.errors import GedcomFormatViolationError
+from gedcom.errors import NotAnActualIndividualError
+from gedcom.errors import NotAnActualFamilyError
ERROR_TEMPLATE = "Line <{0}:{1}> of document violates GEDCOM format {2}\nSee: {3}"
@@ -67,6 +70,12 @@
tags.GEDCOM_TAG_REPOSITORY: RepositoryElement
}
+FAMILY_MEMBERS_TYPE_ALL = "ALL"
+FAMILY_MEMBERS_TYPE_CHILDREN = tags.GEDCOM_TAG_CHILD
+FAMILY_MEMBERS_TYPE_HUSBAND = tags.GEDCOM_TAG_HUSBAND
+FAMILY_MEMBERS_TYPE_PARENTS = "PARENTS"
+FAMILY_MEMBERS_TYPE_WIFE = tags.GEDCOM_TAG_WIFE
+
class Parser():
"""Parses and manipulates GEDCOM 5.5 format data
@@ -304,3 +313,263 @@ def __build_list(self, element, element_list):
element_list.append(element)
for child in element.get_child_elements():
self.__build_list(child, element_list)
+
+ # Methods for analyzing individuals and relationships between individuals
+
+ def get_marriages(self, individual):
+ """Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
+ :type individual: IndividualElement
+ :rtype: tuple
+ """
+ marriages = []
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+ # Get and analyze families where individual is spouse.
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ for family in families:
+ for family_data in family.get_child_elements():
+ if family_data.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
+ date = ''
+ place = ''
+ for marriage_data in family_data.get_child_elements():
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = marriage_data.get_value()
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = marriage_data.get_value()
+ marriages.append((date, place))
+ return marriages
+
+ def get_marriage_years(self, individual):
+ """Returns a list of marriage years (as integers) for an individual
+ :type individual: IndividualElement
+ :rtype: list of int
+ """
+ dates = []
+
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ # Get and analyze families where individual is spouse.
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ for family in families:
+ for child in family.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
+ for childOfChild in child.get_child_elements():
+ if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = childOfChild.get_value().split()[-1]
+ try:
+ dates.append(int(date))
+ except ValueError:
+ pass
+ return dates
+
+ def marriage_year_match(self, individual, year):
+ """Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
+ :type individual: IndividualElement
+ :type year: int
+ :rtype: bool
+ """
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ years = self.get_marriage_years(individual)
+ return year in years
+
+ def marriage_range_match(self, individual, from_year, to_year):
+ """Check if one of the marriage years of an individual is in a given range. Years are integers.
+ :type individual: IndividualElement
+ :type from_year: int
+ :type to_year: int
+ :rtype: bool
+ """
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ years = self.get_marriage_years(individual)
+ for year in years:
+ if from_year <= year <= to_year:
+ return True
+ return False
+
+ def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
+ """Return family elements listed for an individual
+ family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
+ `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
+ provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
+ :type individual: IndividualElement
+ :type family_type: str
+ :rtype: list of FamilyElement
+ """
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ families = []
+ element_dictionary = self.get_element_dictionary()
+
+ for child_element in individual.get_child_elements():
+ is_family = (child_element.get_tag() == family_type
+ and child_element.get_value() in element_dictionary
+ and element_dictionary[child_element.get_value()].is_family())
+ if is_family:
+ families.append(element_dictionary[child_element.get_value()])
+
+ return families
+
+ def get_ancestors(self, individual, ancestor_type="ALL"):
+ """Return elements corresponding to ancestors of an individual
+ Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
+ used to specify only natural (genetic) ancestors.
+ :type individual: IndividualElement
+ :type ancestor_type: str
+ :rtype: list of Element
+ """
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ parents = self.get_parents(individual, ancestor_type)
+ ancestors = []
+ ancestors.extend(parents)
+
+ for parent in parents:
+ ancestors.extend(self.get_ancestors(parent))
+
+ return ancestors
+
+ def get_parents(self, individual, parent_type="ALL"):
+ """Return elements corresponding to parents of an individual
+ Optional parent_type. Default "ALL" returns all parents. "NAT" can be
+ used to specify only natural (genetic) parents.
+ :type individual: IndividualElement
+ :type parent_type: str
+ :rtype: list of IndividualElement
+ """
+ if not isinstance(individual, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ parents = []
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_CHILD)
+
+ for family in families:
+ if parent_type == "NAT":
+ for family_member in family.get_child_elements():
+
+ if family_member.get_tag() == tags.GEDCOM_TAG_CHILD \
+ and family_member.get_value() == individual.get_pointer():
+
+ for child in family_member.get_child_elements():
+ if child.get_value() == "Natural":
+ if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
+ else:
+ parents += self.get_family_members(family, "PARENTS")
+
+ return parents
+
+ def find_path_to_ancestor(self, descendant, ancestor, path=None):
+ """Return path from descendant to ancestor
+ :rtype: object
+ """
+ if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
+ raise NotAnActualIndividualError(
+ "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
+ )
+
+ if not path:
+ path = [descendant]
+
+ if path[-1].get_pointer() == ancestor.get_pointer():
+ return path
+ else:
+ parents = self.get_parents(descendant, "NAT")
+ for parent in parents:
+ potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
+ if potential_path is not None:
+ return potential_path
+
+ return None
+
+ def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
+ """Return array of family members: individual, spouse, and children
+ Optional argument `members_type` can be used to return specific subsets:
+ "FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+ "FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
+ "FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
+ "FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
+ "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
+ :type family: FamilyElement
+ :type members_type: str
+ :rtype: list of IndividualElement
+ """
+ if not isinstance(family, FamilyElement):
+ raise NotAnActualFamilyError(
+ "Operation only valid for element with %s tag." % tags.GEDCOM_TAG_FAMILY
+ )
+
+ family_members = []
+ element_dictionary = self.get_element_dictionary()
+
+ for child_element in family.get_child_elements():
+ # Default is ALL
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE
+ or child_element.get_tag() == tags.GEDCOM_TAG_CHILD)
+
+ if members_type == FAMILY_MEMBERS_TYPE_PARENTS:
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE)
+ elif members_type == FAMILY_MEMBERS_TYPE_HUSBAND:
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ elif members_type == FAMILY_MEMBERS_TYPE_WIFE:
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_WIFE
+ elif members_type == FAMILY_MEMBERS_TYPE_CHILDREN:
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_CHILD
+
+ if is_family and child_element.get_value() in element_dictionary:
+ family_members.append(element_dictionary[child_element.get_value()])
+
+ return family_members
+
+ # Other methods
+
+ def to_gedcom_string(self, recursive=False):
+ """Formats all elements and optionally all of the sub-elements into a GEDCOM string
+ :type recursive: bool
+ """
+ is_gte_python_3 = version_info[0] >= 3
+ output = '' if is_gte_python_3 else b''
+
+ for element in self.get_root_child_elements():
+ if is_gte_python_3:
+ output += element.to_gedcom_string(recursive)
+ else:
+ output += element.to_gedcom_string(recursive).encode('utf-8-sig')
+
+ return output
+
+ def print_gedcom(self):
+ """Write GEDCOM data to stdout"""
+ from sys import stdout
+ self.save_gedcom(stdout)
+
+ def save_gedcom(self, open_file, recursive=True):
+ """Save GEDCOM data to a file
+ :type open_file: file
+ :type recursive: bool
+ """
+ open_file.write(self.to_gedcom_string(recursive))
From d3509f89cdcbdc42f7d0c99e9d5e5cba3dea0c57 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 11:34:03 -0400
Subject: [PATCH 17/23] test: remove utf-8-sig encoding
---
tests/test_parser.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 451a3fa..615a347 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -62,7 +62,7 @@ def test_parse_from_string():
4 LONG W122.234319
"""
gedcom_parser = Parser()
- gedcom_parser.parse([(a + '\n').encode('utf-8-sig') for a in case_1.splitlines()])
+ gedcom_parser.parse([(a + '\n') for a in case_1.splitlines()])
element_1 = gedcom_parser.get_root_child_elements()[0]
assert isinstance(element_1, IndividualElement)
assert element_1.get_tag() == 'INDI'
@@ -86,7 +86,7 @@ def test_parse_from_string():
2 _FREL Natural
2 _MREL Natural
"""
- gedcom_parser.parse([(a + '\n').encode('utf-8-sig') for a in case_2.splitlines()])
+ gedcom_parser.parse([(a + '\n') for a in case_2.splitlines()])
element_2 = gedcom_parser.get_root_child_elements()[0]
assert element_2.get_tag() == 'FAM'
assert element_2.get_pointer() == '@F28@'
@@ -112,7 +112,7 @@ def test_to_gedcom_string():
"""
gedcom_parser = Parser()
- gedcom_parser.parse([(a + '\n').encode('utf-8-sig') for a in case_1.splitlines()])
+ gedcom_parser.parse([(a + '\n') for a in case_1.splitlines()])
case_1_string_array = case_1.splitlines()
gedcom_string = gedcom_parser.to_gedcom_string(True)
From 4b5540aa95acc5c8ee04e369136a51fd0cda1d33 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 12:14:36 -0400
Subject: [PATCH 18/23] fix: fix tag name type, is associates not associations
---
gedcom/subparsers/association_structure.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gedcom/subparsers/association_structure.py b/gedcom/subparsers/association_structure.py
index 3e389de..53e5891 100644
--- a/gedcom/subparsers/association_structure.py
+++ b/gedcom/subparsers/association_structure.py
@@ -22,7 +22,7 @@
"""
Substructure parser for the ASSOCIATION_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_ASSOCIATION` tag.
+`gedcom.tags.GEDCOM_TAG_ASSOCIATES` tag.
"""
import gedcom.tags as tags
From f54521690b6132bba5c2bbb733e8be498bf46471 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 12:16:13 -0400
Subject: [PATCH 19/23] build: add ansel to dependencies so always available
and enabled
---
Pipfile | 1 +
Pipfile.lock | 119 +++++++++++------------------------------------
gedcom/detect.py | 18 ++-----
tox.ini | 1 +
4 files changed, 34 insertions(+), 105 deletions(-)
diff --git a/Pipfile b/Pipfile
index a30b2bf..642e6a1 100644
--- a/Pipfile
+++ b/Pipfile
@@ -12,6 +12,7 @@ pdoc3 = "*"
[packages]
chardet = "*"
+ansel = "*"
[requires]
python_version = "3.5"
diff --git a/Pipfile.lock b/Pipfile.lock
index bd3c135..3e13e07 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "84143c137ae9e2186b45e36a41936a9d4d3d07568627cad373a3f1bbf30f3c68"
+ "sha256": "25eda2701127ac3899d81381bca449f6bcc14ee7afe4ae9c5b2f683afd95dd03"
},
"pipfile-spec": 6,
"requires": {
@@ -16,6 +16,14 @@
]
},
"default": {
+ "ansel": {
+ "hashes": [
+ "sha256:27c1a849b1a683a2b3befd50e9156bda3527e8026f6bc6f04c3d0a2b9cadeed9",
+ "sha256:3cb2c6a726dcf674bcd1cbd1fc4f35b80167b1c090ea94f6bc60c70f4e615eab"
+ ],
+ "index": "pypi",
+ "version": "==0.1.1"
+ },
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
@@ -23,6 +31,13 @@
],
"index": "pypi",
"version": "==3.0.4"
+ },
+ "six": {
+ "hashes": [
+ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
+ "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
+ ],
+ "version": "==1.15.0"
}
},
"develop": {
@@ -47,39 +62,6 @@
],
"version": "==2020.4.5.1"
},
- "cffi": {
- "hashes": [
- "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff",
- "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b",
- "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac",
- "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0",
- "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384",
- "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26",
- "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6",
- "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b",
- "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e",
- "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd",
- "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2",
- "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66",
- "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc",
- "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8",
- "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55",
- "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4",
- "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5",
- "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d",
- "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78",
- "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa",
- "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793",
- "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f",
- "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a",
- "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f",
- "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30",
- "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f",
- "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3",
- "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"
- ],
- "version": "==1.14.0"
- },
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
@@ -88,30 +70,6 @@
"index": "pypi",
"version": "==3.0.4"
},
- "cryptography": {
- "hashes": [
- "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6",
- "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b",
- "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5",
- "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf",
- "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e",
- "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b",
- "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae",
- "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b",
- "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0",
- "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b",
- "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d",
- "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229",
- "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3",
- "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365",
- "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55",
- "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270",
- "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e",
- "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785",
- "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"
- ],
- "version": "==2.9.2"
- },
"distlib": {
"hashes": [
"sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"
@@ -147,20 +105,13 @@
"markers": "python_version < '3.8'",
"version": "==1.6.0"
},
- "jeepney": {
- "hashes": [
- "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e",
- "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf"
- ],
- "markers": "sys_platform == 'linux'",
- "version": "==0.4.3"
- },
- "keyring": {
+ "importlib-resources": {
"hashes": [
- "sha256:3401234209015144a5d75701e71cb47239e552b0882313e9f51e8976f9e27843",
- "sha256:c53e0e5ccde3ad34284a40ce7976b5b3a3d6de70344c3f8ee44364cc340976ec"
+ "sha256:6f87df66833e1942667108628ec48900e02a4ab4ad850e25fbf07cb17cf734ca",
+ "sha256:85dc0b9b325ff78c8bef2e4ff42616094e16b98ebd5e3b50fe7e2f0bbcdcde49"
],
- "version": "==21.2.1"
+ "markers": "python_version < '3.7'",
+ "version": "==1.5.0"
},
"mako": {
"hashes": [
@@ -249,13 +200,6 @@
],
"version": "==1.8.1"
},
- "pycparser": {
- "hashes": [
- "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
- "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
- ],
- "version": "==2.20"
- },
"pygments": {
"hashes": [
"sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
@@ -291,14 +235,6 @@
],
"version": "==0.9.1"
},
- "secretstorage": {
- "hashes": [
- "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6",
- "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b"
- ],
- "markers": "sys_platform == 'linux'",
- "version": "==3.1.2"
- },
"six": {
"hashes": [
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
@@ -330,11 +266,11 @@
},
"twine": {
"hashes": [
- "sha256:c1af8ca391e43b0a06bbc155f7f67db0bf0d19d284bfc88d1675da497a946124",
- "sha256:d561a5e511f70275e5a485a6275ff61851c16ffcb3a95a602189161112d9f160"
+ "sha256:630fadd6e342e725930be6c696537e3f9ccc54331742b16245dab292a17d0460",
+ "sha256:a3d22aab467b4682a22de4a422632e79d07eebd07ff2a7079effb13f8a693787"
],
"index": "pypi",
- "version": "==3.1.1"
+ "version": "==1.15.0"
},
"urllib3": {
"hashes": [
@@ -367,10 +303,11 @@
},
"zipp": {
"hashes": [
- "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
- "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
+ "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1",
+ "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"
],
- "version": "==3.1.0"
+ "markers": "python_version < '3.8'",
+ "version": "==1.2.0"
}
}
}
diff --git a/gedcom/detect.py b/gedcom/detect.py
index 6de1b11..e0ad5aa 100644
--- a/gedcom/detect.py
+++ b/gedcom/detect.py
@@ -31,18 +31,13 @@
"""
import chardet
+import ansel
import gedcom.standards as standards
-
from gedcom.errors import GedcomFormatViolationError
from gedcom.errors import GedcomCharacterSetUnsupportedError
-try:
- import ansel
- ansel.register()
- ANSEL_AVAILABLE = True
-except ModuleNotFoundError:
- ANSEL_AVAILABLE = False
+ansel.register()
def validate_encoding(file_path, codec):
@@ -93,12 +88,7 @@ def get_encoding(file_path):
elif probe['encoding'] == 'ANSEL':
codec = 'ansel'
elif 'ISO-8859' in probe['encoding']:
- if ANSEL_AVAILABLE:
- codec = 'gedcom'
- else:
- errmsg = "This parser can support ANSEL but the Python ansel module is not " + \
- "available at this time.\nSee: {0}".format(standards.GEDCOM_5_5_1)
- raise GedcomCharacterSetUnsupportedError(errmsg)
+ codec = 'gedcom'
if codec == 'unknown':
errmsg = "Unable to properly identify a supported GEDCOM character encoding for" + \
@@ -139,7 +129,7 @@ def get_version(file_path, codec):
real_version = gedcom_version
- # UTF came in the 5.5.1 specification
+ # UTF was added in the 5.5.1 specification
if gedcom_version == '5.5' and 'utf' in codec:
real_version = gedcom_version
diff --git a/tox.ini b/tox.ini
index 1eadc32..2f00a83 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,6 +14,7 @@ basepython =
py38: python3.8
deps =
chardet
+ ansel
check-manifest
flake8
pytest
From 2a09015631ae8b604211d527a6e033faa5331a72 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 17:59:04 -0400
Subject: [PATCH 20/23] feat: add record types supported by reader
---
gedcom/records.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 gedcom/records.py
diff --git a/gedcom/records.py b/gedcom/records.py
new file mode 100644
index 0000000..a2ae70f
--- /dev/null
+++ b/gedcom/records.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""Module containing the standard GEDCOM record types recognized by the
+GEDCOM `gedcom.reader.Reader`."""
+
+
+GEDCOM_RECORD_FAMILY = 'family'
+"""Identifies the `FAM_RECORD` record type."""
+
+GEDCOM_RECORD_HEADER = 'header'
+"""Identifies the `HEADER` record type."""
+
+GEDCOM_RECORD_INDIVIDUAL = 'individual'
+"""Identifies the `INDIVIDUAL_RECORD` record type."""
+
+GEDCOM_RECORD_NOTE = 'note'
+"""Identifies the `NOTE_RECORD` record type."""
+
+GEDCOM_RECORD_SOURCE = 'source'
+"""Identifies the `SOURCE_RECORD` record type."""
+
+GEDCOM_RECORD_REPOSITORY = 'repository'
+"""Identifies the `REPOSITORY_RECORD` record type."""
+
+GEDCOM_RECORD_SUBMISSION = 'submission'
+"""Identifies the `SUBMISSION_RECORD` record type."""
+
+GEDCOM_RECORD_SUBMITTER = 'submitter'
+"""Identifies the `SUBMITTER_RECORD` record type."""
From c3aa2337368c681928bdfebfd5d4564dd026106d Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 18:00:32 -0400
Subject: [PATCH 21/23] feat: add typing hints to everything, update doc
strings, update docs
---
docs/gedcom/detect.html | 319 +++
docs/gedcom/element/element.html | 138 +-
docs/gedcom/element/family.html | 325 ++-
docs/gedcom/element/header.html | 502 +++++
docs/gedcom/element/index.html | 69 +-
docs/gedcom/element/individual.html | 838 +++++---
docs/gedcom/element/note.html | 265 +++
docs/gedcom/element/object.html | 287 ++-
docs/gedcom/element/repository.html | 293 +++
docs/gedcom/element/root.html | 10 +-
docs/gedcom/element/source.html | 424 ++++
docs/gedcom/element/submission.html | 274 +++
docs/gedcom/element/submitter.html | 323 +++
docs/gedcom/errors.html | 495 +++++
docs/gedcom/helpers.html | 12 +-
docs/gedcom/index.html | 64 +-
docs/gedcom/parser.html | 731 ++++---
docs/gedcom/reader.html | 375 ++++
docs/gedcom/standards.html | 123 ++
docs/gedcom/subparsers/address_structure.html | 195 ++
.../subparsers/association_structure.html | 159 ++
docs/gedcom/subparsers/change_date.html | 156 ++
.../subparsers/child_to_family_link.html | 158 ++
docs/gedcom/subparsers/event_detail.html | 209 ++
.../subparsers/family_event_detail.html | 152 ++
.../subparsers/family_event_structure.html | 155 ++
docs/gedcom/subparsers/index.html | 235 ++
.../individual_attribute_structure.html | 160 ++
.../subparsers/individual_event_detail.html | 134 ++
.../individual_event_structure.html | 228 ++
.../subparsers/lds_individual_ordinance.html | 215 ++
.../gedcom/subparsers/lds_spouse_sealing.html | 204 ++
docs/gedcom/subparsers/multimedia_link.html | 186 ++
docs/gedcom/subparsers/note_structure.html | 139 ++
.../subparsers/personal_name_pieces.html | 181 ++
.../subparsers/personal_name_structure.html | 191 ++
docs/gedcom/subparsers/place_structure.html | 220 ++
docs/gedcom/subparsers/source_citation.html | 230 ++
.../source_repository_citation.html | 164 ++
.../subparsers/spouse_to_family_link.html | 138 ++
.../subparsers/user_reference_number.html | 137 ++
docs/gedcom/tags.html | 1885 ++++++++++++++++-
gedcom/__init__.py | 1 +
gedcom/detect.py | 41 +-
gedcom/element/element.py | 147 +-
gedcom/element/family.py | 7 +-
gedcom/element/header.py | 7 +-
gedcom/element/individual.py | 143 +-
gedcom/element/note.py | 7 +-
gedcom/element/object.py | 7 +-
gedcom/element/repository.py | 7 +-
gedcom/element/root.py | 5 +-
gedcom/element/source.py | 7 +-
gedcom/element/submission.py | 5 +-
gedcom/element/submitter.py | 5 +-
gedcom/errors.py | 8 +-
gedcom/parser.py | 203 +-
gedcom/reader.py | 32 +-
gedcom/standards.py | 10 +-
gedcom/subparsers/address_structure.py | 14 +-
gedcom/subparsers/association_structure.py | 13 +-
gedcom/subparsers/change_date.py | 13 +-
gedcom/subparsers/child_to_family_link.py | 13 +-
gedcom/subparsers/event_detail.py | 13 +-
gedcom/subparsers/family_event_detail.py | 13 +-
gedcom/subparsers/family_event_structure.py | 15 +-
.../individual_attribute_structure.py | 15 +-
gedcom/subparsers/individual_event_detail.py | 13 +-
.../subparsers/individual_event_structure.py | 15 +-
gedcom/subparsers/lds_individual_ordinance.py | 15 +-
gedcom/subparsers/lds_spouse_sealing.py | 15 +-
gedcom/subparsers/multimedia_link.py | 13 +-
gedcom/subparsers/note_structure.py | 14 +-
gedcom/subparsers/personal_name_pieces.py | 13 +-
gedcom/subparsers/personal_name_structure.py | 26 +-
gedcom/subparsers/place_structure.py | 13 +-
gedcom/subparsers/source_citation.py | 13 +-
.../subparsers/source_repository_citation.py | 13 +-
gedcom/subparsers/spouse_to_family_link.py | 13 +-
gedcom/subparsers/user_reference_number.py | 15 +-
gedcom/tags.py | 61 +-
81 files changed, 11271 insertions(+), 1430 deletions(-)
create mode 100644 docs/gedcom/detect.html
create mode 100644 docs/gedcom/element/header.html
create mode 100644 docs/gedcom/element/note.html
create mode 100644 docs/gedcom/element/repository.html
create mode 100644 docs/gedcom/element/source.html
create mode 100644 docs/gedcom/element/submission.html
create mode 100644 docs/gedcom/element/submitter.html
create mode 100644 docs/gedcom/errors.html
create mode 100644 docs/gedcom/reader.html
create mode 100644 docs/gedcom/standards.html
create mode 100644 docs/gedcom/subparsers/address_structure.html
create mode 100644 docs/gedcom/subparsers/association_structure.html
create mode 100644 docs/gedcom/subparsers/change_date.html
create mode 100644 docs/gedcom/subparsers/child_to_family_link.html
create mode 100644 docs/gedcom/subparsers/event_detail.html
create mode 100644 docs/gedcom/subparsers/family_event_detail.html
create mode 100644 docs/gedcom/subparsers/family_event_structure.html
create mode 100644 docs/gedcom/subparsers/index.html
create mode 100644 docs/gedcom/subparsers/individual_attribute_structure.html
create mode 100644 docs/gedcom/subparsers/individual_event_detail.html
create mode 100644 docs/gedcom/subparsers/individual_event_structure.html
create mode 100644 docs/gedcom/subparsers/lds_individual_ordinance.html
create mode 100644 docs/gedcom/subparsers/lds_spouse_sealing.html
create mode 100644 docs/gedcom/subparsers/multimedia_link.html
create mode 100644 docs/gedcom/subparsers/note_structure.html
create mode 100644 docs/gedcom/subparsers/personal_name_pieces.html
create mode 100644 docs/gedcom/subparsers/personal_name_structure.html
create mode 100644 docs/gedcom/subparsers/place_structure.html
create mode 100644 docs/gedcom/subparsers/source_citation.html
create mode 100644 docs/gedcom/subparsers/source_repository_citation.html
create mode 100644 docs/gedcom/subparsers/spouse_to_family_link.html
create mode 100644 docs/gedcom/subparsers/user_reference_number.html
diff --git a/docs/gedcom/detect.html b/docs/gedcom/detect.html
new file mode 100644
index 0000000..a0aa942
--- /dev/null
+++ b/docs/gedcom/detect.html
@@ -0,0 +1,319 @@
+
+
+
+
+
+
+gedcom.detect API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.detect
+
+
+
Functions to detect GEDCOM encoding and version.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Functions to detect GEDCOM encoding and version.
+"""
+
+import chardet
+import ansel
+
+import gedcom.tags as tags
+import gedcom.standards as standards
+from gedcom.errors import GedcomFormatViolationError
+from gedcom.errors import GedcomCharacterSetUnsupportedError
+
+ansel.register()
+
+
+def __validate_encoding(file_path, codec):
+ """Check the encoding is compatible with the encoding as reported by the `gedcom.tags.GEDCOM_TAG_CHARACTER` header tag.
+
+ :type file_path: str
+
+ :type codec: str
+ """
+ with open(file_path, 'r', encoding=codec) as gedcom_data:
+ for line in gedcom_data:
+ if tags.GEDCOM_TAG_CHARACTER in line:
+ character_set = line.split(' ')[2].lower().strip()
+ break
+
+ if character_set == 'ansel' and codec == 'gedcom':
+ return
+
+ if character_set == 'ascii' and codec == 'utf-8':
+ return
+
+ if character_set not in codec:
+ errmsg = "A " + codec + " encoding was detected but the GEDCOM reports using " + \
+ "a " + character_set + " encoding.\n" + \
+ "Processing aborted as unsure how to properly proceed.\n" + \
+ "See: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomCharacterSetUnsupportedError(errmsg)
+
+
+def get_encoding(file_path):
+ """Probe a GEDCOM file to determine the encoding and validate it against the encoding reported in the file header by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
+
+ :type file_path: str
+
+ :rtype: str
+ """
+ with open(file_path, 'rb') as gedcom_data:
+ sample_data = gedcom_data.read(262144)
+
+ # Note chardet reports Ansel as ISO-8859-1 or ISO-8859-2 at this time
+ # depending on sample size, and could be making a faulty assumption here
+ # by treating it as Ansel. The ansel module supports both ansel and a
+ # gedcom codec with some gedcom specific extensions so we use that.
+ codec = 'unknown'
+ probe = chardet.detect(sample_data)
+ if probe['encoding'] in ['UTF-8', 'UTF-8-SIG']:
+ codec = 'utf-8-sig'
+ elif probe['encoding'] == 'UTF-16':
+ codec = 'utf-16'
+ elif probe['encoding'] == 'ASCII':
+ codec = 'ascii'
+ elif probe['encoding'] == 'ANSEL':
+ codec = 'ansel'
+ elif 'ISO-8859' in probe['encoding']:
+ codec = 'gedcom'
+
+ if codec == 'unknown':
+ errmsg = "Unable to properly identify a supported GEDCOM character encoding for" + \
+ "the file.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomCharacterSetUnsupportedError(errmsg)
+
+ __validate_encoding(file_path, codec)
+ return codec
+
+
+def get_version(file_path, codec):
+ """Probes a GEDCOM file to identify the version of the standard used as some reported 5.5 files are really 5.5.1. Returns probed version, reported version, reported format
+
+ :type file_path: str
+
+ :type codec: str
+
+ :rtype real_version: str
+
+ :rtype reported_version: str
+
+ :rtype reported_format: str
+ """
+ in_gedc_tag = False
+ gedcom_version = None
+ gedcom_format = None
+ with open(file_path, 'r', encoding=codec) as gedcom_data:
+ for line in gedcom_data:
+ if '1 GEDC' in line:
+ in_gedc_tag = True
+ continue
+ if in_gedc_tag:
+ if '2 VERS' in line:
+ gedcom_version = line.split(' ')[2].strip()
+ continue
+ if '2 FORM' in line:
+ gedcom_format = line.split(' ')[2].strip()
+ break
+
+ if gedcom_version is None or gedcom_format is None:
+ errmsg = "Malformed GEDCOM file, the required version number or format were" + \
+ " not found as expected.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
+
+ real_version = gedcom_version
+
+ # UTF was added in the 5.5.1 specification
+ if gedcom_version == '5.5' and 'utf' in codec:
+ real_version = gedcom_version
+
+ return real_version, gedcom_version, gedcom_format
+
+
+
+
+
+
+
+
Functions
+
+
+def get_encoding(file_path)
+
+
+
Probe a GEDCOM file to determine the encoding and validate it against the encoding reported in the file header by the GEDCOM_TAG_CHARACTER tag.
+
:type file_path: str
+
:rtype: str
+
+
+Expand source code
+
+
def get_encoding(file_path):
+ """Probe a GEDCOM file to determine the encoding and validate it against the encoding reported in the file header by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
+
+ :type file_path: str
+
+ :rtype: str
+ """
+ with open(file_path, 'rb') as gedcom_data:
+ sample_data = gedcom_data.read(262144)
+
+ # Note chardet reports Ansel as ISO-8859-1 or ISO-8859-2 at this time
+ # depending on sample size, and could be making a faulty assumption here
+ # by treating it as Ansel. The ansel module supports both ansel and a
+ # gedcom codec with some gedcom specific extensions so we use that.
+ codec = 'unknown'
+ probe = chardet.detect(sample_data)
+ if probe['encoding'] in ['UTF-8', 'UTF-8-SIG']:
+ codec = 'utf-8-sig'
+ elif probe['encoding'] == 'UTF-16':
+ codec = 'utf-16'
+ elif probe['encoding'] == 'ASCII':
+ codec = 'ascii'
+ elif probe['encoding'] == 'ANSEL':
+ codec = 'ansel'
+ elif 'ISO-8859' in probe['encoding']:
+ codec = 'gedcom'
+
+ if codec == 'unknown':
+ errmsg = "Unable to properly identify a supported GEDCOM character encoding for" + \
+ "the file.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomCharacterSetUnsupportedError(errmsg)
+
+ __validate_encoding(file_path, codec)
+ return codec
+
+
+
+def get_version(file_path, codec)
+
+
+
Probes a GEDCOM file to identify the version of the standard used as some reported 5.5 files are really 5.5.1. Returns probed version, reported version, reported format
+
:type file_path: str
+
:type codec: str
+
:rtype real_version: str
+
:rtype reported_version: str
+
:rtype reported_format: str
+
+
+Expand source code
+
+
def get_version(file_path, codec):
+ """Probes a GEDCOM file to identify the version of the standard used as some reported 5.5 files are really 5.5.1. Returns probed version, reported version, reported format
+
+ :type file_path: str
+
+ :type codec: str
+
+ :rtype real_version: str
+
+ :rtype reported_version: str
+
+ :rtype reported_format: str
+ """
+ in_gedc_tag = False
+ gedcom_version = None
+ gedcom_format = None
+ with open(file_path, 'r', encoding=codec) as gedcom_data:
+ for line in gedcom_data:
+ if '1 GEDC' in line:
+ in_gedc_tag = True
+ continue
+ if in_gedc_tag:
+ if '2 VERS' in line:
+ gedcom_version = line.split(' ')[2].strip()
+ continue
+ if '2 FORM' in line:
+ gedcom_format = line.split(' ')[2].strip()
+ break
+
+ if gedcom_version is None or gedcom_format is None:
+ errmsg = "Malformed GEDCOM file, the required version number or format were" + \
+ " not found as expected.\nSee: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
+
+ real_version = gedcom_version
+
+ # UTF was added in the 5.5.1 specification
+ if gedcom_version == '5.5' and 'utf' in codec:
+ real_version = gedcom_version
+
+ return real_version, gedcom_version, gedcom_format
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/element/element.html b/docs/gedcom/element/element.html
index 7d9c271..468890c 100644
--- a/docs/gedcom/element/element.html
+++ b/docs/gedcom/element/element.html
@@ -3,14 +3,14 @@
-
+
gedcom.element.element API documentation
-
-
+
+
@@ -233,19 +233,34 @@
Module gedcom.element.element
:rtype: Element
"""
from gedcom.element.family import FamilyElement
- from gedcom.element.file import FileElement
from gedcom.element.individual import IndividualElement
+ from gedcom.element.note import NoteElement
from gedcom.element.object import ObjectElement
+ from gedcom.element.repository import RepositoryElement
+ from gedcom.element.source import SourceElement
+ from gedcom.element.submitter import SubmitterElement
+ from gedcom.element.submission import SubmissionElement
+ from gedcom.element.header import HeaderElement
# Differentiate between the type of the new child element
if tag == gedcom.tags.GEDCOM_TAG_FAMILY:
child_element = FamilyElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
- elif tag == gedcom.tags.GEDCOM_TAG_FILE:
- child_element = FileElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
child_element = IndividualElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_NOTE:
+ child_element = NoteElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
child_element = ObjectElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_REPOSITORY:
+ child_element = RepositoryElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_SOURCE:
+ child_element = SourceElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_SUBMITTER:
+ child_element = SubmitterElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_SUBMISSION:
+ child_element = SubmissionElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ elif tag == gedcom.tags.GEDCOM_TAG_HEADER:
+ child_element = HeaderElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
else:
child_element = Element(self.get_level() + 1, pointer, tag, value, self.__crlf)
@@ -336,7 +351,7 @@
Returns the direct child elements of this element
-:rtype: list of Element
+
Returns the direct child elements of this element
+:rtype: list of Element
Expand source code
@@ -673,9 +708,9 @@
Methods
def get_individual(self)
-
Returns this element and all of its sub-elements represented as a GEDCOM string
+
Returns this element and all of its sub-elements represented as a GEDCOM string
::deprecated:: As of version 1.0.0 use to_gedcom_string() method instead
-:rtype: str
+:rtype: str
Expand source code
@@ -693,8 +728,8 @@
Methods
def get_level(self)
-
Returns the level of this element from within the GEDCOM file
-:rtype: int
+
Returns the level of this element from within the GEDCOM file
+:rtype: int
Expand source code
@@ -710,8 +745,8 @@
Methods
def get_multi_line_value(self)
-
Returns the value of this element including concatenations or continuations
-:rtype: str
+
Returns the value of this element including concatenations or continuations
+:rtype: str
Expand source code
@@ -737,8 +772,8 @@
Methods
def get_parent_element(self)
-
Returns the parent element of this element
-:rtype: Element
+
Returns the parent element of this element
+:rtype: Element
Expand source code
@@ -754,8 +789,8 @@
Methods
def get_pointer(self)
-
Returns the pointer of this element from within the GEDCOM file
-:rtype: str
+
Returns the pointer of this element from within the GEDCOM file
+:rtype: str
Expand source code
@@ -771,8 +806,8 @@
Methods
def get_tag(self)
-
Returns the tag of this element from within the GEDCOM file
-:rtype: str
+
Returns the tag of this element from within the GEDCOM file
+:rtype: str
Expand source code
@@ -788,8 +823,8 @@
Methods
def get_value(self)
-
Return the value of this element from within the GEDCOM file
-:rtype: str
+
Return the value of this element from within the GEDCOM file
+:rtype: str
Each line in a GEDCOM file is an element with the format
-
level [pointer] tag [value]
-
where level and tag are required, and pointer and value are
-optional.
-Elements are arranged hierarchically according to their
-level, and elements with a level of zero are at the top level.
-Elements with a level greater than zero are children of their
-parent.
-
A pointer has the format @pname@, where pname is any sequence of
-characters and numbers. The pointer identifies the object being
-pointed to, so that any pointer included as the value of any
-element points back to the original object.
-For example, an
-element may have a FAMS tag whose value is @F1@, meaning that this
-element points to the family record in which the associated person
-is a spouse. Likewise, an element with a tag of FAMC has a value
-that points to a family record in which the associated person is a
-child.
-
See a GEDCOM file for examples of tags and their values.
-
Tags available to an element are seen here: gedcom.tags
+
Element associated with a FAM_RECORD
Expand source code
class FamilyElement(Element):
+ """Element associated with a `FAM_RECORD`"""
def get_tag(self):
- return gedcom.tags.GEDCOM_TAG_FAMILY
+ return tags.GEDCOM_TAG_FAMILY
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': self.get_pointer(),
+ 'restriction': '',
+ 'events': family_event_structure(self),
+ 'key_to_husband': '',
+ 'key_to_wife': '',
+ 'children': [],
+ 'number_of_children': '',
+ 'submitters': [],
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ lds_events = lds_spouse_sealing(self)
+ if len(lds_events) > 0:
+ for event in lds_events:
+ record['events'].append(event)
+
+ for child in self.get_child_elements():
+ if child.get_tag() in FAMILY_SINGLE_TAGS:
+ record[FAMILY_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHILD:
+ entry = {
+ 'key_to_child': child.get_value(),
+ 'relationship_to_father': '',
+ 'relationship_to_mother': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
+ entry['relationship_to_father'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
+ entry['relationship_to_mother'] = gchild.get_value()
+
+ record['children'].append(entry)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SUBMITTER:
+ record['submitters'].append(child.get_value())
+ continue
+
+ return record
GEDCOM element for a HEADER header record identified by the
+GEDCOM_TAG_HEADER tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `HEADER` header record identified by the
+`gedcom.tags.GEDCOM_TAG_HEADER` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+
+HEADER_TAGS = {
+ tags.GEDCOM_TAG_DESTINATION: 'destination',
+ tags.GEDCOM_TAG_SUBMITTER: 'key_to_submitter',
+ tags.GEDCOM_TAG_SUBMISSION: 'key_to_submission',
+ tags.GEDCOM_TAG_FILE: 'file',
+ tags.GEDCOM_TAG_COPYRIGHT: 'copyright',
+ tags.GEDCOM_TAG_LANGUAGE: 'language',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON: 'key_to_home_person'
+}
+
+
+class HeaderElement(Element):
+ """Element associated with a `HEADER`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_HEADER
+
+ def get_record(self):
+ """Parse and return the full record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'source': '',
+ 'product': {
+ 'version': '',
+ 'name': '',
+ 'corporation': '',
+ 'address': {}
+ },
+ 'data': {
+ 'source_data': '',
+ 'published': '',
+ 'copyright': ''
+ },
+ 'destination': '',
+ 'transmission_date': '',
+ 'transmission_time': '',
+ 'key_to_submitter': '',
+ 'key_to_submission': '',
+ 'file': '',
+ 'copyright': '',
+ 'gedcom': {
+ 'version': '',
+ 'format': '',
+ },
+ 'character_set': '',
+ 'character_set_version': '',
+ 'language': '',
+ 'place_hierarchy': '',
+ 'key_to_home_person': '',
+ 'notes': []
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['source'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_VERSION:
+ record['product']['version'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['product']['name'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_CORPORATE:
+ record['product']['corporation'] = gchild.get_value()
+
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['product']['address'] = address_structure(gchild)
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATA:
+ record['data']['source_data'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['data']['published'] = ggchild.get_value()
+ continue
+
+ if ggchild.get_tag() == tags.GEDCOM_TAG_COPYRIGHT:
+ record['data']['copyright'] = ggchild.get_multi_line_value()
+ continue
+ continue
+
+ if child.get_tag() in HEADER_TAGS:
+ record[HEADER_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['transmission_date'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TIME:
+ record['transmission_time'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_GEDCOM:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_VERSION:
+ record['gedcom']['version'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['gedcom']['format'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHARACTER:
+ record['character_set'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_VERSION:
+ record['character_set_version'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PLACE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['place_hierarchy'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
GEDCOM element for a INDIVIDUAL_RECORD individual record identified by the
+GEDCOM_TAG_INDIVIDUAL tag.
Expand source code
@@ -29,6 +31,7 @@
Module gedcom.element.individual
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -52,29 +55,139 @@
Module gedcom.element.individual
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""GEDCOM element consisting of tag `gedcom.tags.GEDCOM_TAG_INDIVIDUAL`"""
+"""
+GEDCOM element for a `INDIVIDUAL_RECORD` individual record identified by the
+`gedcom.tags.GEDCOM_TAG_INDIVIDUAL` tag.
+"""
import re as regex
+import gedcom.tags as tags
from gedcom.element.element import Element
+from gedcom.subparsers.personal_name_structure import personal_name_structure
+from gedcom.subparsers.individual_event_structure import individual_event_structure
+from gedcom.subparsers.individual_attribute_structure import individual_attribute_structure
+from gedcom.subparsers.lds_individual_ordinance import lds_individual_ordinance
+from gedcom.subparsers.child_to_family_link import child_to_family_link
+from gedcom.subparsers.spouse_to_family_link import spouse_to_family_link
+from gedcom.subparsers.association_structure import association_structure
+from gedcom.subparsers.user_reference_number import user_reference_number
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.multimedia_link import multimedia_link
from gedcom.helpers import deprecated
-import gedcom.tags
-
-class NotAnActualIndividualError(Exception):
- pass
+INDIVIDUAL_SINGLE_TAGS = {
+ tags.GEDCOM_TAG_RESTRICTION: 'restriction',
+ tags.GEDCOM_TAG_SEX: 'sex',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id',
+ tags.GEDCOM_TAG_REC_FILE_NUMBER: 'permanent_file_number',
+ tags.GEDCOM_TAG_AFN: 'ancestral_file_number'
+}
class IndividualElement(Element):
+ """Element associated with an `INDIVIDUAL_RECORD`"""
def get_tag(self):
- return gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ return tags.GEDCOM_TAG_INDIVIDUAL
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': self.get_pointer(),
+ 'restriction': '',
+ 'names': [],
+ 'sex': 'U',
+ 'events': individual_event_structure(self),
+ 'attributes': individual_attribute_structure(self),
+ 'child_to_family': [],
+ 'spouse_to_family': [],
+ 'submitters': [],
+ 'associates': [],
+ 'aliases': [],
+ 'ancestors_interest': [],
+ 'descendants_interest': [],
+ 'permanent_file_number': '',
+ 'ancestral_file_number': '',
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ lds_events = lds_individual_ordinance(self)
+ if len(lds_events) > 0:
+ for event in lds_events:
+ record['events'].append(event)
+
+ for child in self.get_child_elements():
+ if child.get_tag() in INDIVIDUAL_SINGLE_TAGS:
+ record[INDIVIDUAL_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['names'].append(personal_name_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['child_to_family'].append(child_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_SPOUSE:
+ record['spouse_to_family'].append(spouse_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SUBMITTER:
+ record['submitters'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ASSOCIATES:
+ record['associates'].append(association_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ALIAS:
+ record['aliases'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ANCES_INTEREST:
+ record['ancestors_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DESCENDANTS_INT:
+ record['descendants_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['changed'] = change_date(child)
+
+ return record
def is_deceased(self):
"""Checks if this individual is deceased
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
return True
return False
@@ -86,7 +199,7 @@
Module gedcom.element.individual
found_child = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
found_child = True
return found_child
@@ -96,7 +209,7 @@
Module gedcom.element.individual
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
+ if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
private = child.get_value()
if private == 'Y':
return True
@@ -110,13 +223,14 @@
Module gedcom.element.individual
given_name = ""
surname = ""
- # Return the first gedcom.tags.GEDCOM_TAG_NAME that is found.
- # Alternatively as soon as we have both the gedcom.tags.GEDCOM_TAG_GIVEN_NAME and _SURNAME return those.
+ # Return the first tags.GEDCOM_TAG_NAME that is found.
+ # Alternatively as soon as we have both the tags.GEDCOM_TAG_GIVEN_NAME
+ # and _SURNAME return those.
found_given_name = False
found_surname_name = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_NAME:
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
# Some GEDCOM files don't use child tags but instead
# place the name in the value of the NAME tag.
if child.get_value() != "":
@@ -129,14 +243,14 @@
Module gedcom.element.individual
return given_name, surname
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
- given_name = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
+ given_name = gchild.get_value()
found_given_name = True
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
- surname = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
+ surname = gchild.get_value()
found_surname_name = True
if found_given_name and found_surname_name:
@@ -146,7 +260,8 @@
Module gedcom.element.individual
return given_name, surname
def get_all_names(self):
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == gedcom.tags.GEDCOM_TAG_NAME]
+ """Return all names"""
+ return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
def surname_match(self, surname_to_match):
"""Matches a string with the surname of an individual
@@ -180,13 +295,14 @@
Module gedcom.element.individual
gender = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_SEX:
+ if child.get_tag() == tags.GEDCOM_TAG_SEX:
gender = child.get_value()
return gender
def get_birth_data(self):
- """Returns the birth data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
+ """Returns the birth data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
:rtype: tuple
"""
date = ""
@@ -194,17 +310,17 @@
Module gedcom.element.individual
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -215,10 +331,10 @@
Module gedcom.element.individual
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -237,14 +353,14 @@
Module gedcom.element.individual
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -255,10 +371,10 @@
Module gedcom.element.individual
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -285,17 +401,17 @@
Module gedcom.element.individual
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BURIAL:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -314,22 +430,22 @@
Module gedcom.element.individual
census = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
+ if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
date = ''
place = ''
sources = []
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
census.append((date, place, sources))
@@ -342,10 +458,10 @@
Module gedcom.element.individual
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CHANGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
return date
@@ -356,7 +472,7 @@
Module gedcom.element.individual
occupation = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
+ if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
occupation = child.get_value()
return occupation
@@ -494,42 +610,113 @@
Each line in a GEDCOM file is an element with the format
-
level [pointer] tag [value]
-
where level and tag are required, and pointer and value are
-optional.
-Elements are arranged hierarchically according to their
-level, and elements with a level of zero are at the top level.
-Elements with a level greater than zero are children of their
-parent.
-
A pointer has the format @pname@, where pname is any sequence of
-characters and numbers. The pointer identifies the object being
-pointed to, so that any pointer included as the value of any
-element points back to the original object.
-For example, an
-element may have a FAMS tag whose value is @F1@, meaning that this
-element points to the family record in which the associated person
-is a spouse. Likewise, an element with a tag of FAMC has a value
-that points to a family record in which the associated person is a
-child.
-
See a GEDCOM file for examples of tags and their values.
-
Tags available to an element are seen here: gedcom.tags
+
Element associated with an INDIVIDUAL_RECORD
Expand source code
class IndividualElement(Element):
+ """Element associated with an `INDIVIDUAL_RECORD`"""
def get_tag(self):
- return gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ return tags.GEDCOM_TAG_INDIVIDUAL
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': self.get_pointer(),
+ 'restriction': '',
+ 'names': [],
+ 'sex': 'U',
+ 'events': individual_event_structure(self),
+ 'attributes': individual_attribute_structure(self),
+ 'child_to_family': [],
+ 'spouse_to_family': [],
+ 'submitters': [],
+ 'associates': [],
+ 'aliases': [],
+ 'ancestors_interest': [],
+ 'descendants_interest': [],
+ 'permanent_file_number': '',
+ 'ancestral_file_number': '',
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ lds_events = lds_individual_ordinance(self)
+ if len(lds_events) > 0:
+ for event in lds_events:
+ record['events'].append(event)
+
+ for child in self.get_child_elements():
+ if child.get_tag() in INDIVIDUAL_SINGLE_TAGS:
+ record[INDIVIDUAL_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['names'].append(personal_name_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['child_to_family'].append(child_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_SPOUSE:
+ record['spouse_to_family'].append(spouse_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SUBMITTER:
+ record['submitters'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ASSOCIATES:
+ record['associates'].append(association_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ALIAS:
+ record['aliases'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ANCES_INTEREST:
+ record['ancestors_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DESCENDANTS_INT:
+ record['descendants_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['changed'] = change_date(child)
+
+ return record
def is_deceased(self):
"""Checks if this individual is deceased
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
return True
return False
@@ -541,7 +728,7 @@
Classes
found_child = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
found_child = True
return found_child
@@ -551,7 +738,7 @@
Classes
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
+ if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
private = child.get_value()
if private == 'Y':
return True
@@ -565,13 +752,14 @@
Classes
given_name = ""
surname = ""
- # Return the first gedcom.tags.GEDCOM_TAG_NAME that is found.
- # Alternatively as soon as we have both the gedcom.tags.GEDCOM_TAG_GIVEN_NAME and _SURNAME return those.
+ # Return the first tags.GEDCOM_TAG_NAME that is found.
+ # Alternatively as soon as we have both the tags.GEDCOM_TAG_GIVEN_NAME
+ # and _SURNAME return those.
found_given_name = False
found_surname_name = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_NAME:
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
# Some GEDCOM files don't use child tags but instead
# place the name in the value of the NAME tag.
if child.get_value() != "":
@@ -584,14 +772,14 @@
Classes
return given_name, surname
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
- given_name = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
+ given_name = gchild.get_value()
found_given_name = True
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
- surname = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
+ surname = gchild.get_value()
found_surname_name = True
if found_given_name and found_surname_name:
@@ -601,7 +789,8 @@
Classes
return given_name, surname
def get_all_names(self):
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == gedcom.tags.GEDCOM_TAG_NAME]
+ """Return all names"""
+ return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
def surname_match(self, surname_to_match):
"""Matches a string with the surname of an individual
@@ -635,13 +824,14 @@
Classes
gender = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_SEX:
+ if child.get_tag() == tags.GEDCOM_TAG_SEX:
gender = child.get_value()
return gender
def get_birth_data(self):
- """Returns the birth data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
+ """Returns the birth data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
:rtype: tuple
"""
date = ""
@@ -649,17 +839,17 @@
Classes
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -670,10 +860,10 @@
Classes
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -692,14 +882,14 @@
Classes
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -710,10 +900,10 @@
Classes
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -740,17 +930,17 @@
Classes
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BURIAL:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -769,22 +959,22 @@
Classes
census = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
+ if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
date = ''
place = ''
sources = []
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
census.append((date, place, sources))
@@ -797,10 +987,10 @@
Classes
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CHANGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
return date
@@ -811,7 +1001,7 @@
Classes
occupation = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
+ if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
occupation = child.get_value()
return occupation
@@ -944,10 +1134,10 @@
Methods
def birth_range_match(self, from_year, to_year)
-
Checks if the birth year of a person lies within the given range
+
Checks if the birth year of a person lies within the given range
:type from_year: int
:type to_year: int
-:rtype: bool
+:rtype: bool
Expand source code
@@ -970,9 +1160,9 @@
Methods
def birth_year_match(self, year)
-
Returns True if the given year matches the birth year of this person
+
Returns True if the given year matches the birth year of this person
:type year: int
-:rtype: bool
+:rtype: bool
Expand source code
@@ -989,7 +1179,7 @@
Methods
def criteria_match(self, criteria)
-
Checks if this individual matches all of the given criteria
+
Checks if this individual matches all of the given criteria
criteria is a colon-separated list, where each item in the
list has the form [name]=[value]. The following criteria are supported:
surname=[name]
@@ -1002,7 +1192,7 @@
Methods
Match a person whose birth year is in the range of years from
[from_year] to [to_year], including both [from_year] and [to_year].
:type criteria: str
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1090,10 +1280,10 @@
Methods
def death_range_match(self, from_year, to_year)
-
Checks if the death year of a person lies within the given range
+
Checks if the death year of a person lies within the given range
:type from_year: int
:type to_year: int
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1116,9 +1306,9 @@
Methods
def death_year_match(self, year)
-
Returns True if the given year matches the death year of this person
+
Returns True if the given year matches the death year of this person
:type year: int
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1135,27 +1325,30 @@
Methods
def get_all_names(self)
-
+
Return all names
Expand source code
def get_all_names(self):
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == gedcom.tags.GEDCOM_TAG_NAME]
+ """Return all names"""
+ return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
def get_birth_data(self)
-
Returns the birth data of a person formatted as a tuple: (str date, str place, list sources)
-:rtype: tuple
+
Returns the birth data of a person formatted as a tuple:
+(str date, str place, list sources)
+:rtype: tuple
Expand source code
def get_birth_data(self):
- """Returns the birth data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
+ """Returns the birth data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
:rtype: tuple
"""
date = ""
@@ -1163,17 +1356,17 @@
Methods
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -1182,8 +1375,8 @@
Methods
def get_birth_year(self)
-
Returns the birth year of a person in integer format
-:rtype: int
+
Returns the birth year of a person in integer format
+:rtype: int
Expand source code
@@ -1195,10 +1388,10 @@
Methods
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BIRTH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -1213,9 +1406,9 @@
Methods
def get_burial(self)
-
Returns the burial data of a person formatted as a tuple: (str date, str´ place,listsources)
-::deprecated:: As of version 1.0.0 useget_burial_data()` method instead
-:rtype: tuple
+
Returns the burial data of a person formatted as a tuple: (str date, str´ place,list` sources)
+::deprecated:: As of version 1.0.0 use get_burial_data() method instead
+:rtype: tuple
Expand source code
@@ -1233,8 +1426,8 @@
Methods
def get_burial_data(self)
-
Returns the burial data of a person formatted as a tuple: (str date, str´ place,list` sources)
-:rtype: tuple
+
Returns the burial data of a person formatted as a tuple: (str date, str´ place,list` sources)
+:rtype: tuple
Expand source code
@@ -1248,17 +1441,17 @@
Methods
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_BURIAL:
- for childOfChild in child.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -1267,9 +1460,9 @@
Methods
def get_census(self)
-
Returns a list of censuses of an individual formatted as tuples: (str date, str´ place,listsources)
-::deprecated:: As of version 1.0.0 useget_census_data()` method instead
-:rtype: list of tuple
+
Returns a list of censuses of an individual formatted as tuples: (str date, str´ place,list` sources)
+::deprecated:: As of version 1.0.0 use get_census_data() method instead
+:rtype: list of tuple
Expand source code
@@ -1287,8 +1480,8 @@
Methods
def get_census_data(self)
-
Returns a list of censuses of an individual formatted as tuples: (str date, str´ place,list` sources)
-:rtype: list of tuple
+
Returns a list of censuses of an individual formatted as tuples: (str date, str´ place,list` sources)
+:rtype: list of tuple
Expand source code
@@ -1300,22 +1493,22 @@
Methods
census = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
+ if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
date = ''
place = ''
sources = []
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
census.append((date, place, sources))
@@ -1326,8 +1519,8 @@
Methods
def get_death_data(self)
-
Returns the death data of a person formatted as a tuple: (str date, str place, list sources)
-:rtype: tuple
+
Returns the death data of a person formatted as a tuple: (str date, str place, list sources)
+:rtype: tuple
Expand source code
@@ -1341,14 +1534,14 @@
Methods
sources = []
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
- place = childOfChild.get_value()
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SOURCE:
- sources.append(childOfChild.get_value())
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ place = gchild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ sources.append(gchild.get_value())
return date, place, sources
@@ -1357,8 +1550,8 @@
Methods
def get_death_year(self)
-
Returns the death year of a person in integer format
-:rtype: int
+
Returns the death year of a person in integer format
+:rtype: int
Expand source code
@@ -1370,10 +1563,10 @@
Methods
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date_split = childOfChild.get_value().split()
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date_split = gchild.get_value().split()
date = date_split[len(date_split) - 1]
if date == "":
@@ -1388,8 +1581,8 @@
Methods
def get_gender(self)
-
Returns the gender of a person in string format
-:rtype: str
+
Returns the gender of a person in string format
+:rtype: str
Expand source code
@@ -1401,7 +1594,7 @@
Methods
gender = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_SEX:
+ if child.get_tag() == tags.GEDCOM_TAG_SEX:
gender = child.get_value()
return gender
@@ -1411,8 +1604,8 @@
Methods
def get_last_change_date(self)
-
Returns the date of when the person data was last changed formatted as a string
-:rtype: str
+
Returns the date of when the person data was last changed formatted as a string
+:rtype: str
Expand source code
@@ -1424,10 +1617,10 @@
Methods
date = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_CHANGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value()
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value()
return date
@@ -1436,8 +1629,8 @@
Methods
def get_name(self)
-
Returns an individual's names as a tuple: (str given_name, str surname)
-:rtype: tuple
+
Returns an individual's names as a tuple: (str given_name, str surname)
+:rtype: tuple
Expand source code
@@ -1449,13 +1642,14 @@
Methods
given_name = ""
surname = ""
- # Return the first gedcom.tags.GEDCOM_TAG_NAME that is found.
- # Alternatively as soon as we have both the gedcom.tags.GEDCOM_TAG_GIVEN_NAME and _SURNAME return those.
+ # Return the first tags.GEDCOM_TAG_NAME that is found.
+ # Alternatively as soon as we have both the tags.GEDCOM_TAG_GIVEN_NAME
+ # and _SURNAME return those.
found_given_name = False
found_surname_name = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_NAME:
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
# Some GEDCOM files don't use child tags but instead
# place the name in the value of the NAME tag.
if child.get_value() != "":
@@ -1468,14 +1662,14 @@
Methods
return given_name, surname
- for childOfChild in child.get_child_elements():
+ for gchild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
- given_name = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
+ given_name = gchild.get_value()
found_given_name = True
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
- surname = childOfChild.get_value()
+ if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
+ surname = gchild.get_value()
found_surname_name = True
if found_given_name and found_surname_name:
@@ -1489,8 +1683,8 @@
Methods
def get_occupation(self)
-
Returns the occupation of a person
-:rtype: str
+
Returns the occupation of a person
+:rtype: str
Expand source code
@@ -1502,20 +1696,121 @@
Methods
occupation = ""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
+ if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
occupation = child.get_value()
return occupation
+
+def get_record(self)
+
+
+
Parse and return the record in dictionary format
+:rtype: dict
+
+
+Expand source code
+
+
def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': self.get_pointer(),
+ 'restriction': '',
+ 'names': [],
+ 'sex': 'U',
+ 'events': individual_event_structure(self),
+ 'attributes': individual_attribute_structure(self),
+ 'child_to_family': [],
+ 'spouse_to_family': [],
+ 'submitters': [],
+ 'associates': [],
+ 'aliases': [],
+ 'ancestors_interest': [],
+ 'descendants_interest': [],
+ 'permanent_file_number': '',
+ 'ancestral_file_number': '',
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ lds_events = lds_individual_ordinance(self)
+ if len(lds_events) > 0:
+ for event in lds_events:
+ record['events'].append(event)
+
+ for child in self.get_child_elements():
+ if child.get_tag() in INDIVIDUAL_SINGLE_TAGS:
+ record[INDIVIDUAL_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['names'].append(personal_name_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['child_to_family'].append(child_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_SPOUSE:
+ record['spouse_to_family'].append(spouse_to_family_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SUBMITTER:
+ record['submitters'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ASSOCIATES:
+ record['associates'].append(association_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ALIAS:
+ record['aliases'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ANCES_INTEREST:
+ record['ancestors_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DESCENDANTS_INT:
+ record['descendants_interest'].append(child.get_value())
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['changed'] = change_date(child)
+
+ return record
+
+
def given_match(self, name)
-
Matches a string with the given name of an individual
+
Matches a string with the given name of an individual
::deprecated:: As of version 1.0.0 use given_name_match() method instead
:type name: str
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1534,9 +1829,9 @@
Methods
def given_name_match(self, given_name_to_match)
-
Matches a string with the given name of an individual
+
Matches a string with the given name of an individual
:type given_name_to_match: str
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1554,8 +1849,8 @@
Methods
def is_child(self)
-
Checks if this element is a child of a family
-:rtype: bool
+
Checks if this element is a child of a family
+:rtype: bool
Expand source code
@@ -1567,7 +1862,7 @@
Methods
found_child = False
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
+ if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
found_child = True
return found_child
@@ -1577,8 +1872,8 @@
Methods
def is_deceased(self)
-
Checks if this individual is deceased
-:rtype: bool
+
Checks if this individual is deceased
+:rtype: bool
Expand source code
@@ -1588,7 +1883,7 @@
Methods
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_DEATH:
+ if child.get_tag() == tags.GEDCOM_TAG_DEATH:
return True
return False
@@ -1598,8 +1893,8 @@
Methods
def is_private(self)
-
Checks if this individual is marked private
-:rtype: bool
+
Checks if this individual is marked private
+:rtype: bool
Expand source code
@@ -1609,7 +1904,7 @@
Methods
:rtype: bool
"""
for child in self.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
+ if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
private = child.get_value()
if private == 'Y':
return True
@@ -1621,9 +1916,9 @@
Methods
def surname_match(self, surname_to_match)
-
Matches a string with the surname of an individual
+
Matches a string with the surname of an individual
:type surname_to_match: str
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1660,25 +1955,6 @@
Inherited members
-
-class NotAnActualIndividualError
-(...)
-
-
-
Common base class for all non-exit exceptions.
-
-
-Expand source code
-
-
class NotAnActualIndividualError(Exception):
- pass
GEDCOM element for a NOTE_RECORD note record identified by the
+GEDCOM_TAG_NOTE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `NOTE_RECORD` note record identified by the
+`gedcom.tags.GEDCOM_TAG_NOTE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.user_reference_number import user_reference_number
+
+
+class NoteElement(Element):
+ """Element associated with a `NOTE_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_NOTE
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_note': self.get_pointer(),
+ 'note': self.get_multi_line_value(),
+ 'references': [],
+ 'record_id': '',
+ 'citations': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
GEDCOM element for a MULTIMEDIA_RECORD media record identified by the
+GEDCOM_TAG_OBJECT tag.
Expand source code
@@ -29,6 +31,7 @@
Module gedcom.element.object
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -52,23 +55,87 @@
Module gedcom.element.object
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""GEDCOM element consisting of tag `gedcom.tags.GEDCOM_TAG_OBJECT`"""
+"""
+GEDCOM element for a `MULTIMEDIA_RECORD` media record identified by the
+`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
+"""
+import gedcom.tags as tags
from gedcom.element.element import Element
-import gedcom.tags
-
-
-class NotAnActualObjectError(Exception):
- pass
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.user_reference_number import user_reference_number
class ObjectElement(Element):
+ """Element associated with a `MULTIMEDIA_RECORD`"""
- def is_object(self):
- """Checks if this element is an actual object
- :rtype: bool
+ def get_tag(self):
+ return tags.GEDCOM_TAG_OBJECT
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
"""
- return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT
+ record = {
+ 'key_to_object': self.get_pointer(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'references': [],
+ 'record_id': '',
+ 'citations': [],
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
+
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
+
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_TITLE:
+ record['title'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
@@ -80,62 +147,84 @@
Module gedcom.element.object
Classes
-
-class NotAnActualObjectError
-(...)
-
-
-
Common base class for all non-exit exceptions.
-
-
-Expand source code
-
-
class NotAnActualObjectError(Exception):
- pass
-
-
Ancestors
-
-
builtins.Exception
-
builtins.BaseException
-
-
class ObjectElement(level, pointer, tag, value, crlf='\n', multi_line=True)
-
GEDCOM element
-
Each line in a GEDCOM file is an element with the format
-
level [pointer] tag [value]
-
where level and tag are required, and pointer and value are
-optional.
-Elements are arranged hierarchically according to their
-level, and elements with a level of zero are at the top level.
-Elements with a level greater than zero are children of their
-parent.
-
A pointer has the format @pname@, where pname is any sequence of
-characters and numbers. The pointer identifies the object being
-pointed to, so that any pointer included as the value of any
-element points back to the original object.
-For example, an
-element may have a FAMS tag whose value is @F1@, meaning that this
-element points to the family record in which the associated person
-is a spouse. Likewise, an element with a tag of FAMC has a value
-that points to a family record in which the associated person is a
-child.
-
See a GEDCOM file for examples of tags and their values.
-
Tags available to an element are seen here: gedcom.tags
+
Element associated with a MULTIMEDIA_RECORD
Expand source code
class ObjectElement(Element):
+ """Element associated with a `MULTIMEDIA_RECORD`"""
- def is_object(self):
- """Checks if this element is an actual object
- :rtype: bool
+ def get_tag(self):
+ return tags.GEDCOM_TAG_OBJECT
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
"""
- return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT
+ record = {
+ 'key_to_object': self.get_pointer(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'references': [],
+ 'record_id': '',
+ 'citations': [],
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
+
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
+
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_TITLE:
+ record['title'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
Ancestors
@@ -143,21 +232,78 @@
Ancestors
Methods
-
-def is_object(self)
+
+def get_record(self)
-
Checks if this element is an actual object
-:rtype: bool
+
Parse and return the record in dictionary format
+:rtype: dict
Expand source code
-
def is_object(self):
- """Checks if this element is an actual object
- :rtype: bool
+
def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
"""
- return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT
+ record = {
+ 'key_to_object': self.get_pointer(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'references': [],
+ 'record_id': '',
+ 'citations': [],
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
+
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
+
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_TITLE:
+ record['title'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
GEDCOM element for a REPOSITORY_RECORD repository record identified by the
+GEDCOM_TAG_REPOSITORY tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `REPOSITORY_RECORD` repository record identified by the
+`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.user_reference_number import user_reference_number
+
+
+class RepositoryElement(Element):
+ """Element associated with a `REPOSITORY_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_REPOSITORY
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_repository': self.get_pointer(),
+ 'name': '',
+ 'address': {},
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': []
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['name'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(self)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
GEDCOM element for a SOURCE_RECORD source record identified by the
+GEDCOM_TAG_SOURCE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `SOURCE_RECORD` source record identified by the
+`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.multimedia_link import multimedia_link
+from gedcom.subparsers.user_reference_number import user_reference_number
+from gedcom.subparsers.source_repository_citation import source_repository_citation
+
+SOURCE_PLURAL_TAGS = {
+ tags.GEDCOM_TAG_AUTHOR: 'author',
+ tags.GEDCOM_TAG_TITLE: 'title',
+ tags.GEDCOM_TAG_PUBLICATION: 'publication',
+ tags.GEDCOM_TAG_TEXT: 'text'
+}
+
+SOURCE_SINGLE_TAGS = {
+ tags.GEDCOM_TAG_ABBREVIATION: 'abbreviation',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_APID: 'apid'
+}
+
+
+class SourceElement(Element):
+ """Element associated with a SOURCE_RECORD"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_SOURCE
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_source': self.get_pointer(),
+ 'data': {
+ 'events': '',
+ 'date': '',
+ 'place': '',
+ 'agency': '',
+ 'notes': []
+ },
+ 'author': '',
+ 'title': '',
+ 'abbreviation': '',
+ 'publication': '',
+ 'text': '',
+ 'repository': {},
+ 'references': [],
+ 'record_id': '',
+ 'change_date': {},
+ 'notes': [],
+ 'media': [],
+ 'apid': ''
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() in SOURCE_PLURAL_TAGS:
+ record[SOURCE_PLURAL_TAGS[child.get_tag()]] = child.get_multi_line_value()
+ continue
+
+ if child.get_tag() in SOURCE_SINGLE_TAGS:
+ record[SOURCE_SINGLE_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REPOSITORY:
+ record['repository'] = source_repository_citation(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATA:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_EVENT:
+ record['data']['events'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['data']['date'] = ggchild.get_value()
+ continue
+
+ if ggchild.get_tag() == tags.GEDCOM_TAG_PLACE:
+ record['data']['place'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGENCY:
+ record['data']['agency'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['data']['notes'].append(note_structure(gchild))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REFERENCE:
+ record['references'].append(user_reference_number(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+ continue
+
+ return record
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/element/submission.html b/docs/gedcom/element/submission.html
new file mode 100644
index 0000000..95097e3
--- /dev/null
+++ b/docs/gedcom/element/submission.html
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+gedcom.element.submission API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.element.submission
+
+
+
GEDCOM element for a SUBMISSION_RECORD submission record identified by the
+GEDCOM_TAG_SUBMISSION tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `SUBMISSION_RECORD` submission record identified by the
+`gedcom.tags.GEDCOM_TAG_SUBMISSION` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.change_date import change_date
+
+SUBMISSION_TAGS = {
+ tags.GEDCOM_TAG_SUBMITTER: 'key_to_submitter',
+ tags.GEDCOM_TAG_FAMILY_FILE: 'family_file',
+ tags.GEDCOM_TAG_TEMPLE: 'temple',
+ tags.GEDCOM_TAG_ANCESTORS: 'generations_of_ancestors',
+ tags.GEDCOM_TAG_DESCENDANTS: 'generations_of_decendants',
+ tags.GEDCOM_TAG_ORDINANCE: 'ordinance_process_flag',
+ tags.GEDCOM_TAG_REC_ID_NUMBER: 'record_id'
+}
+
+
+class SubmissionElement(Element):
+ """Element associated with a `SUBMISSION_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_SUBMISSION
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_submission': self.get_pointer(),
+ 'key_to_submitter': '',
+ 'family_file': '',
+ 'temple': '',
+ 'generations_of_ancestors': '',
+ 'generations_of_descendants': '',
+ 'ordinance_process_flag': '',
+ 'record_id': '',
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() in SUBMISSION_TAGS:
+ record[SUBMISSION_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/element/submitter.html b/docs/gedcom/element/submitter.html
new file mode 100644
index 0000000..a38edbe
--- /dev/null
+++ b/docs/gedcom/element/submitter.html
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+gedcom.element.submitter API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.element.submitter
+
+
+
GEDCOM element for a SUBMITTER_RECORD submitter record identified by the
+GEDCOM_TAG_SUBMITTER tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+GEDCOM element for a `SUBMITTER_RECORD` submitter record identified by the
+`gedcom.tags.GEDCOM_TAG_SUBMITTER` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.element.element import Element
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.change_date import change_date
+from gedcom.subparsers.multimedia_link import multimedia_link
+
+
+class SubmitterElement(Element):
+ """Element associated with a `SUBMITTER_RECORD`"""
+
+ def get_tag(self):
+ return tags.GEDCOM_TAG_SUBMITTER
+
+ def get_record(self):
+ """Parse and return the record in dictionary format
+ :rtype: dict
+ """
+ record = {
+ 'key_to_submitter': self.get_pointer(),
+ 'name': '',
+ 'address': {},
+ 'media': [],
+ 'language': '',
+ 'registered_file_number': '',
+ 'record_id': '',
+ 'notes': [],
+ 'change_date': {}
+ }
+ for child in self.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NAME:
+ record['name'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(self)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_LANGUAGE:
+ record['language'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_FILE_NUMBER:
+ record['registered_file_number'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_REC_ID_NUMBER:
+ record['record_id'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CHANGE:
+ record['change_date'] = change_date(child)
+
+ return record
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/errors.html b/docs/gedcom/errors.html
new file mode 100644
index 0000000..b6fe2eb
--- /dev/null
+++ b/docs/gedcom/errors.html
@@ -0,0 +1,495 @@
+
+
+
+
+
+
+gedcom.errors API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.errors
+
+
+
Module containing the exception handling classes.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Module containing the exception handling classes.
+"""
+
+
+class GedcomFormatViolationError(Exception):
+ """Raised when the document format does not appear to conform
+ to the GEDCOM standard and strict parsing required.
+ """
+
+
+class GedcomStructureViolationError(Exception):
+ """Raised when the structure of a record does not conform to
+ the GEDCOM standard.
+ """
+
+
+class GedcomCharacterSetUnsupportedError(Exception):
+ """Raised when a GEDCOM appears to contain a character set
+ the standard or the parser does not support.
+ """
+
+
+class GedcomVersionUnsupportedError(Exception):
+ """Raised when a particular GEDCOM version is not supported
+ by the parser and the standard for the version requires the
+ parser to reject it.
+ """
+
+
+class GedcomFormatUnsupportedError(Exception):
+ """Raised if the GEDCOM format is not recognized by the
+ parser. Note some misspellings as documented on page 148
+ in the 5.5.5 standard are treated as LINEAGE-LINKED and
+ allowed.
+ """
+
+
+class NotAnActualIndividualError(Exception):
+ """Raised if record does not appear to be an `INDIVIDUAL_RECORD`"""
+
+
+class NotAnActualFamilyError(Exception):
+ """Raised if record does not appear to be a `FAM_RECORD`"""
+
+
+class NotAnActualSourceError(Exception):
+ """Raised if record does not appear to be a `SOURCE_RECORD`"""
+
+
+class NotAnActualRepositoryError(Exception):
+ """Raised if record does not appear to be a `REPOSITORY_RECORD`"""
+
+
+class NotAnActualNoteError(Exception):
+ """Raised if record does not appear to be a `NOTE_RECORD`"""
+
+
+class NotAnActualObjectError(Exception):
+ """Raised if record does not appear to be a `MULTIMEDIA_RECORD`"""
+
+
+class NotAnActualHeaderError(Exception):
+ """Raised if record does not appear to be a `HEADER`"""
+
+
+class NotAnActualSubmitterError(Exception):
+ """Raised if record does not appear to be a `SUBMITTER_RECORD`"""
+
+
+class NotAnActualSubmissionError(Exception):
+ """Raised if record does not appear to be a `SUBMISSION_RECORD`"""
Raised when a GEDCOM appears to contain a character set
+the standard or the parser does not support.
+
+
+Expand source code
+
+
class GedcomCharacterSetUnsupportedError(Exception):
+ """Raised when a GEDCOM appears to contain a character set
+ the standard or the parser does not support.
+ """
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class GedcomFormatUnsupportedError
+(...)
+
+
+
Raised if the GEDCOM format is not recognized by the
+parser. Note some misspellings as documented on page 148
+in the 5.5.5 standard are treated as LINEAGE-LINKED and
+allowed.
+
+
+Expand source code
+
+
class GedcomFormatUnsupportedError(Exception):
+ """Raised if the GEDCOM format is not recognized by the
+ parser. Note some misspellings as documented on page 148
+ in the 5.5.5 standard are treated as LINEAGE-LINKED and
+ allowed.
+ """
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class GedcomFormatViolationError
+(...)
+
+
+
Raised when the document format does not appear to conform
+to the GEDCOM standard and strict parsing required.
+
+
+Expand source code
+
+
class GedcomFormatViolationError(Exception):
+ """Raised when the document format does not appear to conform
+ to the GEDCOM standard and strict parsing required.
+ """
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class GedcomStructureViolationError
+(...)
+
+
+
Raised when the structure of a record does not conform to
+the GEDCOM standard.
+
+
+Expand source code
+
+
class GedcomStructureViolationError(Exception):
+ """Raised when the structure of a record does not conform to
+ the GEDCOM standard.
+ """
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class GedcomVersionUnsupportedError
+(...)
+
+
+
Raised when a particular GEDCOM version is not supported
+by the parser and the standard for the version requires the
+parser to reject it.
+
+
+Expand source code
+
+
class GedcomVersionUnsupportedError(Exception):
+ """Raised when a particular GEDCOM version is not supported
+ by the parser and the standard for the version requires the
+ parser to reject it.
+ """
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualFamilyError
+(...)
+
+
+
Raised if record does not appear to be a FAM_RECORD
+
+
+Expand source code
+
+
class NotAnActualFamilyError(Exception):
+ """Raised if record does not appear to be a `FAM_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualHeaderError
+(...)
+
+
+
Raised if record does not appear to be a HEADER
+
+
+Expand source code
+
+
class NotAnActualHeaderError(Exception):
+ """Raised if record does not appear to be a `HEADER`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualIndividualError
+(...)
+
+
+
Raised if record does not appear to be an INDIVIDUAL_RECORD
+
+
+Expand source code
+
+
class NotAnActualIndividualError(Exception):
+ """Raised if record does not appear to be an `INDIVIDUAL_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualNoteError
+(...)
+
+
+
Raised if record does not appear to be a NOTE_RECORD
+
+
+Expand source code
+
+
class NotAnActualNoteError(Exception):
+ """Raised if record does not appear to be a `NOTE_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualObjectError
+(...)
+
+
+
Raised if record does not appear to be a MULTIMEDIA_RECORD
+
+
+Expand source code
+
+
class NotAnActualObjectError(Exception):
+ """Raised if record does not appear to be a `MULTIMEDIA_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualRepositoryError
+(...)
+
+
+
Raised if record does not appear to be a REPOSITORY_RECORD
+
+
+Expand source code
+
+
class NotAnActualRepositoryError(Exception):
+ """Raised if record does not appear to be a `REPOSITORY_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualSourceError
+(...)
+
+
+
Raised if record does not appear to be a SOURCE_RECORD
+
+
+Expand source code
+
+
class NotAnActualSourceError(Exception):
+ """Raised if record does not appear to be a `SOURCE_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualSubmissionError
+(...)
+
+
+
Raised if record does not appear to be a SUBMISSION_RECORD
+
+
+Expand source code
+
+
class NotAnActualSubmissionError(Exception):
+ """Raised if record does not appear to be a `SUBMISSION_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+class NotAnActualSubmitterError
+(...)
+
+
+
Raised if record does not appear to be a SUBMITTER_RECORD
+
+
+Expand source code
+
+
class NotAnActualSubmitterError(Exception):
+ """Raised if record does not appear to be a `SUBMITTER_RECORD`"""
+
+
Ancestors
+
+
builtins.Exception
+
builtins.BaseException
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/helpers.html b/docs/gedcom/helpers.html
index 783b4cd..8543391 100644
--- a/docs/gedcom/helpers.html
+++ b/docs/gedcom/helpers.html
@@ -3,14 +3,14 @@
-
+
gedcom.helpers API documentation
-
-
+
+
@@ -90,9 +90,9 @@
Functions
def deprecated(func)
-
This is a decorator which can be used to mark functions
+
This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
-when the function is used.
Module containing the actual Parser used to generate elements - out of each line -
-which can in return be manipulated.
+
Module containing the actual Parser used to generate elements
+out of each line - which can in return be manipulated.
Expand source code
@@ -31,6 +31,7 @@
Module gedcom.parser
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -55,35 +56,61 @@
Module gedcom.parser
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Module containing the actual `gedcom.parser.Parser` used to generate elements - out of each line -
-which can in return be manipulated.
+Module containing the actual `gedcom.parser.Parser` used to generate elements
+out of each line - which can in return be manipulated.
"""
import re as regex
from sys import version_info
+
+import gedcom.tags as tags
+import gedcom.standards as standards
+
+from gedcom.detect import get_encoding, get_version
from gedcom.element.element import Element
-from gedcom.element.family import FamilyElement, NotAnActualFamilyError
-from gedcom.element.file import FileElement
-from gedcom.element.individual import IndividualElement, NotAnActualIndividualError
+from gedcom.element.header import HeaderElement
+from gedcom.element.family import FamilyElement
+from gedcom.element.individual import IndividualElement
+from gedcom.element.note import NoteElement
from gedcom.element.object import ObjectElement
+from gedcom.element.source import SourceElement
+from gedcom.element.submission import SubmissionElement
+from gedcom.element.submitter import SubmitterElement
+from gedcom.element.repository import RepositoryElement
from gedcom.element.root import RootElement
-import gedcom.tags
+
+from gedcom.errors import GedcomVersionUnsupportedError
+from gedcom.errors import GedcomFormatUnsupportedError
+from gedcom.errors import GedcomFormatViolationError
+from gedcom.errors import NotAnActualIndividualError
+from gedcom.errors import NotAnActualFamilyError
+
+ERROR_TEMPLATE = "Line <{0}:{1}> of document violates GEDCOM format {2}\nSee: {3}"
+
+RECORD_ELEMENTS = {
+ tags.GEDCOM_TAG_HEADER: HeaderElement,
+ tags.GEDCOM_TAG_INDIVIDUAL: IndividualElement,
+ tags.GEDCOM_TAG_FAMILY: FamilyElement,
+ tags.GEDCOM_TAG_NOTE: NoteElement,
+ tags.GEDCOM_TAG_OBJECT: ObjectElement,
+ tags.GEDCOM_TAG_SOURCE: SourceElement,
+ tags.GEDCOM_TAG_SUBMISSION: SubmissionElement,
+ tags.GEDCOM_TAG_SUBMITTER: SubmitterElement,
+ tags.GEDCOM_TAG_REPOSITORY: RepositoryElement
+}
FAMILY_MEMBERS_TYPE_ALL = "ALL"
-FAMILY_MEMBERS_TYPE_CHILDREN = gedcom.tags.GEDCOM_TAG_CHILD
-FAMILY_MEMBERS_TYPE_HUSBAND = gedcom.tags.GEDCOM_TAG_HUSBAND
+FAMILY_MEMBERS_TYPE_CHILDREN = tags.GEDCOM_TAG_CHILD
+FAMILY_MEMBERS_TYPE_HUSBAND = tags.GEDCOM_TAG_HUSBAND
FAMILY_MEMBERS_TYPE_PARENTS = "PARENTS"
-FAMILY_MEMBERS_TYPE_WIFE = gedcom.tags.GEDCOM_TAG_WIFE
-
+FAMILY_MEMBERS_TYPE_WIFE = tags.GEDCOM_TAG_WIFE
-class GedcomFormatViolationError(Exception):
- pass
-
-class Parser(object):
+class Parser():
"""Parses and manipulates GEDCOM 5.5 format data
- For documentation of the GEDCOM 5.5 format, see: http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
+ For documentation of the GEDCOM 5.5 format, see:
+ http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
This parser reads and parses a GEDCOM file.
@@ -99,8 +126,9 @@
Module gedcom.parser
self.__root_element = RootElement()
def invalidate_cache(self):
- """Empties the element list and dictionary to cause `gedcom.parser.Parser.get_element_list()`
- and `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
+ """Empties the element list and dictionary to cause
+ `gedcom.parser.Parser.get_element_list()` and
+ `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
The update gets deferred until each of the methods actually gets called.
"""
@@ -113,10 +141,11 @@
Module gedcom.parser
By default elements are in the same order as they appeared in the file.
This list gets generated on-the-fly, but gets cached. If the database
- was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once to let this
- method return updated data.
+ was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once
+ to let this method return updated data.
- Consider using `gedcom.parser.Parser.get_root_element()` or `gedcom.parser.Parser.get_root_child_elements()` to access
+ Consider using `gedcom.parser.Parser.get_root_element()` or
+ `gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
:rtype: list of Element
@@ -127,7 +156,8 @@
Module gedcom.parser
return self.__element_list
def get_element_dictionary(self):
- """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file
+ """Returns a dictionary containing all elements, identified by a pointer,
+ from within the GEDCOM file
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -140,7 +170,8 @@
Module gedcom.parser
"""
if not self.__element_dictionary:
self.__element_dictionary = {
- element.get_pointer(): element for element in self.get_root_child_elements() if element.get_pointer()
+ element.get_pointer():
+ element for element in self.get_root_child_elements() if element.get_pointer()
}
return self.__element_dictionary
@@ -168,7 +199,21 @@
Module gedcom.parser
:type file_path: str
:type strict: bool
"""
- with open(file_path, 'rb') as gedcom_stream:
+ codec = get_encoding(file_path)
+ real_version, reported_version, reported_format = get_version(file_path, codec)
+
+ if reported_version == '5.5.5':
+ errmsg = "This parser does not properly support the GEDCOM " + reported_version + \
+ " standard at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomVersionUnsupportedError(errmsg)
+
+ if reported_format not in ['LINEAGE-LINKED', 'LINEAGE_LINKED',
+ 'LINAGE-LINKED', 'Lineage - Linked']:
+ errmsg = "This parser does not recognize the GEDCOM format " + reported_format + \
+ " at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomFormatUnsupportedError(errmsg)
+
+ with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
def parse(self, gedcom_stream, strict=True):
@@ -183,7 +228,7 @@
end_of_line_regex = '([\r\n]{1,2})'
# Complete regex
- gedcom_line_regex = level_regex + pointer_regex + tag_regex + value_regex + end_of_line_regex
+ gedcom_line_regex = level_regex + pointer_regex + tag_regex + \
+ value_regex + end_of_line_regex
regex_match = regex.match(gedcom_line_regex, line)
if regex_match is None:
if strict:
- error_message = ("Line <%d:%s> of document violates GEDCOM format 5.5" % (line_number, line)
- + "\nSee: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdf")
- raise GedcomFormatViolationError(error_message)
+ errmsg = ERROR_TEMPLATE.format(line_number, line, '5.5.1', standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
+
+ # Quirk check - see if this is a line without a CRLF (which could be the last line)
+ last_line_regex = level_regex + pointer_regex + tag_regex + value_regex
+ regex_match = regex.match(last_line_regex, line)
+ if regex_match is not None:
+ line_parts = regex_match.groups()
+
+ level = int(line_parts[0])
+ pointer = line_parts[1].rstrip(' ')
+ tag = line_parts[2]
+ value = line_parts[3][1:]
+ crlf = '\n'
else:
- # Quirk check - see if this is a line without a CRLF (which could be the last line)
- last_line_regex = level_regex + pointer_regex + tag_regex + value_regex
- regex_match = regex.match(last_line_regex, line)
- if regex_match is not None:
- line_parts = regex_match.groups()
-
- level = int(line_parts[0])
- pointer = line_parts[1].rstrip(' ')
- tag = line_parts[2]
- value = line_parts[3][1:]
- crlf = '\n'
- else:
- # Quirk check - Sometimes a gedcom has a text field with a CR.
- # This creates a line without the standard level and pointer.
- # If this is detected then turn it into a CONC or CONT.
- line_regex = '([^\n\r]*|)'
- cont_line_regex = line_regex + end_of_line_regex
- regex_match = regex.match(cont_line_regex, line)
- line_parts = regex_match.groups()
- level = last_element.get_level()
- tag = last_element.get_tag()
- pointer = None
- value = line_parts[0][1:]
- crlf = line_parts[1]
- if tag != gedcom.tags.GEDCOM_TAG_CONTINUED and tag != gedcom.tags.GEDCOM_TAG_CONCATENATION:
- # Increment level and change this line to a CONC
- level += 1
- tag = gedcom.tags.GEDCOM_TAG_CONCATENATION
+ # Quirk check - Sometimes a gedcom has a text field with a CR.
+ # This creates a line without the standard level and pointer.
+ # If this is detected then turn it into a CONC or CONT.
+ line_regex = '([^\n\r]*|)'
+ cont_line_regex = line_regex + end_of_line_regex
+ regex_match = regex.match(cont_line_regex, line)
+ line_parts = regex_match.groups()
+ level = last_element.get_level()
+ tag = last_element.get_tag()
+ pointer = None
+ value = line_parts[0][1:]
+ crlf = line_parts[1]
+ if tag not in [tags.GEDCOM_TAG_CONTINUED, tags.GEDCOM_TAG_CONCATENATION]:
+ # Increment level and change this line to a CONC
+ level += 1
+ tag = tags.GEDCOM_TAG_CONCATENATION
else:
line_parts = regex_match.groups()
@@ -267,20 +312,14 @@
Module gedcom.parser
# Check level: should never be more than one higher than previous line.
if level > last_element.get_level() + 1:
- error_message = ("Line %d of document violates GEDCOM format 5.5" % line_number
- + "\nLines must be no more than one level higher than previous line."
- + "\nSee: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdf")
- raise GedcomFormatViolationError(error_message)
+ errmsg = "Line {0} of document violates GEDCOM format 5.5.1\n".format(line_number) + \
+ "Lines must be no more than one level higher than previous line.\n" + \
+ "See: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
# Create element. Store in list and dict, create children and parents.
- if tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
- element = IndividualElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_FAMILY:
- element = FamilyElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_FILE:
- element = FileElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
- element = ObjectElement(level, pointer, tag, value, crlf, multi_line=False)
+ if tag in RECORD_ELEMENTS:
+ element = RECORD_ELEMENTS[tag](level, pointer, tag, value, crlf, multi_line=False)
else:
element = Element(level, pointer, tag, value, crlf, multi_line=False)
@@ -314,19 +353,19 @@
Module gedcom.parser
marriages = []
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
# Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
for family in families:
for family_data in family.get_child_elements():
- if family_data.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
+ if family_data.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
date = ''
place = ''
for marriage_data in family_data.get_child_elements():
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_DATE:
date = marriage_data.get_value()
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_PLACE:
place = marriage_data.get_value()
marriages.append((date, place))
return marriages
@@ -340,16 +379,16 @@
Module gedcom.parser
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
# Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
for family in families:
for child in family.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
+ if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
+ if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
date = childOfChild.get_value().split()[-1]
try:
dates.append(int(date))
@@ -365,7 +404,7 @@
Module gedcom.parser
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
years = self.get_marriage_years(individual)
@@ -380,7 +419,7 @@
Module gedcom.parser
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
years = self.get_marriage_years(individual)
@@ -389,20 +428,18 @@
Module gedcom.parser
return True
return False
- def get_families(self, individual, family_type=gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE):
+ def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
"""Return family elements listed for an individual
-
- family_type can be `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
-
+ family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
+ `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
+ provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
:type individual: IndividualElement
:type family_type: str
:rtype: list of FamilyElement
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
families = []
@@ -419,17 +456,15 @@
Module gedcom.parser
def get_ancestors(self, individual, ancestor_type="ALL"):
"""Return elements corresponding to ancestors of an individual
-
Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
used to specify only natural (genetic) ancestors.
-
:type individual: IndividualElement
:type ancestor_type: str
:rtype: list of Element
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
parents = self.get_parents(individual, ancestor_type)
@@ -443,35 +478,33 @@
Module gedcom.parser
def get_parents(self, individual, parent_type="ALL"):
"""Return elements corresponding to parents of an individual
-
Optional parent_type. Default "ALL" returns all parents. "NAT" can be
used to specify only natural (genetic) parents.
-
:type individual: IndividualElement
:type parent_type: str
:rtype: list of IndividualElement
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
parents = []
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_CHILD)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_CHILD)
for family in families:
if parent_type == "NAT":
for family_member in family.get_child_elements():
- if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
+ if family_member.get_tag() == tags.GEDCOM_TAG_CHILD \
and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
- if child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_WIFE)
- elif child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_HUSBAND)
+ if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
else:
parents += self.get_family_members(family, "PARENTS")
@@ -483,7 +516,7 @@
Module gedcom.parser
"""
if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
if not path:
@@ -502,22 +535,19 @@
Module gedcom.parser
def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
"""Return array of family members: individual, spouse, and children
-
Optional argument `members_type` can be used to return specific subsets:
-
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
-
:type family: FamilyElement
:type members_type: str
:rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
- "Operation only valid for element with %s tag." % gedcom.tags.GEDCOM_TAG_FAMILY
+ "Operation only valid for element with %s tag." % tags.GEDCOM_TAG_FAMILY
)
family_members = []
@@ -525,19 +555,19 @@
Module gedcom.parser
for child_element in family.get_child_elements():
# Default is ALL
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD)
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE
+ or child_element.get_tag() == tags.GEDCOM_TAG_CHILD)
if members_type == FAMILY_MEMBERS_TYPE_PARENTS:
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE)
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE)
elif members_type == FAMILY_MEMBERS_TYPE_HUSBAND:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
elif members_type == FAMILY_MEMBERS_TYPE_WIFE:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_WIFE
elif members_type == FAMILY_MEMBERS_TYPE_CHILDREN:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_CHILD
if is_family and child_element.get_value() in element_dictionary:
family_members.append(element_dictionary[child_element.get_value()])
@@ -583,45 +613,28 @@
Module gedcom.parser
Classes
-
-class GedcomFormatViolationError
-(...)
-
-
-
Common base class for all non-exit exceptions.
-
-
-Expand source code
-
-
class GedcomFormatViolationError(Exception):
- pass
class Parser():
"""Parses and manipulates GEDCOM 5.5 format data
- For documentation of the GEDCOM 5.5 format, see: http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
+ For documentation of the GEDCOM 5.5 format, see:
+ http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
This parser reads and parses a GEDCOM file.
@@ -637,8 +650,9 @@
Ancestors
self.__root_element = RootElement()
def invalidate_cache(self):
- """Empties the element list and dictionary to cause `gedcom.parser.Parser.get_element_list()`
- and `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
+ """Empties the element list and dictionary to cause
+ `gedcom.parser.Parser.get_element_list()` and
+ `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
The update gets deferred until each of the methods actually gets called.
"""
@@ -651,10 +665,11 @@
Ancestors
By default elements are in the same order as they appeared in the file.
This list gets generated on-the-fly, but gets cached. If the database
- was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once to let this
- method return updated data.
+ was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once
+ to let this method return updated data.
- Consider using `gedcom.parser.Parser.get_root_element()` or `gedcom.parser.Parser.get_root_child_elements()` to access
+ Consider using `gedcom.parser.Parser.get_root_element()` or
+ `gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
:rtype: list of Element
@@ -665,7 +680,8 @@
Ancestors
return self.__element_list
def get_element_dictionary(self):
- """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file
+ """Returns a dictionary containing all elements, identified by a pointer,
+ from within the GEDCOM file
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -678,7 +694,8 @@
Ancestors
"""
if not self.__element_dictionary:
self.__element_dictionary = {
- element.get_pointer(): element for element in self.get_root_child_elements() if element.get_pointer()
+ element.get_pointer():
+ element for element in self.get_root_child_elements() if element.get_pointer()
}
return self.__element_dictionary
@@ -706,7 +723,21 @@
Ancestors
:type file_path: str
:type strict: bool
"""
- with open(file_path, 'rb') as gedcom_stream:
+ codec = get_encoding(file_path)
+ real_version, reported_version, reported_format = get_version(file_path, codec)
+
+ if reported_version == '5.5.5':
+ errmsg = "This parser does not properly support the GEDCOM " + reported_version + \
+ " standard at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomVersionUnsupportedError(errmsg)
+
+ if reported_format not in ['LINEAGE-LINKED', 'LINEAGE_LINKED',
+ 'LINAGE-LINKED', 'Lineage - Linked']:
+ errmsg = "This parser does not recognize the GEDCOM format " + reported_format + \
+ " at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomFormatUnsupportedError(errmsg)
+
+ with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
def parse(self, gedcom_stream, strict=True):
@@ -721,7 +752,7 @@
end_of_line_regex = '([\r\n]{1,2})'
# Complete regex
- gedcom_line_regex = level_regex + pointer_regex + tag_regex + value_regex + end_of_line_regex
+ gedcom_line_regex = level_regex + pointer_regex + tag_regex + \
+ value_regex + end_of_line_regex
regex_match = regex.match(gedcom_line_regex, line)
if regex_match is None:
if strict:
- error_message = ("Line <%d:%s> of document violates GEDCOM format 5.5" % (line_number, line)
- + "\nSee: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdf")
- raise GedcomFormatViolationError(error_message)
+ errmsg = ERROR_TEMPLATE.format(line_number, line, '5.5.1', standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
+
+ # Quirk check - see if this is a line without a CRLF (which could be the last line)
+ last_line_regex = level_regex + pointer_regex + tag_regex + value_regex
+ regex_match = regex.match(last_line_regex, line)
+ if regex_match is not None:
+ line_parts = regex_match.groups()
+
+ level = int(line_parts[0])
+ pointer = line_parts[1].rstrip(' ')
+ tag = line_parts[2]
+ value = line_parts[3][1:]
+ crlf = '\n'
else:
- # Quirk check - see if this is a line without a CRLF (which could be the last line)
- last_line_regex = level_regex + pointer_regex + tag_regex + value_regex
- regex_match = regex.match(last_line_regex, line)
- if regex_match is not None:
- line_parts = regex_match.groups()
-
- level = int(line_parts[0])
- pointer = line_parts[1].rstrip(' ')
- tag = line_parts[2]
- value = line_parts[3][1:]
- crlf = '\n'
- else:
- # Quirk check - Sometimes a gedcom has a text field with a CR.
- # This creates a line without the standard level and pointer.
- # If this is detected then turn it into a CONC or CONT.
- line_regex = '([^\n\r]*|)'
- cont_line_regex = line_regex + end_of_line_regex
- regex_match = regex.match(cont_line_regex, line)
- line_parts = regex_match.groups()
- level = last_element.get_level()
- tag = last_element.get_tag()
- pointer = None
- value = line_parts[0][1:]
- crlf = line_parts[1]
- if tag != gedcom.tags.GEDCOM_TAG_CONTINUED and tag != gedcom.tags.GEDCOM_TAG_CONCATENATION:
- # Increment level and change this line to a CONC
- level += 1
- tag = gedcom.tags.GEDCOM_TAG_CONCATENATION
+ # Quirk check - Sometimes a gedcom has a text field with a CR.
+ # This creates a line without the standard level and pointer.
+ # If this is detected then turn it into a CONC or CONT.
+ line_regex = '([^\n\r]*|)'
+ cont_line_regex = line_regex + end_of_line_regex
+ regex_match = regex.match(cont_line_regex, line)
+ line_parts = regex_match.groups()
+ level = last_element.get_level()
+ tag = last_element.get_tag()
+ pointer = None
+ value = line_parts[0][1:]
+ crlf = line_parts[1]
+ if tag not in [tags.GEDCOM_TAG_CONTINUED, tags.GEDCOM_TAG_CONCATENATION]:
+ # Increment level and change this line to a CONC
+ level += 1
+ tag = tags.GEDCOM_TAG_CONCATENATION
else:
line_parts = regex_match.groups()
@@ -805,20 +836,14 @@
Ancestors
# Check level: should never be more than one higher than previous line.
if level > last_element.get_level() + 1:
- error_message = ("Line %d of document violates GEDCOM format 5.5" % line_number
- + "\nLines must be no more than one level higher than previous line."
- + "\nSee: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdf")
- raise GedcomFormatViolationError(error_message)
+ errmsg = "Line {0} of document violates GEDCOM format 5.5.1\n".format(line_number) + \
+ "Lines must be no more than one level higher than previous line.\n" + \
+ "See: {0}".format(standards.GEDCOM_5_5_1)
+ raise GedcomFormatViolationError(errmsg)
# Create element. Store in list and dict, create children and parents.
- if tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
- element = IndividualElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_FAMILY:
- element = FamilyElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_FILE:
- element = FileElement(level, pointer, tag, value, crlf, multi_line=False)
- elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
- element = ObjectElement(level, pointer, tag, value, crlf, multi_line=False)
+ if tag in RECORD_ELEMENTS:
+ element = RECORD_ELEMENTS[tag](level, pointer, tag, value, crlf, multi_line=False)
else:
element = Element(level, pointer, tag, value, crlf, multi_line=False)
@@ -852,19 +877,19 @@
Ancestors
marriages = []
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
# Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
for family in families:
for family_data in family.get_child_elements():
- if family_data.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
+ if family_data.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
date = ''
place = ''
for marriage_data in family_data.get_child_elements():
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_DATE:
date = marriage_data.get_value()
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_PLACE:
place = marriage_data.get_value()
marriages.append((date, place))
return marriages
@@ -878,16 +903,16 @@
Ancestors
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
# Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
for family in families:
for child in family.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
+ if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
+ if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
date = childOfChild.get_value().split()[-1]
try:
dates.append(int(date))
@@ -903,7 +928,7 @@
Ancestors
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
years = self.get_marriage_years(individual)
@@ -918,7 +943,7 @@
Ancestors
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
years = self.get_marriage_years(individual)
@@ -927,20 +952,18 @@
Ancestors
return True
return False
- def get_families(self, individual, family_type=gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE):
+ def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
"""Return family elements listed for an individual
-
- family_type can be `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
-
+ family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
+ `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
+ provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
:type individual: IndividualElement
:type family_type: str
:rtype: list of FamilyElement
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
families = []
@@ -957,17 +980,15 @@
Ancestors
def get_ancestors(self, individual, ancestor_type="ALL"):
"""Return elements corresponding to ancestors of an individual
-
Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
used to specify only natural (genetic) ancestors.
-
:type individual: IndividualElement
:type ancestor_type: str
:rtype: list of Element
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
parents = self.get_parents(individual, ancestor_type)
@@ -981,35 +1002,33 @@
Ancestors
def get_parents(self, individual, parent_type="ALL"):
"""Return elements corresponding to parents of an individual
-
Optional parent_type. Default "ALL" returns all parents. "NAT" can be
used to specify only natural (genetic) parents.
-
:type individual: IndividualElement
:type parent_type: str
:rtype: list of IndividualElement
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
parents = []
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_CHILD)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_CHILD)
for family in families:
if parent_type == "NAT":
for family_member in family.get_child_elements():
- if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
+ if family_member.get_tag() == tags.GEDCOM_TAG_CHILD \
and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
- if child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_WIFE)
- elif child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_HUSBAND)
+ if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
else:
parents += self.get_family_members(family, "PARENTS")
@@ -1021,7 +1040,7 @@
Ancestors
"""
if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
if not path:
@@ -1040,22 +1059,19 @@
Ancestors
def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
"""Return array of family members: individual, spouse, and children
-
Optional argument `members_type` can be used to return specific subsets:
-
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
-
:type family: FamilyElement
:type members_type: str
:rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
- "Operation only valid for element with %s tag." % gedcom.tags.GEDCOM_TAG_FAMILY
+ "Operation only valid for element with %s tag." % tags.GEDCOM_TAG_FAMILY
)
family_members = []
@@ -1063,19 +1079,19 @@
Ancestors
for child_element in family.get_child_elements():
# Default is ALL
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD)
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE
+ or child_element.get_tag() == tags.GEDCOM_TAG_CHILD)
if members_type == FAMILY_MEMBERS_TYPE_PARENTS:
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE)
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE)
elif members_type == FAMILY_MEMBERS_TYPE_HUSBAND:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
elif members_type == FAMILY_MEMBERS_TYPE_WIFE:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_WIFE
elif members_type == FAMILY_MEMBERS_TYPE_CHILDREN:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_CHILD
if is_family and child_element.get_value() in element_dictionary:
family_members.append(element_dictionary[child_element.get_value()])
@@ -1111,14 +1127,18 @@
Return path from descendant to ancestor
-:rtype: object
+
Return path from descendant to ancestor
+:rtype: object
Expand source code
@@ -1129,7 +1149,7 @@
Methods
"""
if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
if not path:
@@ -1151,29 +1171,27 @@
Return elements corresponding to ancestors of an individual
-
Optional ancestor_type. Default "ALL" returns all ancestors, "NAT" can be
-used to specify only natural (genetic) ancestors.
-
:type individual: IndividualElement
+
Return elements corresponding to ancestors of an individual
+Optional ancestor_type. Default "ALL" returns all ancestors, "NAT" can be
+used to specify only natural (genetic) ancestors.
+:type individual: IndividualElement
:type ancestor_type: str
-:rtype: list of Element
+:rtype: list of Element
Expand source code
def get_ancestors(self, individual, ancestor_type="ALL"):
"""Return elements corresponding to ancestors of an individual
-
Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
used to specify only natural (genetic) ancestors.
-
:type individual: IndividualElement
:type ancestor_type: str
:rtype: list of Element
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
parents = self.get_parents(individual, ancestor_type)
@@ -1190,19 +1208,21 @@
Methods
def get_element_dictionary(self)
-
Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file
+
Returns a dictionary containing all elements, identified by a pointer,
+from within the GEDCOM file
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
This dictionary gets generated on-the-fly, but gets cached. If the
database was modified, you should call invalidate_cache() once to let
this method return updated data.
-
:rtype: dict of Element
+
:rtype: dict of Element
Expand source code
def get_element_dictionary(self):
- """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file
+ """Returns a dictionary containing all elements, identified by a pointer,
+ from within the GEDCOM file
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -1215,7 +1235,8 @@
Methods
"""
if not self.__element_dictionary:
self.__element_dictionary = {
- element.get_pointer(): element for element in self.get_root_child_elements() if element.get_pointer()
+ element.get_pointer():
+ element for element in self.get_root_child_elements() if element.get_pointer()
}
return self.__element_dictionary
@@ -1225,14 +1246,15 @@
Methods
def get_element_list(self)
-
Returns a list containing all elements from within the GEDCOM file
+
Returns a list containing all elements from within the GEDCOM file
By default elements are in the same order as they appeared in the file.
This list gets generated on-the-fly, but gets cached. If the database
-was modified, you should call Parser.invalidate_cache() once to let this
-method return updated data.
By default elements are in the same order as they appeared in the file.
This list gets generated on-the-fly, but gets cached. If the database
- was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once to let this
- method return updated data.
+ was modified, you should call `gedcom.parser.Parser.invalidate_cache()` once
+ to let this method return updated data.
- Consider using `gedcom.parser.Parser.get_root_element()` or `gedcom.parser.Parser.get_root_child_elements()` to access
+ Consider using `gedcom.parser.Parser.get_root_element()` or
+ `gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
:rtype: list of Element
@@ -1261,31 +1284,29 @@
Return family elements listed for an individual
+family_type can be tags.GEDCOM_TAG_FAMILY_SPOUSE (families where the individual is a spouse) or
+tags.GEDCOM_TAG_FAMILY_CHILD (families where the individual is a child). If a value is not
+provided, tags.GEDCOM_TAG_FAMILY_SPOUSE is default value.
+:type individual: IndividualElement
:type family_type: str
-:rtype: list of FamilyElement
def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
"""Return family elements listed for an individual
-
- family_type can be `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
-
+ family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
+ `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
+ provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
:type individual: IndividualElement
:type family_type: str
:rtype: list of FamilyElement
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
families = []
@@ -1305,38 +1326,35 @@
Return array of family members: individual, spouse, and children
-
Optional argument members_type can be used to return specific subsets:
-
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+
Return array of family members: individual, spouse, and children
+Optional argument members_type can be used to return specific subsets:
+"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
-"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
-
:type family: FamilyElement
+"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
+:type family: FamilyElement
:type members_type: str
-:rtype: list of IndividualElement
+:rtype: list of IndividualElement
Expand source code
def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
"""Return array of family members: individual, spouse, and children
-
Optional argument `members_type` can be used to return specific subsets:
-
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
-
:type family: FamilyElement
:type members_type: str
:rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
- "Operation only valid for element with %s tag." % gedcom.tags.GEDCOM_TAG_FAMILY
+ "Operation only valid for element with %s tag." % tags.GEDCOM_TAG_FAMILY
)
family_members = []
@@ -1344,19 +1362,19 @@
Methods
for child_element in family.get_child_elements():
# Default is ALL
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD)
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE
+ or child_element.get_tag() == tags.GEDCOM_TAG_CHILD)
if members_type == FAMILY_MEMBERS_TYPE_PARENTS:
- is_family = (child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
- or child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE)
+ is_family = (child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
+ or child_element.get_tag() == tags.GEDCOM_TAG_WIFE)
elif members_type == FAMILY_MEMBERS_TYPE_HUSBAND:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_HUSBAND
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_HUSBAND
elif members_type == FAMILY_MEMBERS_TYPE_WIFE:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_WIFE
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_WIFE
elif members_type == FAMILY_MEMBERS_TYPE_CHILDREN:
- is_family = child_element.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD
+ is_family = child_element.get_tag() == tags.GEDCOM_TAG_CHILD
if is_family and child_element.get_value() in element_dictionary:
family_members.append(element_dictionary[child_element.get_value()])
@@ -1368,9 +1386,9 @@
Methods
def get_marriage_years(self, individual)
-
Returns a list of marriage years (as integers) for an individual
+
Returns a list of marriage years (as integers) for an individual
:type individual: IndividualElement
-:rtype: list of int
+:rtype: list of int
Expand source code
@@ -1384,16 +1402,16 @@
Methods
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
# Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
for family in families:
for child in family.get_child_elements():
- if child.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
+ if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
+ if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
date = childOfChild.get_value().split()[-1]
try:
dates.append(int(date))
@@ -1406,9 +1424,9 @@
Methods
def get_marriages(self, individual)
-
Returns a list of marriages of an individual formatted as a tuple (str date, str place)
+
Returns a list of marriages of an individual formatted as a tuple (str date, str place)
:type individual: IndividualElement
-:rtype: tuple
+:rtype: tuple
Expand source code
@@ -1421,19 +1439,19 @@
Methods
marriages = []
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
# Get and analyze families where individual is spouse.
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_SPOUSE)
for family in families:
for family_data in family.get_child_elements():
- if family_data.get_tag() == gedcom.tags.GEDCOM_TAG_MARRIAGE:
+ if family_data.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
date = ''
place = ''
for marriage_data in family_data.get_child_elements():
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_DATE:
date = marriage_data.get_value()
- if marriage_data.get_tag() == gedcom.tags.GEDCOM_TAG_PLACE:
+ if marriage_data.get_tag() == tags.GEDCOM_TAG_PLACE:
place = marriage_data.get_value()
marriages.append((date, place))
return marriages
@@ -1443,47 +1461,45 @@
Return elements corresponding to parents of an individual
-
Optional parent_type. Default "ALL" returns all parents. "NAT" can be
-used to specify only natural (genetic) parents.
-
:type individual: IndividualElement
+
Return elements corresponding to parents of an individual
+Optional parent_type. Default "ALL" returns all parents. "NAT" can be
+used to specify only natural (genetic) parents.
+:type individual: IndividualElement
:type parent_type: str
-:rtype: list of IndividualElement
+:rtype: list of IndividualElement
Expand source code
def get_parents(self, individual, parent_type="ALL"):
"""Return elements corresponding to parents of an individual
-
Optional parent_type. Default "ALL" returns all parents. "NAT" can be
used to specify only natural (genetic) parents.
-
:type individual: IndividualElement
:type parent_type: str
:rtype: list of IndividualElement
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
parents = []
- families = self.get_families(individual, gedcom.tags.GEDCOM_TAG_FAMILY_CHILD)
+ families = self.get_families(individual, tags.GEDCOM_TAG_FAMILY_CHILD)
for family in families:
if parent_type == "NAT":
for family_member in family.get_child_elements():
- if family_member.get_tag() == gedcom.tags.GEDCOM_TAG_CHILD \
+ if family_member.get_tag() == tags.GEDCOM_TAG_CHILD \
and family_member.get_value() == individual.get_pointer():
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
- if child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_WIFE)
- elif child.get_tag() == gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, gedcom.tags.GEDCOM_TAG_HUSBAND)
+ if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
+ parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
else:
parents += self.get_family_members(family, "PARENTS")
@@ -1494,9 +1510,9 @@
Methods
def get_root_child_elements(self)
-
Returns a list of logical records in the GEDCOM file
+
Returns a list of logical records in the GEDCOM file
By default, elements are in the same order as they appeared in the file.
-
:rtype: list of Element
+
:rtype: list of Element
Expand source code
@@ -1515,9 +1531,9 @@
Methods
def get_root_element(self)
-
Returns a virtual root element containing all logical records as children
+
Returns a virtual root element containing all logical records as children
When printed, this element converts to an empty string.
The update gets deferred until each of the methods actually gets called.
Expand source code
def invalidate_cache(self):
- """Empties the element list and dictionary to cause `gedcom.parser.Parser.get_element_list()`
- and `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
+ """Empties the element list and dictionary to cause
+ `gedcom.parser.Parser.get_element_list()` and
+ `gedcom.parser.Parser.get_element_dictionary()` to return updated data.
The update gets deferred until each of the methods actually gets called.
"""
@@ -1557,11 +1575,11 @@
Check if one of the marriage years of an individual is in a given range. Years are integers.
+
Check if one of the marriage years of an individual is in a given range. Years are integers.
:type individual: IndividualElement
:type from_year: int
:type to_year: int
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1575,7 +1593,7 @@
Methods
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
years = self.get_marriage_years(individual)
@@ -1589,10 +1607,10 @@
Methods
def marriage_year_match(self, individual, year)
-
Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
+
Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
:type individual: IndividualElement
:type year: int
-:rtype: bool
+:rtype: bool
Expand source code
@@ -1605,7 +1623,7 @@
Methods
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
- "Operation only valid for elements with %s tag" % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
+ "Operation only valid for elements with %s tag" % tags.GEDCOM_TAG_INDIVIDUAL
)
years = self.get_marriage_years(individual)
@@ -1616,9 +1634,9 @@
Methods
def parse(self, gedcom_stream, strict=True)
-
Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
+
Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
:type gedcom_stream: a file stream, or str array of lines with new line at the end
-:type strict: bool
+:type strict: bool
Expand source code
@@ -1635,7 +1653,7 @@
Methods
last_element = self.get_root_element()
for line in gedcom_stream:
- last_element = self.__parse_line(line_number, line.decode('utf-8-sig'), last_element, strict)
+ last_element = self.__parse_line(line_number, line, last_element, strict)
line_number += 1
@@ -1643,9 +1661,9 @@
Methods
def parse_file(self, file_path, strict=True)
-
Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
+
Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
:type file_path: str
-:type strict: bool
+:type strict: bool
Expand source code
@@ -1655,7 +1673,21 @@
Methods
:type file_path: str
:type strict: bool
"""
- with open(file_path, 'rb') as gedcom_stream:
+ codec = get_encoding(file_path)
+ real_version, reported_version, reported_format = get_version(file_path, codec)
+
+ if reported_version == '5.5.5':
+ errmsg = "This parser does not properly support the GEDCOM " + reported_version + \
+ " standard at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomVersionUnsupportedError(errmsg)
+
+ if reported_format not in ['LINEAGE-LINKED', 'LINEAGE_LINKED',
+ 'LINAGE-LINKED', 'Lineage - Linked']:
+ errmsg = "This parser does not recognize the GEDCOM format " + reported_format + \
+ " at this time\nSee: {0}".format(standards.GEDCOM_5_5_5)
+ raise GedcomFormatUnsupportedError(errmsg)
+
+ with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
@@ -1663,7 +1695,7 @@
Methods
def print_gedcom(self)
-
Write GEDCOM data to stdout
+
Write GEDCOM data to stdout
Expand source code
@@ -1678,9 +1710,9 @@
Methods
def save_gedcom(self, open_file, recursive=True)
-
Save GEDCOM data to a file
+
Save GEDCOM data to a file
:type open_file: file
-:type recursive: bool
+:type recursive: bool
Expand source code
@@ -1697,8 +1729,8 @@
Methods
def to_gedcom_string(self, recursive=False)
-
Formats all elements and optionally all of the sub-elements into a GEDCOM string
-:type recursive: bool
+
Formats all elements and optionally all of the sub-elements into a GEDCOM string
+:type recursive: bool
Module containing a Reader with higher order methods than the
+base Parser
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Module containing a `gedcom.reader.Reader` with higher order methods than the
+base `gedcom.parser.Parser`
+"""
+
+from gedcom.parser import Parser
+from gedcom.element.header import HeaderElement
+from gedcom.element.individual import IndividualElement
+from gedcom.element.family import FamilyElement
+from gedcom.element.note import NoteElement
+from gedcom.element.object import ObjectElement
+from gedcom.element.source import SourceElement
+from gedcom.element.submission import SubmissionElement
+from gedcom.element.submitter import SubmitterElement
+from gedcom.element.repository import RepositoryElement
+
+ELEMENT_TYPES = {
+ 'header': HeaderElement,
+ 'individual': IndividualElement,
+ 'family': FamilyElement,
+ 'note': NoteElement,
+ 'media': ObjectElement,
+ 'source': SourceElement,
+ 'submission': SubmissionElement,
+ 'submitter': SubmitterElement,
+ 'repository': RepositoryElement
+}
+
+RECORD_KEYS = {
+ 'header': None,
+ 'individual': 'key_to_individual',
+ 'family': 'key_to_family',
+ 'media': 'key_to_object',
+ 'note': 'key_to_note',
+ 'source': 'key_to_source',
+ 'submission': 'key_to_submission',
+ 'submitter': 'key_to_submitter',
+ 'repository': 'key_to_repository'
+}
+
+
+class Reader(Parser):
+ """Simple wrapper class around the core parser with simple methods for
+ extracting parsed records as structured data.
+ """
+
+ def get_records_by_type(self, record_type, output='list'):
+ """Return either a list or dictionary with all the requested records
+ :type: record_type: str
+ :type: output: str
+ :rtype: list or dict
+ """
+ record_list = []
+ record_dict = {}
+
+ for element in self.get_root_child_elements():
+ if isinstance(element, ELEMENT_TYPES[record_type]):
+ record = element.get_record()
+ if output == 'list':
+ record_list.append(record)
+ else:
+ if RECORD_KEYS[record_type] is not None:
+ record_dict.update({record[RECORD_KEYS[record_type]]: record})
+ else:
+ record_dict.update({'@HEAD@': record})
+
+ if output == 'list':
+ return record_list
+
+ return record_dict
+
+ def get_all_records(self, entries='list'):
+ """Return a dictionary with all the requested records
+ :type: entries: str
+ :rtype: dict
+ """
+ record_dict = {}
+ for key in RECORD_KEYS:
+ if entries == 'list':
+ record_dict.update({key: []})
+ else:
+ record_dict.update({key: {}})
+
+ for element in self.get_root_child_elements():
+ for key in ELEMENT_TYPES:
+ if isinstance(element, ELEMENT_TYPES[key]):
+ record = element.get_record()
+ if entries == 'list':
+ record_dict[key].append(record)
+ else:
+ if key != 'header':
+ record_dict[key].update({record[RECORD_KEYS[key]]: record})
+ else:
+ record_dict['header'].update({'@HEAD@': record})
+
+ return record_dict
+
+
+
+
+
+
+
+
+
+
Classes
+
+
+class Reader
+
+
+
Simple wrapper class around the core parser with simple methods for
+extracting parsed records as structured data.
+
+
+Expand source code
+
+
class Reader(Parser):
+ """Simple wrapper class around the core parser with simple methods for
+ extracting parsed records as structured data.
+ """
+
+ def get_records_by_type(self, record_type, output='list'):
+ """Return either a list or dictionary with all the requested records
+ :type: record_type: str
+ :type: output: str
+ :rtype: list or dict
+ """
+ record_list = []
+ record_dict = {}
+
+ for element in self.get_root_child_elements():
+ if isinstance(element, ELEMENT_TYPES[record_type]):
+ record = element.get_record()
+ if output == 'list':
+ record_list.append(record)
+ else:
+ if RECORD_KEYS[record_type] is not None:
+ record_dict.update({record[RECORD_KEYS[record_type]]: record})
+ else:
+ record_dict.update({'@HEAD@': record})
+
+ if output == 'list':
+ return record_list
+
+ return record_dict
+
+ def get_all_records(self, entries='list'):
+ """Return a dictionary with all the requested records
+ :type: entries: str
+ :rtype: dict
+ """
+ record_dict = {}
+ for key in RECORD_KEYS:
+ if entries == 'list':
+ record_dict.update({key: []})
+ else:
+ record_dict.update({key: {}})
+
+ for element in self.get_root_child_elements():
+ for key in ELEMENT_TYPES:
+ if isinstance(element, ELEMENT_TYPES[key]):
+ record = element.get_record()
+ if entries == 'list':
+ record_dict[key].append(record)
+ else:
+ if key != 'header':
+ record_dict[key].update({record[RECORD_KEYS[key]]: record})
+ else:
+ record_dict['header'].update({'@HEAD@': record})
+
+ return record_dict
Return either a list or dictionary with all the requested records
+:type: record_type: str
+:type: output: str
+:rtype: list or dict
+
+
+Expand source code
+
+
def get_records_by_type(self, record_type, output='list'):
+ """Return either a list or dictionary with all the requested records
+ :type: record_type: str
+ :type: output: str
+ :rtype: list or dict
+ """
+ record_list = []
+ record_dict = {}
+
+ for element in self.get_root_child_elements():
+ if isinstance(element, ELEMENT_TYPES[record_type]):
+ record = element.get_record()
+ if output == 'list':
+ record_list.append(record)
+ else:
+ if RECORD_KEYS[record_type] is not None:
+ record_dict.update({record[RECORD_KEYS[record_type]]: record})
+ else:
+ record_dict.update({'@HEAD@': record})
+
+ if output == 'list':
+ return record_list
+
+ return record_dict
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/standards.html b/docs/gedcom/standards.html
new file mode 100644
index 0000000..5f7af48
--- /dev/null
+++ b/docs/gedcom/standards.html
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+gedcom.standards API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.standards
+
+
+
The official FamilySearch 5.5 standard
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""The official FamilySearch 5.5 standard"""
+GEDCOM_5_5 = "https://edge.fscdn.org/assets/img/documents/" + \
+ "gedcom55-82e1509bd8dbe7477e3b500e4f62c240.pdf"
+
+"""The official FamilySearch 5.5.1 standard"""
+GEDCOM_5_5_1 = "https://edge.fscdn.org/assets/img/documents/" + \
+ "ged551-5bac5e57fe88dd37df0e153d9c515335.pdf"
+
+"""The GEDCOM-L working group 5.5.1 addendum"""
+GEDCOM_5_5_1_GEDCOM_L_ADDENDUM = "https://genealogy.net/GEDCOM/" + \
+ "GEDCOM551%20GEDCOM-L%20Addendum-R1.pdf"
+
+"""The gedcom.org 5.5.5 specification with annotations"""
+GEDCOM_5_5_5 = "https://www.gedcom.org/specs/GEDCOM555.zip"
+
+
+
+
+
+
Global variables
+
+
var GEDCOM_5_5
+
+
The official FamilySearch 5.5.1 standard
+
+
var GEDCOM_5_5_1
+
+
The GEDCOM-L working group 5.5.1 addendum
+
+
var GEDCOM_5_5_1_GEDCOM_L_ADDENDUM
+
+
The gedcom.org 5.5.5 specification with annotations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/address_structure.html b/docs/gedcom/subparsers/address_structure.html
new file mode 100644
index 0000000..38a6857
--- /dev/null
+++ b/docs/gedcom/subparsers/address_structure.html
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+gedcom.subparsers.address_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.address_structure
+
+
+
Substructure parser for the ADDRESS_STRUCTURE embedded record.
+
Note this is usually referenced as part of a larger structure and the
+GEDCOM_TAG_ADDRESS tag is at the same level as some of
+the other parts of this structure.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the ADDRESS_STRUCTURE embedded record.
+
+Note this is usually referenced as part of a larger structure and the
+`gedcom.tags.GEDCOM_TAG_ADDRESS` tag is at the same level as some of
+the other parts of this structure.
+"""
+
+import gedcom.tags as tags
+
+ADDRESS_TAGS = {
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE: 'addresse',
+ tags.GEDCOM_TAG_ADDRESS1: 'address1',
+ tags.GEDCOM_TAG_ADDRESS2: 'address2',
+ tags.GEDCOM_TAG_ADDRESS3: 'address3',
+ tags.GEDCOM_TAG_CITY: 'city',
+ tags.GEDCOM_TAG_STATE: 'state',
+ tags.GEDCOM_TAG_POSTAL_CODE: 'postal_code',
+ tags.GEDCOM_TAG_COUNTRY: 'country'
+}
+
+CONTACT_TAGS = {
+ tags.GEDCOM_TAG_PHONE: 'phone',
+ tags.GEDCOM_TAG_EMAIL: 'email',
+ tags.GEDCOM_TAG_FAX: 'fax',
+ tags.GEDCOM_TAG_WWW: 'www'
+}
+
+
+def address_structure(element):
+ """Parses and extracts the ADDRESS_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'address': '',
+ 'addresse': '',
+ 'address1': '',
+ 'address2': '',
+ 'address3': '',
+ 'city': '',
+ 'state': '',
+ 'postal_code': '',
+ 'country': '',
+ 'phone': [],
+ 'email': [],
+ 'fax': [],
+ 'www': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = child.get_multi_line_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in ADDRESS_TAGS:
+ record[ADDRESS_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if child.get_tag() in CONTACT_TAGS:
+ record[CONTACT_TAGS[child.get_tag()]].append(child.get_value())
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def address_structure(element)
+
+
+
Parses and extracts the ADDRESS_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def address_structure(element):
+ """Parses and extracts the ADDRESS_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'address': '',
+ 'addresse': '',
+ 'address1': '',
+ 'address2': '',
+ 'address3': '',
+ 'city': '',
+ 'state': '',
+ 'postal_code': '',
+ 'country': '',
+ 'phone': [],
+ 'email': [],
+ 'fax': [],
+ 'www': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = child.get_multi_line_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in ADDRESS_TAGS:
+ record[ADDRESS_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if child.get_tag() in CONTACT_TAGS:
+ record[CONTACT_TAGS[child.get_tag()]].append(child.get_value())
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/association_structure.html b/docs/gedcom/subparsers/association_structure.html
new file mode 100644
index 0000000..b196418
--- /dev/null
+++ b/docs/gedcom/subparsers/association_structure.html
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+gedcom.subparsers.association_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.association_structure
+
+
+
Substructure parser for the ASSOCIATION_STRUCTURE record identified by the
+GEDCOM_TAG_ASSOCIATES tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the ASSOCIATION_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_ASSOCIATES` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+
+def association_structure(element):
+ """Parses and extracts the ASSOCIATION_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': element.get_value(),
+ 'relationship': '',
+ 'citations': [],
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_RELATIONSHIP:
+ record['relationship'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def association_structure(element)
+
+
+
Parses and extracts the ASSOCIATION_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def association_structure(element):
+ """Parses and extracts the ASSOCIATION_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'key_to_individual': element.get_value(),
+ 'relationship': '',
+ 'citations': [],
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_RELATIONSHIP:
+ record['relationship'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/change_date.html b/docs/gedcom/subparsers/change_date.html
new file mode 100644
index 0000000..00b0f92
--- /dev/null
+++ b/docs/gedcom/subparsers/change_date.html
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+gedcom.subparsers.change_date API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.change_date
+
+
+
Substructure parser for the CHANGE_DATE record identified by the
+GEDCOM_TAG_CHANGE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the CHANGE_DATE record identified by the
+`gedcom.tags.GEDCOM_TAG_CHANGE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+
+def change_date(element):
+ """Parses and extracts the CHANGE_DATE
+ :rtype: dict
+ """
+ record = {
+ 'date': '',
+ 'time': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['date'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TIME:
+ record['time'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def change_date(element)
+
+
+
Parses and extracts the CHANGE_DATE
+:rtype: dict
+
+
+Expand source code
+
+
def change_date(element):
+ """Parses and extracts the CHANGE_DATE
+ :rtype: dict
+ """
+ record = {
+ 'date': '',
+ 'time': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['date'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TIME:
+ record['time'] = gchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/child_to_family_link.html b/docs/gedcom/subparsers/child_to_family_link.html
new file mode 100644
index 0000000..3a05fa8
--- /dev/null
+++ b/docs/gedcom/subparsers/child_to_family_link.html
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+gedcom.subparsers.child_to_family_link API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.child_to_family_link
+
+
+
Substructure parser for the CHILD_TO_FAMILY_LINK record identified by the
+GEDCOM_TAG_FAMILY_CHILD tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the CHILD_TO_FAMILY_LINK record identified by the
+`gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+
+def child_to_family_link(element):
+ """Parses and extracts the CHILD_TO_FAMILY_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': element.get_value(),
+ 'pedigree': '',
+ 'status': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_PEDIGREE:
+ record['pedigree'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def child_to_family_link(element)
+
+
+
Parses and extracts the CHILD_TO_FAMILY_LINK
+:rtype: dict
+
+
+Expand source code
+
+
def child_to_family_link(element):
+ """Parses and extracts the CHILD_TO_FAMILY_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': element.get_value(),
+ 'pedigree': '',
+ 'status': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_PEDIGREE:
+ record['pedigree'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/event_detail.html b/docs/gedcom/subparsers/event_detail.html
new file mode 100644
index 0000000..e9969bc
--- /dev/null
+++ b/docs/gedcom/subparsers/event_detail.html
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+gedcom.subparsers.event_detail API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.event_detail
+
+
+
Substructure parser for the EVENT_DETAIL embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the EVENT_DETAIL embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.place_structure import place_structure
+from gedcom.subparsers.address_structure import address_structure
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+from gedcom.subparsers.multimedia_link import multimedia_link
+
+EVENT_TAGS = {
+ tags.GEDCOM_TAG_TYPE: 'type',
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_AGENCY: 'responsible_agency',
+ tags.GEDCOM_TAG_RELIGION: 'religious_affiliation',
+ tags.GEDCOM_TAG_CAUSE: 'cause_of_event',
+ tags.GEDCOM_TAG_RESTRICTION: 'restriction'
+}
+
+
+def event_detail(element):
+ """Parses and extracts the EVENT_DETAIL
+ :rtype: dict
+ """
+ record = {
+ 'type': '',
+ 'date': '',
+ 'place': {},
+ 'address': {},
+ 'responsible_agency': '',
+ 'religious_affiliation': '',
+ 'cause_of_event': '',
+ 'restriction_notice': '',
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() in EVENT_TAGS:
+ record[EVENT_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PLACE:
+ record['place'] = place_structure(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(element)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def event_detail(element)
+
+
+
Parses and extracts the EVENT_DETAIL
+:rtype: dict
+
+
+Expand source code
+
+
def event_detail(element):
+ """Parses and extracts the EVENT_DETAIL
+ :rtype: dict
+ """
+ record = {
+ 'type': '',
+ 'date': '',
+ 'place': {},
+ 'address': {},
+ 'responsible_agency': '',
+ 'religious_affiliation': '',
+ 'cause_of_event': '',
+ 'restriction_notice': '',
+ 'notes': [],
+ 'citations': [],
+ 'media': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() in EVENT_TAGS:
+ record[EVENT_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PLACE:
+ record['place'] = place_structure(child)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADDRESS:
+ record['address'] = address_structure(element)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/family_event_detail.html b/docs/gedcom/subparsers/family_event_detail.html
new file mode 100644
index 0000000..08b7fd4
--- /dev/null
+++ b/docs/gedcom/subparsers/family_event_detail.html
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+gedcom.subparsers.family_event_detail API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.family_event_detail
+
+
+
Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.event_detail import event_detail
+
+
+def family_event_detail(element):
+ """Parses and extracts the FAMILY_EVENT_DETAIL
+ :rtype: dict
+ """
+ record = event_detail(element)
+ record['husband_age'] = ''
+ record['wife_age'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_HUSBAND:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['husband_age'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_WIFE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['wife_age'] = gchild.get_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def family_event_detail(element)
+
+
+
Parses and extracts the FAMILY_EVENT_DETAIL
+:rtype: dict
+
+
+Expand source code
+
+
def family_event_detail(element):
+ """Parses and extracts the FAMILY_EVENT_DETAIL
+ :rtype: dict
+ """
+ record = event_detail(element)
+ record['husband_age'] = ''
+ record['wife_age'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_HUSBAND:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['husband_age'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_WIFE:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['wife_age'] = gchild.get_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/family_event_structure.html b/docs/gedcom/subparsers/family_event_structure.html
new file mode 100644
index 0000000..39f4ab5
--- /dev/null
+++ b/docs/gedcom/subparsers/family_event_structure.html
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+gedcom.subparsers.family_event_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.family_event_structure
+
+
+
Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.family_event_detail import family_event_detail
+
+EVENT_TAGS = {
+ tags.GEDCOM_TAG_ANNULMENT: 'annulment',
+ tags.GEDCOM_TAG_CENSUS: 'census',
+ tags.GEDCOM_TAG_DIVORCE: 'divorce',
+ tags.GEDCOM_TAG_DIVORCE_FILED: 'divorce_filed',
+ tags.GEDCOM_TAG_ENGAGEMENT: 'engagement',
+ tags.GEDCOM_TAG_MARRIAGE: 'marriage',
+ tags.GEDCOM_TAG_MARRIAGE_BANN: 'marriage_bann',
+ tags.GEDCOM_TAG_MARR_CONTRACT: 'marriage_contract',
+ tags.GEDCOM_TAG_MARR_LICENSE: 'marriage_license',
+ tags.GEDCOM_TAG_MARR_SETTLEMENT: 'marriage_settlement',
+ tags.GEDCOM_TAG_RESIDENCE: 'residence',
+ tags.GEDCOM_TAG_EVENT: 'event'
+}
+
+
+def family_event_structure(element):
+ """Parses and extracts the FAMILY_EVENT_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in EVENT_TAGS:
+ record = family_event_detail(child)
+ record['description'] = child.get_multi_line_value()
+ record['tag'] = child.get_tag()
+ record['event'] = EVENT_TAGS[child.get_tag()]
+ records.append(record)
+
+ return records
+
+
+
+
+
+
+
+
Functions
+
+
+def family_event_structure(element)
+
+
+
Parses and extracts the FAMILY_EVENT_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def family_event_structure(element):
+ """Parses and extracts the FAMILY_EVENT_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in EVENT_TAGS:
+ record = family_event_detail(child)
+ record['description'] = child.get_multi_line_value()
+ record['tag'] = child.get_tag()
+ record['event'] = EVENT_TAGS[child.get_tag()]
+ records.append(record)
+
+ return records
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/index.html b/docs/gedcom/subparsers/index.html
new file mode 100644
index 0000000..2299960
--- /dev/null
+++ b/docs/gedcom/subparsers/index.html
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+gedcom.subparsers API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers
+
+
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+__all__ = [
+ "address_structure",
+ "association_structure",
+ "change_date",
+ "child_to_family_link",
+ "event_detail",
+ "family_event_detail",
+ "family_event_structure",
+ "individual_attribute_structure",
+ "individual_event_detail",
+ "individual_event_structure",
+ "lds_individual_ordinance",
+ "lds_spouse_sealing",
+ "multimedia_link",
+ "note_structure",
+ "personal_name_pieces",
+ "personal_name_structure",
+ "place_structure",
+ "source_citation",
+ "source_repository_citation",
+ "spouse_to_family_link",
+ "user_reference_number"
+]
Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier …
Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
+referenced in place in part of another structure there is no identifier tag.
Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record. As
+this is referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record. As
+this is referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.individual_event_detail import individual_event_detail
+
+ATTRIBUTE_TAGS = {
+ tags.GEDCOM_TAG_CASTE: 'caste',
+ tags.GEDCOM_TAG_PHY_DESCRIPTION: 'physical_description',
+ tags.GEDCOM_TAG_EDUCATION: 'eduction',
+ tags.GEDCOM_TAG_IDENT_NUMBER: 'identity_number',
+ tags.GEDCOM_TAG_NATIONALITY: 'nationality',
+ tags.GEDCOM_TAG_CHILDREN_COUNT: 'number_of_children',
+ tags.GEDCOM_TAG_MARRIAGE_COUNT: 'number_of_marriages',
+ tags.GEDCOM_TAG_OCCUPATION: 'occupation',
+ tags.GEDCOM_TAG_PROPERTY: 'property',
+ tags.GEDCOM_TAG_RELIGION: 'religion',
+ tags.GEDCOM_TAG_RESIDENCE: 'residence',
+ tags.GEDCOM_TAG_SOC_SEC_NUMBER: 'social_security_number',
+ tags.GEDCOM_TAG_TITLE: 'title',
+ tags.GEDCOM_TAG_FACT: 'fact',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE: 'cause_of_death'
+}
+
+
+def individual_attribute_structure(element):
+ """Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in ATTRIBUTE_TAGS:
+ record = individual_event_detail(child)
+ record['description'] = child.get_multi_line_value()
+ record['tag'] = child.get_tag()
+ record['attribute'] = ATTRIBUTE_TAGS[child.get_tag()]
+ records.append(record)
+ continue
+
+ return records
+
+
+
+
+
+
+
+
Functions
+
+
+def individual_attribute_structure(element)
+
+
+
Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def individual_attribute_structure(element):
+ """Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in ATTRIBUTE_TAGS:
+ record = individual_event_detail(child)
+ record['description'] = child.get_multi_line_value()
+ record['tag'] = child.get_tag()
+ record['attribute'] = ATTRIBUTE_TAGS[child.get_tag()]
+ records.append(record)
+ continue
+
+ return records
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/individual_event_detail.html b/docs/gedcom/subparsers/individual_event_detail.html
new file mode 100644
index 0000000..bdd4118
--- /dev/null
+++ b/docs/gedcom/subparsers/individual_event_detail.html
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+gedcom.subparsers.individual_event_detail API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.individual_event_detail
+
+
+
Substructure parser for the INDIVIDUAL_EVENT_DETAIL emdedded record. As this
+is referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the INDIVIDUAL_EVENT_DETAIL emdedded record. As this
+is referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.event_detail import event_detail
+
+
+def individual_event_detail(element):
+ """Parses and extracts INDIVIDUAL_EVENT_DETAIL
+ :rtype: dict
+ """
+ record = event_detail(element)
+ record['age'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['age'] = child.get_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def individual_event_detail(element)
+
+
+
Parses and extracts INDIVIDUAL_EVENT_DETAIL
+:rtype: dict
+
+
+Expand source code
+
+
def individual_event_detail(element):
+ """Parses and extracts INDIVIDUAL_EVENT_DETAIL
+ :rtype: dict
+ """
+ record = event_detail(element)
+ record['age'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_AGE:
+ record['age'] = child.get_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/individual_event_structure.html b/docs/gedcom/subparsers/individual_event_structure.html
new file mode 100644
index 0000000..660175d
--- /dev/null
+++ b/docs/gedcom/subparsers/individual_event_structure.html
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+gedcom.subparsers.individual_event_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Substructure parser for the INDIVIDUAL_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the INDIVIDUAL_EVENT_STRUCTURE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.individual_event_detail import individual_event_detail
+
+EVENT_TAGS = {
+ tags.GEDCOM_TAG_DEATH: 'death',
+ tags.GEDCOM_TAG_BURIAL: 'burial',
+ tags.GEDCOM_TAG_CREMATION: 'cremation',
+ tags.GEDCOM_TAG_BAPTISM: 'baptism',
+ tags.GEDCOM_TAG_BAR_MITZVAH: 'bar_mitzvah',
+ tags.GEDCOM_TAG_BAS_MITZVAH: 'bas_mitzvah',
+ tags.GEDCOM_TAG_BLESSING: 'blessing',
+ tags.GEDCOM_TAG_ADULT_CHRISTENING: 'adult_christening',
+ tags.GEDCOM_TAG_CONFIRMATION: 'confirmation',
+ tags.GEDCOM_TAG_FIRST_COMMUNION: 'first_communion',
+ tags.GEDCOM_TAG_ORDINATION: 'ordination',
+ tags.GEDCOM_TAG_NATURALIZATION: 'naturalization',
+ tags.GEDCOM_TAG_EMIGRATION: 'emmigration',
+ tags.GEDCOM_TAG_IMMIGRATION: 'immigration',
+ tags.GEDCOM_TAG_CENSUS: 'census',
+ tags.GEDCOM_TAG_PROBATE: 'probate',
+ tags.GEDCOM_TAG_WILL: 'will',
+ tags.GEDCOM_TAG_GRADUATION: 'graduation',
+ tags.GEDCOM_TAG_RETIREMENT: 'retirement',
+ tags.GEDCOM_TAG_EVENT: 'event',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_DEGREE: 'degree',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_FUNERAL: 'funeral',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL: 'medical',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_MILITARY: 'military'
+}
+
+BIRTH_EVENT_TAGS = {
+ tags.GEDCOM_TAG_BIRTH: 'birth',
+ tags.GEDCOM_TAG_CHRISTENING: 'christening'
+}
+
+
+def individual_event_structure(element):
+ """Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in BIRTH_EVENT_TAGS:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = BIRTH_EVENT_TAGS[child.get_tag()]
+ record['description'] = child.get_multi_line_value()
+ record['family'] = ''
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['family'] = gchild.get_value()
+ records.append(record)
+ continue
+
+ if child.get_tag() in EVENT_TAGS:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = EVENT_TAGS[child.get_tag()]
+ record['description'] = child.get_multi_line_value()
+ records.append(record)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADOPTION:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = 'adoption'
+ record['description'] = child.get_multi_line_value()
+ record['family'] = ''
+ record['parent'] = ''
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['family'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_ADOPTION:
+ record['parent'] = ggchild.get_value()
+ records.append(record)
+
+ return records
+
+
+
+
+
+
+
+
Functions
+
+
+def individual_event_structure(element)
+
+
+
Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def individual_event_structure(element):
+ """Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in BIRTH_EVENT_TAGS:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = BIRTH_EVENT_TAGS[child.get_tag()]
+ record['description'] = child.get_multi_line_value()
+ record['family'] = ''
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['family'] = gchild.get_value()
+ records.append(record)
+ continue
+
+ if child.get_tag() in EVENT_TAGS:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = EVENT_TAGS[child.get_tag()]
+ record['description'] = child.get_multi_line_value()
+ records.append(record)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ADOPTION:
+ record = individual_event_detail(child)
+ record['tag'] = child.get_tag()
+ record['event'] = 'adoption'
+ record['description'] = child.get_multi_line_value()
+ record['family'] = ''
+ record['parent'] = ''
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
+ record['family'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_ADOPTION:
+ record['parent'] = ggchild.get_value()
+ records.append(record)
+
+ return records
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/lds_individual_ordinance.html b/docs/gedcom/subparsers/lds_individual_ordinance.html
new file mode 100644
index 0000000..0b928dd
--- /dev/null
+++ b/docs/gedcom/subparsers/lds_individual_ordinance.html
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+gedcom.subparsers.lds_individual_ordinance API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.lds_individual_ordinance
+
+
+
Substructure parser for the LDS_INDIVIDUAL_ORDINANCE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the LDS_INDIVIDUAL_ORDINANCE embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+ORDINANCE_TAGS = {
+ tags.GEDCOM_TAG_BAPTISM_LDS: 'lds_baptism',
+ tags.GEDCOM_TAG_CONFIRMATION_L: 'lds_confirmation',
+ tags.GEDCOM_TAG_ENDOWMENT: 'lds_endowment',
+ tags.GEDCOM_TAG_SEALING_CHILD: 'lds_sealing_child'
+}
+
+ORDINANCE_ATTRIBUTE_TAGS = {
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_TEMPLE: 'temple',
+ tags.GEDCOM_TAG_PLACE: 'place',
+ tags.GEDCOM_TAG_FAMILY_CHILD: 'key_to_family'
+}
+
+
+def lds_individual_ordinance(element):
+ """Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in ORDINANCE_TAGS:
+ record = {
+ 'date': '',
+ 'temple': '',
+ 'place': '',
+ 'status': '',
+ 'status_change': '',
+ 'notes': [],
+ 'citations': [],
+ 'tag': child.get_tag(),
+ 'event': ORDINANCE_TAGS[child.get_tag()]
+ }
+ if child.get_tag() == tags.GEDCOM_TAG_SEALING_CHILD:
+ record.update({'key_to_family': ''})
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in ORDINANCE_ATTRIBUTE_TAGS:
+ record[ORDINANCE_ATTRIBUTE_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['status_change'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ records.append(record)
+ continue
+
+ return records
+
+
+
+
+
+
+
+
Functions
+
+
+def lds_individual_ordinance(element)
+
+
+
Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
+:rtype: dict
+
+
+Expand source code
+
+
def lds_individual_ordinance(element):
+ """Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() in ORDINANCE_TAGS:
+ record = {
+ 'date': '',
+ 'temple': '',
+ 'place': '',
+ 'status': '',
+ 'status_change': '',
+ 'notes': [],
+ 'citations': [],
+ 'tag': child.get_tag(),
+ 'event': ORDINANCE_TAGS[child.get_tag()]
+ }
+ if child.get_tag() == tags.GEDCOM_TAG_SEALING_CHILD:
+ record.update({'key_to_family': ''})
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in ORDINANCE_ATTRIBUTE_TAGS:
+ record[ORDINANCE_ATTRIBUTE_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['status_change'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ records.append(record)
+ continue
+
+ return records
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/lds_spouse_sealing.html b/docs/gedcom/subparsers/lds_spouse_sealing.html
new file mode 100644
index 0000000..18b05a3
--- /dev/null
+++ b/docs/gedcom/subparsers/lds_spouse_sealing.html
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+gedcom.subparsers.lds_spouse_sealing API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.lds_spouse_sealing
+
+
+
Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
+referenced in place as part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+SEALING_TAGS = {
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_TEMPLE: 'temple',
+ tags.GEDCOM_TAG_PLACE: 'place',
+ tags.GEDCOM_TAG_FAMILY_CHILD: 'key_to_family'
+}
+
+
+def lds_spouse_sealing(element):
+ """Parses and extracts the LDS_SPOUSE_SEALING
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_SEALING_SPOUSE:
+ record = {
+ 'date': '',
+ 'temple': '',
+ 'place': '',
+ 'status': '',
+ 'status_change': '',
+ 'notes': [],
+ 'citations': [],
+ 'tag': tags.GEDCOM_TAG_SEALING_SPOUSE,
+ 'event': 'lds_spouse_sealing'
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in SEALING_TAGS:
+ record[SEALING_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['status_change'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ records.append(record)
+ continue
+
+ return records
+
+
+
+
+
+
+
+
Functions
+
+
+def lds_spouse_sealing(element)
+
+
+
Parses and extracts the LDS_SPOUSE_SEALING
+:rtype: dict
+
+
+Expand source code
+
+
def lds_spouse_sealing(element):
+ """Parses and extracts the LDS_SPOUSE_SEALING
+ :rtype: dict
+ """
+ records = []
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_SEALING_SPOUSE:
+ record = {
+ 'date': '',
+ 'temple': '',
+ 'place': '',
+ 'status': '',
+ 'status_change': '',
+ 'notes': [],
+ 'citations': [],
+ 'tag': tags.GEDCOM_TAG_SEALING_SPOUSE,
+ 'event': 'lds_spouse_sealing'
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() in SEALING_TAGS:
+ record[SEALING_TAGS[gchild.get_tag()]] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_STATUS:
+ record['status'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['status_change'] = ggchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ records.append(record)
+ continue
+
+ return records
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/multimedia_link.html b/docs/gedcom/subparsers/multimedia_link.html
new file mode 100644
index 0000000..4ff3962
--- /dev/null
+++ b/docs/gedcom/subparsers/multimedia_link.html
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+gedcom.subparsers.multimedia_link API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.multimedia_link
+
+
+
Substructure parser for the MULTIMEDIA_LINK record identified by the
+GEDCOM_TAG_OBJECT tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the MULTIMEDIA_LINK record identified by the
+`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
+"""
+
+import gedcom.tags as tags
+
+MEDIA_TAGS = {
+ tags.GEDCOM_TAG_FILE: 'file',
+ tags.GEDCOM_TAG_FORMAT: 'format',
+ tags.GEDCOM_TAG_MEDIA: 'type',
+ tags.GEDCOM_TAG_TITLE: 'title',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_PHOTO: 'preferred',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY: 'preferred'
+}
+
+
+def multimedia_link(element):
+ """Parse and extract a MULTIMEDIA_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_object': element.get_value(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'preferred': ''
+ }
+ if record['key_to_object'] not in [None, '']:
+ if '@' in record['key_to_object']:
+ return record
+
+ record['key_to_object'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['type'] = ggchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() in MEDIA_TAGS:
+ record[MEDIA_TAGS[child.get_tag()]] = child.get_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def multimedia_link(element)
+
+
+
Parse and extract a MULTIMEDIA_LINK
+:rtype: dict
+
+
+Expand source code
+
+
def multimedia_link(element):
+ """Parse and extract a MULTIMEDIA_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_object': element.get_value(),
+ 'file': '',
+ 'format': '',
+ 'type': '',
+ 'title': '',
+ 'preferred': ''
+ }
+ if record['key_to_object'] not in [None, '']:
+ if '@' in record['key_to_object']:
+ return record
+
+ record['key_to_object'] = ''
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FILE:
+ record['file'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['format'] = gchild.get_value()
+ for ggchild in gchild.get_child_elements():
+ if ggchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['type'] = ggchild.get_value()
+ continue
+ continue
+
+ if child.get_tag() in MEDIA_TAGS:
+ record[MEDIA_TAGS[child.get_tag()]] = child.get_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/note_structure.html b/docs/gedcom/subparsers/note_structure.html
new file mode 100644
index 0000000..55c2594
--- /dev/null
+++ b/docs/gedcom/subparsers/note_structure.html
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+gedcom.subparsers.note_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.note_structure
+
+
+
Substructure parser for the NOTE_STRUCTURE record identified by the
+GEDCOM_TAG_NOTE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the NOTE_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_NOTE` tag.
+"""
+
+
+def note_structure(element):
+ """Parse and extract a NOTE_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'key_to_note': element.get_value(),
+ 'note': ''
+ }
+ if record['key_to_note'] not in [None, '']:
+ if '@' in record['key_to_note']:
+ return record
+ record['key_to_note'] = ''
+ record['note'] = element.get_multi_line_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def note_structure(element)
+
+
+
Parse and extract a NOTE_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def note_structure(element):
+ """Parse and extract a NOTE_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'key_to_note': element.get_value(),
+ 'note': ''
+ }
+ if record['key_to_note'] not in [None, '']:
+ if '@' in record['key_to_note']:
+ return record
+ record['key_to_note'] = ''
+ record['note'] = element.get_multi_line_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/personal_name_pieces.html b/docs/gedcom/subparsers/personal_name_pieces.html
new file mode 100644
index 0000000..41fe7f6
--- /dev/null
+++ b/docs/gedcom/subparsers/personal_name_pieces.html
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+gedcom.subparsers.personal_name_pieces API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.personal_name_pieces
+
+
+
Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
+referenced in place in part of another structure there is no identifier tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
+referenced in place in part of another structure there is no identifier tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+from gedcom.subparsers.source_citation import source_citation
+
+NAME_TAGS = {
+ tags.GEDCOM_TAG_NAME_PREFIX: 'prefix',
+ tags.GEDCOM_TAG_GIVEN_NAME: 'given',
+ tags.GEDCOM_TAG_NICKNAME: 'nick',
+ tags.GEDCOM_TAG_SURN_PREFIX: 'surname_prefix',
+ tags.GEDCOM_TAG_SURNAME: 'surname',
+ tags.GEDCOM_TAG_NAME_SUFFIX: 'suffix',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME: 'rufname'
+}
+
+
+def personal_name_pieces(element):
+ """Parse and extract PERSONAL_NAME_PIECES
+ :rtype: dict
+ """
+ record = {
+ 'prefix': '',
+ 'given': '',
+ 'nick': '',
+ 'surname_prefix': '',
+ 'surname': '',
+ 'suffix': '',
+ 'rufname': '',
+ 'notes': [],
+ 'citations': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() in NAME_TAGS:
+ record[NAME_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def personal_name_pieces(element)
+
+
+
Parse and extract PERSONAL_NAME_PIECES
+:rtype: dict
+
+
+Expand source code
+
+
def personal_name_pieces(element):
+ """Parse and extract PERSONAL_NAME_PIECES
+ :rtype: dict
+ """
+ record = {
+ 'prefix': '',
+ 'given': '',
+ 'nick': '',
+ 'surname_prefix': '',
+ 'surname': '',
+ 'suffix': '',
+ 'rufname': '',
+ 'notes': [],
+ 'citations': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() in NAME_TAGS:
+ record[NAME_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_SOURCE:
+ record['citations'].append(source_citation(child))
+ continue
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/personal_name_structure.html b/docs/gedcom/subparsers/personal_name_structure.html
new file mode 100644
index 0000000..e2f8ab0
--- /dev/null
+++ b/docs/gedcom/subparsers/personal_name_structure.html
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+gedcom.subparsers.personal_name_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.personal_name_structure
+
+
+
Substructure parser for the PERSONAL_NAME_STRUCTURE record identified by the
+GEDCOM_TAG_NAME tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the PERSONAL_NAME_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_NAME` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.personal_name_pieces import personal_name_pieces
+
+
+def extract_name(element):
+ """Parse and extract name record in a PERSONAL_NAME_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'name': '',
+ 'type': '',
+ 'pieces': {}
+ }
+ record['name'] = element.get_value()
+ record['pieces'] = personal_name_pieces(element)
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ return record
+
+
+def personal_name_structure(element):
+ """Parse and extract a PERSONAL_NAME_STRUCTURE
+ :rtype: dict
+ """
+ record = extract_name(element)
+ record['phonetic'] = []
+ record['romanized'] = []
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_PHONETIC:
+ record['phonetic'].append(extract_name(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED:
+ record['romanized'].append(extract_name(child))
+ continue
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def extract_name(element)
+
+
+
Parse and extract name record in a PERSONAL_NAME_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def extract_name(element):
+ """Parse and extract name record in a PERSONAL_NAME_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'name': '',
+ 'type': '',
+ 'pieces': {}
+ }
+ record['name'] = element.get_value()
+ record['pieces'] = personal_name_pieces(element)
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+ return record
+
+
+
+def personal_name_structure(element)
+
+
+
Parse and extract a PERSONAL_NAME_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def personal_name_structure(element):
+ """Parse and extract a PERSONAL_NAME_STRUCTURE
+ :rtype: dict
+ """
+ record = extract_name(element)
+ record['phonetic'] = []
+ record['romanized'] = []
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_PHONETIC:
+ record['phonetic'].append(extract_name(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED:
+ record['romanized'].append(extract_name(child))
+ continue
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/place_structure.html b/docs/gedcom/subparsers/place_structure.html
new file mode 100644
index 0000000..16ed810
--- /dev/null
+++ b/docs/gedcom/subparsers/place_structure.html
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+gedcom.subparsers.place_structure API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.place_structure
+
+
+
Substructure parser for the PLACE_STRUCTURE record identified by the
+GEDCOM_TAG_PLACE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the PLACE_STRUCTURE record identified by the
+`gedcom.tags.GEDCOM_TAG_PLACE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+
+def place_structure(element):
+ """Parse and extract a PLACE_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'name': element.get_value(),
+ 'hierarchy': '',
+ 'phonetic': [],
+ 'romanized': [],
+ 'latitude': '',
+ 'longitude': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['hierarchy'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PHONETIC:
+ subrecord = {
+ 'name': child.get_value(),
+ 'type': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ subrecord['type'] = gchild.get_value()
+ record['phonetic'].append(subrecord)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED:
+ subrecord = {
+ 'name': child.get_value(),
+ 'type': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ subrecord['type'] = gchild.get_value()
+ record['romanized'].append(subrecord)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MAP:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_LATITUDE:
+ record['latitude'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_LONGITUDE:
+ record['longitude'] = gchild.get_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def place_structure(element)
+
+
+
Parse and extract a PLACE_STRUCTURE
+:rtype: dict
+
+
+Expand source code
+
+
def place_structure(element):
+ """Parse and extract a PLACE_STRUCTURE
+ :rtype: dict
+ """
+ record = {
+ 'name': element.get_value(),
+ 'hierarchy': '',
+ 'phonetic': [],
+ 'romanized': [],
+ 'latitude': '',
+ 'longitude': '',
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_FORMAT:
+ record['hierarchy'] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_PHONETIC:
+ subrecord = {
+ 'name': child.get_value(),
+ 'type': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ subrecord['type'] = gchild.get_value()
+ record['phonetic'].append(subrecord)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED:
+ subrecord = {
+ 'name': child.get_value(),
+ 'type': ''
+ }
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_TYPE:
+ subrecord['type'] = gchild.get_value()
+ record['romanized'].append(subrecord)
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_MAP:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_LATITUDE:
+ record['latitude'] = gchild.get_value()
+ continue
+
+ if gchild.get_tag() == tags.GEDCOM_TAG_LONGITUDE:
+ record['longitude'] = gchild.get_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/source_citation.html b/docs/gedcom/subparsers/source_citation.html
new file mode 100644
index 0000000..b941351
--- /dev/null
+++ b/docs/gedcom/subparsers/source_citation.html
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+gedcom.subparsers.source_citation API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.source_citation
+
+
+
Substructure parser for the SOURCE_CITATION record identified by the
+GEDCOM_TAG_SOURCE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the SOURCE_CITATION record identified by the
+`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.multimedia_link import multimedia_link
+from gedcom.subparsers.note_structure import note_structure
+
+CITATION_TAGS = {
+ tags.GEDCOM_TAG_PAGE: 'page',
+ tags.GEDCOM_TAG_DATE: 'date',
+ tags.GEDCOM_TAG_QUALITY_OF_DATA: 'quality',
+ tags.GEDCOM_PROGRAM_DEFINED_TAG_APID: 'apid'
+}
+
+
+def source_citation(element):
+ """Parse and extract a SOURCE_CITATION
+ :rtype: dict
+ """
+ record = {
+ 'key_to_source': element.get_value(),
+ 'source': '',
+ 'page': '',
+ 'event': '',
+ 'role': '',
+ 'date': '',
+ 'text': '',
+ 'media': [],
+ 'notes': [],
+ 'quality': '',
+ 'apid': ''
+ }
+ if record['key_to_source'] not in [None, '']:
+ if '@' not in record['key_to_source']:
+ record['key_to_source'] = ''
+ record['source'] = element.get_multi_line_value()
+
+ for child in element.get_child_elements():
+ if child.get_tag() in CITATION_TAGS:
+ record[CITATION_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_EVENT:
+ record['event'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_ROLE:
+ record['role'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATA:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['date'] = gchild.get_value()
+ continue
+ if gchild.get_tag() == tags.GEDCOM_TAG_TEXT:
+ record['text'] = gchild.get_multi_line_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TEXT:
+ record['text'] = child.get_multi_line_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def source_citation(element)
+
+
+
Parse and extract a SOURCE_CITATION
+:rtype: dict
+
+
+Expand source code
+
+
def source_citation(element):
+ """Parse and extract a SOURCE_CITATION
+ :rtype: dict
+ """
+ record = {
+ 'key_to_source': element.get_value(),
+ 'source': '',
+ 'page': '',
+ 'event': '',
+ 'role': '',
+ 'date': '',
+ 'text': '',
+ 'media': [],
+ 'notes': [],
+ 'quality': '',
+ 'apid': ''
+ }
+ if record['key_to_source'] not in [None, '']:
+ if '@' not in record['key_to_source']:
+ record['key_to_source'] = ''
+ record['source'] = element.get_multi_line_value()
+
+ for child in element.get_child_elements():
+ if child.get_tag() in CITATION_TAGS:
+ record[CITATION_TAGS[child.get_tag()]] = child.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_EVENT:
+ record['event'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_ROLE:
+ record['role'] = gchild.get_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_DATA:
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ record['date'] = gchild.get_value()
+ continue
+ if gchild.get_tag() == tags.GEDCOM_TAG_TEXT:
+ record['text'] = gchild.get_multi_line_value()
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_OBJECT:
+ record['media'].append(multimedia_link(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_TEXT:
+ record['text'] = child.get_multi_line_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/source_repository_citation.html b/docs/gedcom/subparsers/source_repository_citation.html
new file mode 100644
index 0000000..6634433
--- /dev/null
+++ b/docs/gedcom/subparsers/source_repository_citation.html
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+gedcom.subparsers.source_repository_citation API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Substructure parser for the SOURCE_REPOSITORY_CITATION record identified by the
+GEDCOM_TAG_REPOSITORY tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the SOURCE_REPOSITORY_CITATION record identified by the
+`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+
+def source_repository_citation(element):
+ """Parse and extract a SOURCE_REPOSITORY_CITATION
+ :rtype: dict
+ """
+ record = {
+ 'key_to_repository': element.get_value(),
+ 'call_number': '',
+ 'media_type': '',
+ 'notes': []
+ }
+ if record['key_to_repository'] not in [None, '']:
+ if '@' not in record['key_to_repository']:
+ record['key_to_repository'] = ''
+
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CALL_NUMBER:
+ record['call_number'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media_type'] = gchild.get_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def source_repository_citation(element)
+
+
+
Parse and extract a SOURCE_REPOSITORY_CITATION
+:rtype: dict
+
+
+Expand source code
+
+
def source_repository_citation(element):
+ """Parse and extract a SOURCE_REPOSITORY_CITATION
+ :rtype: dict
+ """
+ record = {
+ 'key_to_repository': element.get_value(),
+ 'call_number': '',
+ 'media_type': '',
+ 'notes': []
+ }
+ if record['key_to_repository'] not in [None, '']:
+ if '@' not in record['key_to_repository']:
+ record['key_to_repository'] = ''
+
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+ continue
+
+ if child.get_tag() == tags.GEDCOM_TAG_CALL_NUMBER:
+ record['call_number'] = child.get_value()
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_MEDIA:
+ record['media_type'] = gchild.get_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/spouse_to_family_link.html b/docs/gedcom/subparsers/spouse_to_family_link.html
new file mode 100644
index 0000000..8adbb5e
--- /dev/null
+++ b/docs/gedcom/subparsers/spouse_to_family_link.html
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+gedcom.subparsers.spouse_to_family_link API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.spouse_to_family_link
+
+
+
Substructure parser for the SPOUSE_TO_FAMILY_LINK record identified by the
+GEDCOM_TAG_FAMILY_SPOUSE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Substructure parser for the SPOUSE_TO_FAMILY_LINK record identified by the
+`gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` tag.
+"""
+
+import gedcom.tags as tags
+from gedcom.subparsers.note_structure import note_structure
+
+
+def spouse_to_family_link(element):
+ """Parse and extract a SPOUSE_TO_FAMILY_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': element.get_value(),
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def spouse_to_family_link(element)
+
+
+
Parse and extract a SPOUSE_TO_FAMILY_LINK
+:rtype: dict
+
+
+Expand source code
+
+
def spouse_to_family_link(element):
+ """Parse and extract a SPOUSE_TO_FAMILY_LINK
+ :rtype: dict
+ """
+ record = {
+ 'key_to_family': element.get_value(),
+ 'notes': []
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_NOTE:
+ record['notes'].append(note_structure(child))
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/subparsers/user_reference_number.html b/docs/gedcom/subparsers/user_reference_number.html
new file mode 100644
index 0000000..4d5f0a9
--- /dev/null
+++ b/docs/gedcom/subparsers/user_reference_number.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+gedcom.subparsers.user_reference_number API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
Module gedcom.subparsers.user_reference_number
+
+
+
Parser for a USER_REFERENCE_NUMBER structure identified by the top level
+GEDCOM_TAG_REFERENCE tag.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""
+Parser for a USER_REFERENCE_NUMBER structure identified by the top level
+`gedcom.tags.GEDCOM_TAG_REFERENCE` tag.
+"""
+
+import gedcom.tags as tags
+
+
+def user_reference_number(element):
+ """Parse and extract USER_REFERENCE_NUMBER
+ :rtype: dict
+ """
+ record = {
+ 'reference': element.get_value(),
+ 'type': ''
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+
+ return record
+
+
+
+
+
+
+
+
Functions
+
+
+def user_reference_number(element)
+
+
+
Parse and extract USER_REFERENCE_NUMBER
+:rtype: dict
+
+
+Expand source code
+
+
def user_reference_number(element):
+ """Parse and extract USER_REFERENCE_NUMBER
+ :rtype: dict
+ """
+ record = {
+ 'reference': element.get_value(),
+ 'type': ''
+ }
+ for child in element.get_child_elements():
+ if child.get_tag() == tags.GEDCOM_TAG_TYPE:
+ record['type'] = child.get_value()
+
+ return record
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/tags.html b/docs/gedcom/tags.html
index f1c5491..dd9f85e 100644
--- a/docs/gedcom/tags.html
+++ b/docs/gedcom/tags.html
@@ -3,14 +3,14 @@
-
+
gedcom.tags API documentation
-
+
-
-
+
+
@@ -20,7 +20,7 @@
Module gedcom.tags
-
GEDCOM tags.
+
Standard GEDCOM tags and some common program defined extensions
Expand source code
@@ -29,6 +29,7 @@
Module gedcom.tags
# Python GEDCOM Parser
#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
# Copyright (C) 2016 Andreas Oberritter
@@ -53,63 +54,392 @@
Module gedcom.tags
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-GEDCOM tags.
+Standard GEDCOM tags and some common program defined extensions
"""
-GEDCOM_PROGRAM_DEFINED_TAG_MREL = "_MREL"
-"""Value: `_MREL`
+GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE = "_NAME"
+"""Value: `_NAME`
+
+Name of addresse in a `gedcom.tags.GEDCOM_TAG_ADDRESS` structure.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_ADMINISTRATIVE_ID = "_AIDN"
+"""Value: `_AIDN`
+
+Identifier for a location with the intention of an administrative authority,
+e.g. community identifier.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_APID = "_APID"
+"""Value: `_APID`
+
+Ancestry page identifier. For a citation, points to the page in a Ancestry
+database for the record supporting the citation. For a source record it
+points to the database as a whole.
+
+Ancestry.com Extension."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE = "_DCAUSE"
+"""Value: `_DCAUSE`
+
+Cause of death."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_DEGREE = "_DEG"
+"""Value: `_DEG`
+
+Degree or recognition of accomplishment received by an individual."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_DEMOGRAPHIC_DATA = "_DMGD"
+"""Value: `_DMGD`
+
+A number of ojects, during an ascertainment, e.g. the count of households.
-Relationship to a mother."""
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_FREL = "_FREL"
"""Value: `_FREL`
-Relationship to a father."""
+Type of relationship between child and the father in a family."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_FUNERAL = "_FUN"
+"""Value: `_FUN`
+
+Funeral for an individual."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT = "_GOV"
+"""Value: `_GOV`
+
+The official government id of the object in the Historical Place Register /
+Historic Gazeteer.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT_TYPE = "_GOVTYPE"
+"""Value: `_GOVTYPE`
+
+An integer positive number as defined in the GOV system.
+See http://gov.genealogy.net.net/type/list.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON = "_HME"
+"""Value: `_HME`
+
+Home person in the tree."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_LOCATION = "_LOC"
+"""Value: `_LOC`
+
+Location data record.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MAIDENHEAD = "_MAIDENHEAD"
+"""Value: `_MAIDENHEAD`
+
+The maidenhead code.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL = "_MDCL"
+"""Value: `_MDCL`
+
+Medical information about an individual."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MILITARY = "_MILT"
+"""Value: `_MILT`
+
+A military related event in the individuals life."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_MREL = "_MREL"
+"""Value: `_MREL`
+
+Type of relationship between child and the mother in a family."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_PHOTO = "_PHOTO"
+"""Value: `_PHOTO`
+
+Used by some programs to identify the primary multimedia object for an
+individual, the same as `gedcom.tags.GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY`."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_POSTAL_CODE = "_POST"
+"""Value: `_POST`
+
+The official zip code, called ADDRESS_POSTAL_CODE in the standard.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED = "_PREF"
+"""Value: `_PREF`
+
+Indicates a preferred spouse, child or parents."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY = "_PRIM"
+"""Value: `_PRIM`
+
+Primary multimedia object for an individual."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_SCHEMA = "_SCHEMA"
+"""Value: `_SCHEMA`
+
+Schema substructure extension to describe user defined tags.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME = "_RUFNAME"
+"""Value: `_RUFNAME`
+
+An official given name of a German individual used in legal documents.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_PROGRAM_DEFINED_TAG_UUID = "_UID"
+"""Value: `_UID`
+
+Universal identification number.
+
+5.5.1 GEDCOM-L Addendum."""
+
+GEDCOM_TAG_ABBREVIATION = "ABBR"
+"""Value: `ABBR`
+
+A short name of a title, description, or name."""
+
+GEDCOM_TAG_ADDRESS = "ADDR"
+"""Value: `ADDR`
+
+The contemporary place, usually required for postal purposes, of an individual,
+a submitter of information, a repository, a business, a school, or a company."""
+
+GEDCOM_TAG_ADDRESS1 = "ADR1"
+"""Value: `ADR1`
+
+The first line of an address."""
+
+GEDCOM_TAG_ADDRESS2 = "ADR2"
+"""Value: `ADR2`
+
+The second line of an address."""
+
+GEDCOM_TAG_ADDRESS3 = "ADR3"
+"""Value: `ADR3`
+
+The third line of an address."""
+
+GEDCOM_TAG_ADOPTION = "ADOP"
+"""Value: `ADOP`
+
+Pertaining to creation of a child-parent relationship that does not exist
+biologically."""
+
+GEDCOM_TAG_AFN = "AFN"
+"""Value: `AFN`
+
+Ancestral File Number, a unique permanent record file number of an individual
+record stored in Ancestral File."""
+
+GEDCOM_TAG_AGE = "AGE"
+"""Value: `AGE`
+
+The age of the individual at the time an event occurred, or the age listed in
+the document."""
+
+GEDCOM_TAG_AGENCY = "AGNC"
+"""Value: `AGNC`
+
+The institution or individual having authority and/or responsibility to manage
+or govern."""
+
+GEDCOM_TAG_ALIAS = "ALIA"
+"""Value: `ALIA`
+
+An indicator to link different record descriptions of a person who may be the
+same person."""
+
+GEDCOM_TAG_ANCESTORS = "ANCE"
+"""Value: `ANCE`
+
+Pertaining to forbearers of an individual."""
+
+GEDCOM_TAG_ANCES_INTEREST = "ANCI"
+"""Value: `ANCI`
+
+Indicates an interest in additional research for ancestors of this individual.
+(See also `gedcom.tags.GEDCOM_TAG_DESCENDANTS_INT`)"""
+
+GEDCOM_TAG_ANNULMENT = "ANUL"
+"""Value: `ANUL`
+
+Declaring a marriage void from the beginning (never existed)."""
+
+GEDCOM_TAG_ASSOCIATES = "ASSO"
+"""Value: `ASSO`
+
+An indicator to link friends, neighbors, relatives, or associates of an
+individual."""
+
+GEDCOM_TAG_AUTHOR = "AUTH"
+"""Value: `AUTH`
+
+The name of the individual who created or compiled information."""
+
+GEDCOM_TAG_BAPTISM_LDS = "BAPL"
+"""Value: `BAPL`
+
+The event of baptism performed at age eight or later by priesthood authority
+of the LDS Church. (See also `gedcom.tags.GEDCOM_TAG_BAPTISM`)"""
+
+GEDCOM_TAG_BAPTISM = "BAPM"
+"""Value: `BAPM`
+
+The event of baptism (not LDS), performed in infancy or later."""
+
+GEDCOM_TAG_BAR_MITZVAH = "BARM"
+"""Value: `BARM`
+
+The ceremonial event held when a Jewish boy reaches age 13."""
+
+GEDCOM_TAG_BAS_MITZVAH = "BASM"
+"""Value: `BASM`
+
+The ceremonial event held when a Jewish girl reaches age 13, also known as
+Bat Mitzvah."""
GEDCOM_TAG_BIRTH = "BIRT"
"""Value: `BIRT`
The event of entering into life."""
+GEDCOM_TAG_BLESSING = "BLES"
+"""Value: `BLES`
+
+A religious event of bestowing divine care or intercession. Sometimes given
+in connection with a naming ceremony."""
+
GEDCOM_TAG_BURIAL = "BURI"
"""Value: `BURI`
The event of the proper disposing of the mortal remains of a deceased person."""
+GEDCOM_TAG_CALL_NUMBER = "CALN"
+"""Value: `CALN`
+
+The number used by a repository to identify the specific items in its
+collections."""
+
+GEDCOM_TAG_CASTE = "CAST"
+"""Value: `CAST`
+
+The name of an individual's rank or status in society, based on racial or
+religious differences, or differences in wealth, inherited rank, profession,
+occupation, etc."""
+
+GEDCOM_TAG_CAUSE = "CAUSE"
+"""Value: `CAUS`
+
+A description of the cause of the associated event or fact, such as the cause
+of death."""
+
GEDCOM_TAG_CENSUS = "CENS"
"""Value: `CENS`.
-The event of the periodic count of the population for a designated locality, such as a national or state Census."""
+The event of the periodic count of the population for a designated locality,
+such as a national or state Census."""
GEDCOM_TAG_CHANGE = "CHAN"
"""Value: `CHAN`
Indicates a change, correction, or modification. Typically used in connection
-with a `gedcom.tags.GEDCOM_TAG_DATE` to specify when a change in information occurred."""
+with a `gedcom.tags.GEDCOM_TAG_DATE` to specify when a change in information
+occurred."""
+
+GEDCOM_TAG_CHARACTER = "CHAR"
+"""Value: `CHAR`
+
+An indicator of the character set used in writing this automated information."""
GEDCOM_TAG_CHILD = "CHIL"
"""Value: `CHIL`
The natural, adopted, or sealed (LDS) child of a father and a mother."""
+GEDCOM_TAG_CHRISTENING = "CHR"
+"""Value: `CHR`
+
+The religious event (not LDS) of baptizing and/or naming a child."""
+
+GEDCOM_TAG_ADULT_CHRISTENING = "CHRA"
+"""Value: `CHRA`
+
+The religious event (not LDS) of baptizing and/or naming an adult person."""
+
+GEDCOM_TAG_CITY = "CITY"
+"""Value: `CITY`
+
+A lower level jurisdictional unit. Normally an incorporated municipal unit."""
+
GEDCOM_TAG_CONCATENATION = "CONC"
"""Value: `CONC`
-An indicator that additional data belongs to the superior value. The information from the `CONC` value is to
-be connected to the value of the superior preceding line without a space and without a carriage return and/or
-new line character. Values that are split for a `CONC` tag must always be split at a non-space. If the value is
-split on a space the space will be lost when concatenation takes place. This is because of the treatment that
-spaces get as a GEDCOM delimiter, many GEDCOM values are trimmed of trailing spaces and some systems look for
-the first non-space starting after the tag to determine the beginning of the value."""
+An indicator that additional data belongs to the superior value. The information
+from the `CONC` value is to be connected to the value of the superior preceding
+line without a space and without a carriage return and/or new line character.
+Values that are split for a `CONC` tag must always be split at a non-space. If
+the value is split on a space the space will be lost when concatenation takes
+place. This is because of the treatment that spaces get as a GEDCOM delimiter,
+many GEDCOM values are trimmed of trailing spaces and some systems look for
+the first non-space starting after the tag to determine the beginning of the
+value."""
+
+GEDCOM_TAG_CONFIRMATION = "CONF"
+"""Value: `CONF`
+
+The religious event (not LDS) of conferring the gift of the Holy Ghost and,
+among protestants, full church membership."""
+
+GEDCOM_TAG_CONFIRMATION_L = "CONL"
+"""Value: `CONL`
+
+The religious event by which a person receives membership in the LDS Church."""
GEDCOM_TAG_CONTINUED = "CONT"
"""Value: `CONT`
-An indicator that additional data belongs to the superior value. The information from the `CONT` value is to be
-connected to the value of the superior preceding line with a carriage return and/or new line character.
-Leading spaces could be important to the formatting of the resultant text. When importing values from `CONT` lines
-the reader should assume only one delimiter character following the `CONT` tag. Assume that the rest of the leading
-spaces are to be a part of the value."""
+An indicator that additional data belongs to the superior value. The information
+from the `CONT` value is to be connected to the value of the superior preceding
+line with a carriage return and/or new line character. Leading spaces could be
+important to the formatting of the resultant text. When importing values from
+`CONT` lines the reader should assume only one delimiter character following
+the `CONT` tag. Assume that the rest of the leading spaces are to be a part
+of the value."""
+
+GEDCOM_TAG_COPYRIGHT = "COPR"
+"""Value: `COPR`
+
+A statement that accompanies data to protect it from unlawful duplication
+and distribution."""
+
+GEDCOM_TAG_CORPORATE = "CORP"
+"""Value: `CORP`
+
+A name of an institution, agency, corporation, or company."""
+
+GEDCOM_TAG_CREMATION = "CREM"
+"""Value: `CREM`
+
+Disposal of the remains of a person's body by fire."""
+
+GEDCOM_TAG_COUNTRY = "CTRY"
+"""Value: `CTRY`
+
+The name or code of a country."""
+
+GEDCOM_TAG_DATA = "DATA"
+"""Value: `DATA`
+
+Pertaining to stored automation information."""
GEDCOM_TAG_DATE = "DATE"
"""Value: `DATE`
@@ -121,93 +451,542 @@
Module gedcom.tags
The event when mortal life terminates."""
+GEDCOM_TAG_DESCENDANTS = "DESC"
+"""Value: `DESC`
+
+Pertaining to offspring of an individual."""
+
+GEDCOM_TAG_DESCENDANTS_INT = "DESI"
+"""Value: `DESI`
+
+Indicates an interest in research to identify additional descendants of this
+individual. (See also `gedcom.tags.GEDCOM_TAG_ANCES_INTEREST`)"""
+
+GEDCOM_TAG_DESTINATION = "DEST"
+"""Value: `DEST`
+
+A system receiving data."""
+
+GEDCOM_TAG_DIVORCE = "DIV"
+"""Value: `DIV`
+
+The event of disolving a marriage through civil action."""
+
+GEDCOM_TAG_DIVORCE_FILED = "DIVF"
+"""Value: `DIVF`
+
+An event of filing for a divorce by a spouse."""
+
+GEDCOM_TAG_PHY_DESCRIPTION = "DSCR"
+"""Value: `DSCR`
+
+The physical characteristics of a person, place, or thing."""
+
+GEDCOM_TAG_EDUCATION = "EDUC"
+"""Value: `EDUC`
+
+Indicator of a level of education attained."""
+
+GEDCOM_TAG_EMAIL = "EMAIL"
+"""Value: `EMAIL`
+
+An electronic address that can be used for contact such as an email address."""
+
+GEDCOM_TAG_EMIGRATION = "EMIG"
+"""Value: `EMIG`
+
+An event of leaving one's homeland with the intent of residing elsewhere."""
+
+GEDCOM_TAG_ENDOWMENT = "ENDL"
+"""Value: `ENDL`
+
+A religious event where an endowment ordinance for an individual was performed
+by priesthood authority in an LDS temple."""
+
+GEDCOM_TAG_ENGAGEMENT = "ENGA"
+"""Value: `ENGA`
+
+An event of recording or announcing an agreement between two people to become
+married."""
+
+GEDCOM_TAG_EVENT = "EVEN"
+"""Value: `EVEN`
+
+A noteworthy happening related to an individual, a group, or an organization."""
+
+GEDCOM_TAG_FACT = "FACT"
+"""Value: `FACT`
+
+Pertaining to a noteworthy attribute or fact concerning an individual, a group,
+or an organization. A `FACT` structure is usually qualified or classified by a
+subordinate use of the `gedcom.tags.GEDCOM_TAG_TYPE` tag."""
+
GEDCOM_TAG_FAMILY = "FAM"
"""Value: `FAM`.
-Identifies a legal, common law, or other customary relationship of man and woman and their children,
-if any, or a family created by virtue of the birth of a child to its biological father and mother."""
+Identifies a legal, common law, or other customary relationship of man and woman
+and their children, if any, or a family created by virtue of the birth of a
+child to its biological father and mother."""
GEDCOM_TAG_FAMILY_CHILD = "FAMC"
"""Value: `FAMC`
Identifies the family in which an individual appears as a child."""
+GEDCOM_TAG_FAMILY_FILE = "FAMF"
+"""Value: `FAMF`
+
+Pertaining to, or the name of, a family file. Names stored in a file that are
+assigned to a family for doing temple ordinance work."""
+
GEDCOM_TAG_FAMILY_SPOUSE = "FAMS"
"""Value: `FAMS`
Identifies the family in which an individual appears as a spouse."""
+GEDCOM_TAG_FAX = "FAX"
+"""Value: `FAX`
+
+A FAX telephone number appropriate for sending data facsimiles."""
+
+GEDCOM_TAG_FIRST_COMMUNION = "FCOM"
+"""Value: `FCOM`
+
+A religious rite, the first act of sharing in the Lord's supper as part of
+church worship."""
+
GEDCOM_TAG_FILE = "FILE"
"""Value: `FILE`
-An information storage place that is ordered and arranged for preservation and reference."""
+An information storage place that is ordered and arranged for preservation and
+reference."""
+
+GEDCOM_TAG_PHONETIC = "FONE"
+"""Value: `FONE`
+
+A phonetic variation of a superior text string."""
+
+GEDCOM_TAG_FORMAT = "FORM"
+"""Value: `FORM`
+
+An assigned name given to a consistent format in which information can be
+conveyed."""
+
+GEDCOM_TAG_GEDCOM = "GEDC"
+"""Value: `GEDC`
+
+Information about the use of GEDCOM in a transmission."""
GEDCOM_TAG_GIVEN_NAME = "GIVN"
"""Value: `GIVN`
A given or earned name used for official identification of a person."""
+GEDCOM_TAG_GRADUATION = "GRAD"
+"""Value: `GRAD`
+
+An event of awarding educational diplomas or degrees to individuals."""
+
+GEDCOM_TAG_HEADER = "HEAD"
+"""Value: `HEAD`
+
+Identifies information pertaining to an entire GEDCOM transmission."""
+
GEDCOM_TAG_HUSBAND = "HUSB"
"""Value: `HUSB`
An individual in the family role of a married man or father."""
+GEDCOM_TAG_IDENT_NUMBER = "IDNO"
+"""Value: `IDNO`
+
+A number assigned to identify a person within some significant external system."""
+
+GEDCOM_TAG_IMMIGRATION = "IMMI"
+"""Value: `IMMI`
+
+An event of entering into a new locality witht he intent of residing there."""
+
GEDCOM_TAG_INDIVIDUAL = "INDI"
"""Value: `INDI`
A person."""
+GEDCOM_TAG_LANGUAGE = "LANG"
+"""Value: `LANG`
+
+The name of the language used in a communication or transmission of information."""
+
+GEDCOM_TAG_LATITUDE = "LATI"
+"""Value: `LATI`
+
+A value indicating a coordinate position on a line, plane, or space."""
+
+GEDCOM_TAG_LEGATEE = "LEGA"
+"""Value: `LEGA`
+
+A role of an individual acting as a person receiving a bequest or legal devise."""
+
+GEDCOM_TAG_LONGITUDE = "LONG"
+"""Value: `LONG`
+
+A value indicating a coordinate position on a line, plane, or space."""
+
+GEDCOM_TAG_MAP = "MAP"
+"""Value: `MAP`
+
+Pertains to a representation of measurements usually presented in a graphical
+form."""
+
+GEDCOM_TAG_MARRIAGE_BANN = "MARB"
+"""Value: `MARB`.
+
+An event of an official public notice given that two people intend to marry."""
+
+GEDCOM_TAG_MARR_CONTRACT = "MARC"
+"""Value: `MARC`.
+
+An event of recording a formal agreement of marriage, including the prenuptial
+agreement in which marriage partners reach agreement about the property rights
+of one or both, securing property to their children."""
+
+GEDCOM_TAG_MARR_LICENSE = "MARL"
+"""Value: `MARL`.
+
+An event of obtaining a legal license to marry."""
+
GEDCOM_TAG_MARRIAGE = "MARR"
"""Value: `MARR`.
-A legal, common-law, or customary event of creating a family unit of a man and a woman as husband and wife."""
+A legal, common-law, or customary event of creating a family unit of a man and
+a woman as husband and wife."""
+
+GEDCOM_TAG_MARR_SETTLEMENT = "MARS"
+"""Value: `MARS`.
+
+An event of creating an agreement between two people contemplating marriage,
+at which time they agree to release or modify property rights that would
+otherwise arise from the marriage."""
+
+GEDCOM_TAG_MEDIA = "MEDI"
+"""Value: `MEDI`.
+
+Identifies information about the media or having to do with the medium in which
+information is stored."""
GEDCOM_TAG_NAME = "NAME"
"""Value: `NAME`.
-A word or combination of words used to help identify an individual, title, or other item.
-More than one NAME line should be used for people who were known by multiple names."""
+A word or combination of words used to help identify an individual, title, or
+other item. More than one `NAME` line should be used for people who were known
+by multiple names."""
+
+GEDCOM_TAG_NATIONALITY = "NATI"
+"""Value: `NATI`
+
+The national heritage of an individual."""
+
+GEDCOM_TAG_NATURALIZATION = "NATU"
+"""Value: `NATU`
+
+The event of obtaining citizenship."""
+
+GEDCOM_TAG_CHILDREN_COUNT = "NCHI"
+"""Value: `NCHI`
+
+The number of children that this person is known to be the parent of (all
+marriages) when subordinate to an individual, or that belong to this family
+when subordinate to a `gedcom.tags.GEDCOM_TAG_FAMILY` record."""
+
+GEDCOM_TAG_NICKNAME = "NICK"
+"""Value: `NICK`
+
+A descriptive or familiar that is used instead of, or in addition to, one's
+proper name."""
+
+GEDCOM_TAG_MARRIAGE_COUNT = "NMR"
+"""Value: `NMR`
+
+The number of times this person has participated in a family as a spouse or
+parent."""
+
+GEDCOM_TAG_NOTE = "NOTE"
+"""Value: `NOTE`
+
+Additional information provided by the submitter for understanding the
+enclosing data."""
+
+GEDCOM_TAG_NAME_PREFIX = "NPFX"
+"""Value: `NPFX`
+
+Text which appears on a name line before the given and surname parts of a name.
+i.e. ( Lt. Cmndr. ) Joseph /Allen/ jr. In this example Lt. Cmndr. is considered
+as the name prefix portion."""
+
+GEDCOM_TAG_NAME_SUFFIX = "NSFX"
+"""Value: `NSFX`
+
+Text which appears on a name line after or behind the given and surname parts
+of a name. i.e. Lt. Cmndr. Joseph /Allen/ ( jr. ) In this example jr. is
+considered as the name suffix portion."""
GEDCOM_TAG_OBJECT = "OBJE"
"""Value: `OBJE`
-Pertaining to a grouping of attributes used in describing something. Usually referring to the data required
-to represent a multimedia object, such an audio recording, a photograph of a person, or an image of a document."""
+Pertaining to a grouping of attributes used in describing something. Usually
+referring to the data required to represent a multimedia object, such an audio
+recording, a photograph of a person, or an image of a document."""
GEDCOM_TAG_OCCUPATION = "OCCU"
"""Value: `OCCU`
The type of work or profession of an individual."""
+GEDCOM_TAG_ORDINANCE = "ORDI"
+"""Value: `ORDI`
+
+Pertaining to a religious ordinance in general."""
+
+GEDCOM_TAG_ORDINATION = "ORDN"
+"""Value: `ORDN`
+
+A religious event of receiving authority to act in religious matters."""
+
+GEDCOM_TAG_PAGE = "PAGE"
+"""Value: `PAGE`
+
+A number or description to identify where information can be found in a
+referenced work."""
+
+GEDCOM_TAG_PEDIGREE = "PEDI"
+"""Value: `PEDI`
+
+Information pertaining to an individual to parent lineage chart."""
+
+GEDCOM_TAG_PHONE = "PHON"
+"""Value: `PHON`
+
+A unique number assigned to access a specific telephone."""
+
GEDCOM_TAG_PLACE = "PLAC"
"""Value: `PLAC`
A jurisdictional name to identify the place or location of an event."""
+GEDCOM_TAG_POSTAL_CODE = "POST"
+"""Value: `POST`
+
+A code used by a postal service to identify an area to facilitate mail handling."""
+
GEDCOM_TAG_PRIVATE = "PRIV"
"""Value: `PRIV`
Flag for private address or event."""
+GEDCOM_TAG_PROBATE = "PROB"
+"""Value: `PROB`
+
+An event of judicial determination of the validity of a will. May indicate
+several related court activities over several dates."""
+
+GEDCOM_TAG_PROPERTY = "PROP"
+"""Value: `PROP`
+
+Pertaining to possessions such as real estate or other property of interest."""
+
+GEDCOM_TAG_PUBLICATION = "PUBL"
+"""Value: `PUBL`
+
+Refers to when and/or were a work was published or created."""
+
+GEDCOM_TAG_QUALITY_OF_DATA = "QUAY"
+"""Value: `QUAY`
+
+An assessment of the certainty of the evidence to support the conclusion drawn
+from evidence."""
+
+GEDCOM_TAG_REFERENCE = "REFN"
+"""Value: `REFN`
+
+A description or number used to identify an item for filing, storage, or other
+reference purposes."""
+
+GEDCOM_TAG_RELATIONSHIP = "RELA"
+"""Value: `RELA`
+
+A relationship value between the indicated contexts."""
+
+GEDCOM_TAG_RELIGION = "RELI"
+"""Value: `RELI`
+
+A religious denomination to which a person is affiliated or for which a record
+applies."""
+
+GEDCOM_TAG_REPOSITORY = "REPO"
+"""Value: `REPO`
+
+An institution or person that has the specified item as part of their
+collection(s)."""
+
+GEDCOM_TAG_RESIDENCE = "RESI"
+"""Value: `RESI`
+
+The act of dwelling at a place for a period of time."""
+
+GEDCOM_TAG_RESTRICTION = "RESN"
+"""Value: `RESN`
+
+A processing indicator signifying access to information has been denied or
+otherwise restricted."""
+
+GEDCOM_TAG_RETIREMENT = "RETI"
+"""Value: `RETI`
+
+An event of exiting an occupational relationship with an employer after a
+qualifying time period."""
+
+GEDCOM_TAG_REC_FILE_NUMBER = "RFN"
+"""Value: `RFN`
+
+A permanent number assigned to a record that uniquely identifies it within a
+known file."""
+
+GEDCOM_TAG_REC_ID_NUMBER = "RIN"
+"""Value: `RIN`
+
+A number assigned to a record by an originating automated system that can be
+used by a receiving system to report results pertaining to that record."""
+
+GEDCOM_TAG_ROLE = "ROLE"
+"""Value: `ROLE`
+
+A name given to a role played by an individual in connection with an event."""
+
+GEDCOM_TAG_ROMANIZED = "ROMN"
+"""Value: `ROMN`
+
+A romanized variation of a superior text string."""
+
GEDCOM_TAG_SEX = "SEX"
"""Value: `SEX`
Indicates the sex of an individual--male or female."""
+GEDCOM_TAG_SEALING_CHILD = "SLGC"
+"""Value: `SLGC`
+
+A religious event pertaining to the sealing of a child to his or her parents in
+an LDS temple ceremony."""
+
+GEDCOM_TAG_SEALING_SPOUSE = "SLGS"
+"""Value: `SLGS`
+
+A religious event pertaining to the sealing of a husband and wife in an LDS
+temple ceremony."""
+
GEDCOM_TAG_SOURCE = "SOUR"
"""Value: `SOUR`
The initial or original material from which information was obtained."""
-GEDCOM_TAG_SURNAME = "SURN"
-"""Value: `SURN`
+GEDCOM_TAG_SURN_PREFIX = "SPFX"
+"""Value: `SPFX`
+
+A name piece used as a non-indexing pre-part of a surname."""
+
+GEDCOM_TAG_SOC_SEC_NUMBER = "SSN"
+"""Value: `SSN`
+
+A number assigned by the United States Social Security Administration. Used for
+tax identification purposes."""
+
+GEDCOM_TAG_STATE = "STAE"
+"""Value: `STAE`
+
+A geographical division of a larger jurisdictional area, such as a State within
+the United States of America."""
+
+GEDCOM_TAG_STATUS = "STAT"
+"""Value: `STAT`
+
+An assessment of the state or condition of something."""
+
+GEDCOM_TAG_SUBMITTER = "SUBM"
+"""Value: `SUBM`
+
+An individual or organization who contributes genealogical data to a file or
+transfers it to someone else."""
+
+GEDCOM_TAG_SUBMISSION = "SUBN"
+"""Value: `SUBN`
+
+Pertains to a collection of data issued for processing."""
+
+GEDCOM_TAG_SURNAME = "SURN"
+"""Value: `SURN`
A family name passed on or used by members of a family."""
+GEDCOM_TAG_TEMPLE = "TEMP"
+"""Value: `TEMP`
+
+The name or code that represents the name a temple of the LDS Church."""
+
+GEDCOM_TAG_TEXT = "TEXT"
+"""Value: `TEXT`
+
+The exact wording found in an original source document."""
+
+GEDCOM_TAG_TIME = "TIME"
+"""Value: `TIME`
+
+A time value in a 24-hour clock format, including hours, minutes, and optional
+seconds, separated by a colon (:). Fractions of seconds are shown in decimal
+notation."""
+
+GEDCOM_TAG_TITLE = "TITL"
+"""Value: `TITL`
+
+A description of a specific writing or other work, such as the title of a book
+when used in a source context, or a formal designation used by an individual
+in connection with positions of royalty or other social status, such as Grand
+Duke."""
+
+GEDCOM_TAG_TRAILER = "TRLR"
+"""Value: `TRLR`
+
+At level 0, specifies the end of a GEDCOM transmission."""
+
+GEDCOM_TAG_TYPE = "TYPE"
+"""Value: `TYPE`
+
+A further qualification to the meaning of the associated superior tag. The value
+does not have any computer processing reliability. It is more in the form of a
+short one or two word note that should be displayed any time the associated data
+is displayed."""
+
+GEDCOM_TAG_VERSION = "VERS"
+"""Value: `VERS`
+
+Indicates which version of a product, item, or publication is being used or
+referenced."""
+
GEDCOM_TAG_WIFE = "WIFE"
"""Value: `WIFE`
-An individual in the role as a mother and/or married woman."""
+An individual in the role as a mother and/or married woman."""
+
+GEDCOM_TAG_WWW = "WWW"
+"""Value: `WWW`
+
+World Wide Web home page."""
+
+GEDCOM_TAG_WILL = "WILL"
+"""Value: `WILL`
+
+A legal document treated as an event, by which a person disposes of his or her
+estate, to take effect after death. The event date is the date the will was
+signed while the person was alive. (See also `gedcom.tags.GEDCOM_TAG_PROBATE`)"""
Identifier for a location with the intention of an administrative authority,
+e.g. community identifier.
+
5.5.1 GEDCOM-L Addendum.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_APID
+
+
Value: _APID
+
Ancestry page identifier. For a citation, points to the page in a Ancestry
+database for the record supporting the citation. For a source record it
+points to the database as a whole.
+
Ancestry.com Extension.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE
+
+
Value: _DCAUSE
+
Cause of death.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_DEGREE
+
+
Value: _DEG
+
Degree or recognition of accomplishment received by an individual.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_DEMOGRAPHIC_DATA
+
+
Value: _DMGD
+
A number of ojects, during an ascertainment, e.g. the count of households.
+
5.5.1 GEDCOM-L Addendum.
+
var GEDCOM_PROGRAM_DEFINED_TAG_FREL
-
Value: _FREL
-
Relationship to a father.
+
Value: _FREL
+
Type of relationship between child and the father in a family.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_FUNERAL
+
+
Value: _FUN
+
Funeral for an individual.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT
+
+
Value: _GOV
+
The official government id of the object in the Historical Place Register /
+Historic Gazeteer.
The official zip code, called ADDRESS_POSTAL_CODE in the standard.
+
5.5.1 GEDCOM-L Addendum.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED
+
+
Value: _PREF
+
Indicates a preferred spouse, child or parents.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY
+
+
Value: _PRIM
+
Primary multimedia object for an individual.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME
+
+
Value: _RUFNAME
+
An official given name of a German individual used in legal documents.
+
5.5.1 GEDCOM-L Addendum.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_SCHEMA
+
+
Value: _SCHEMA
+
Schema substructure extension to describe user defined tags.
+
5.5.1 GEDCOM-L Addendum.
+
+
var GEDCOM_PROGRAM_DEFINED_TAG_UUID
+
+
Value: _UID
+
Universal identification number.
+
5.5.1 GEDCOM-L Addendum.
+
+
var GEDCOM_TAG_ABBREVIATION
+
+
Value: ABBR
+
A short name of a title, description, or name.
+
+
var GEDCOM_TAG_ADDRESS
+
+
Value: ADDR
+
The contemporary place, usually required for postal purposes, of an individual,
+a submitter of information, a repository, a business, a school, or a company.
+
+
var GEDCOM_TAG_ADDRESS1
+
+
Value: ADR1
+
The first line of an address.
+
+
var GEDCOM_TAG_ADDRESS2
+
+
Value: ADR2
+
The second line of an address.
+
+
var GEDCOM_TAG_ADDRESS3
+
+
Value: ADR3
+
The third line of an address.
+
+
var GEDCOM_TAG_ADOPTION
+
+
Value: ADOP
+
Pertaining to creation of a child-parent relationship that does not exist
+biologically.
+
+
var GEDCOM_TAG_ADULT_CHRISTENING
+
+
Value: CHRA
+
The religious event (not LDS) of baptizing and/or naming an adult person.
+
+
var GEDCOM_TAG_AFN
+
+
Value: AFN
+
Ancestral File Number, a unique permanent record file number of an individual
+record stored in Ancestral File.
+
+
var GEDCOM_TAG_AGE
+
+
Value: AGE
+
The age of the individual at the time an event occurred, or the age listed in
+the document.
+
+
var GEDCOM_TAG_AGENCY
+
+
Value: AGNC
+
The institution or individual having authority and/or responsibility to manage
+or govern.
+
+
var GEDCOM_TAG_ALIAS
+
+
Value: ALIA
+
An indicator to link different record descriptions of a person who may be the
+same person.
+
+
var GEDCOM_TAG_ANCESTORS
+
+
Value: ANCE
+
Pertaining to forbearers of an individual.
+
+
var GEDCOM_TAG_ANCES_INTEREST
+
+
Value: ANCI
+
Indicates an interest in additional research for ancestors of this individual.
+(See also GEDCOM_TAG_DESCENDANTS_INT)
+
+
var GEDCOM_TAG_ANNULMENT
+
+
Value: ANUL
+
Declaring a marriage void from the beginning (never existed).
+
+
var GEDCOM_TAG_ASSOCIATES
+
+
Value: ASSO
+
An indicator to link friends, neighbors, relatives, or associates of an
+individual.
+
+
var GEDCOM_TAG_AUTHOR
+
+
Value: AUTH
+
The name of the individual who created or compiled information.
+
+
var GEDCOM_TAG_BAPTISM
+
+
Value: BAPM
+
The event of baptism (not LDS), performed in infancy or later.
+
+
var GEDCOM_TAG_BAPTISM_LDS
+
+
Value: BAPL
+
The event of baptism performed at age eight or later by priesthood authority
+of the LDS Church. (See also GEDCOM_TAG_BAPTISM)
+
+
var GEDCOM_TAG_BAR_MITZVAH
+
+
Value: BARM
+
The ceremonial event held when a Jewish boy reaches age 13.
+
+
var GEDCOM_TAG_BAS_MITZVAH
+
+
Value: BASM
+
The ceremonial event held when a Jewish girl reaches age 13, also known as
+Bat Mitzvah.
var GEDCOM_TAG_BIRTH
-
Value: BIRT
-
The event of entering into life.
+
Value: BIRT
+
The event of entering into life.
+
+
var GEDCOM_TAG_BLESSING
+
+
Value: BLES
+
A religious event of bestowing divine care or intercession. Sometimes given
+in connection with a naming ceremony.
var GEDCOM_TAG_BURIAL
-
Value: BURI
-
The event of the proper disposing of the mortal remains of a deceased person.
+
Value: BURI
+
The event of the proper disposing of the mortal remains of a deceased person.
+
+
var GEDCOM_TAG_CALL_NUMBER
+
+
Value: CALN
+
The number used by a repository to identify the specific items in its
+collections.
+
+
var GEDCOM_TAG_CASTE
+
+
Value: CAST
+
The name of an individual's rank or status in society, based on racial or
+religious differences, or differences in wealth, inherited rank, profession,
+occupation, etc.
+
+
var GEDCOM_TAG_CAUSE
+
+
Value: CAUS
+
A description of the cause of the associated event or fact, such as the cause
+of death.
var GEDCOM_TAG_CENSUS
-
Value: CENS.
-
The event of the periodic count of the population for a designated locality, such as a national or state Census.
+
Value: CENS.
+
The event of the periodic count of the population for a designated locality,
+such as a national or state Census.
var GEDCOM_TAG_CHANGE
-
Value: CHAN
+
Value: CHAN
Indicates a change, correction, or modification. Typically used in connection
-with a GEDCOM_TAG_DATE to specify when a change in information occurred.
+with a GEDCOM_TAG_DATE to specify when a change in information
+occurred.
+
+
var GEDCOM_TAG_CHARACTER
+
+
Value: CHAR
+
An indicator of the character set used in writing this automated information.
var GEDCOM_TAG_CHILD
-
Value: CHIL
-
The natural, adopted, or sealed (LDS) child of a father and a mother.
+
Value: CHIL
+
The natural, adopted, or sealed (LDS) child of a father and a mother.
+
+
var GEDCOM_TAG_CHILDREN_COUNT
+
+
Value: NCHI
+
The number of children that this person is known to be the parent of (all
+marriages) when subordinate to an individual, or that belong to this family
+when subordinate to a GEDCOM_TAG_FAMILY record.
+
+
var GEDCOM_TAG_CHRISTENING
+
+
Value: CHR
+
The religious event (not LDS) of baptizing and/or naming a child.
+
+
var GEDCOM_TAG_CITY
+
+
Value: CITY
+
A lower level jurisdictional unit. Normally an incorporated municipal unit.
var GEDCOM_TAG_CONCATENATION
-
Value: CONC
-
An indicator that additional data belongs to the superior value. The information from the CONC value is to
-be connected to the value of the superior preceding line without a space and without a carriage return and/or
-new line character. Values that are split for a CONC tag must always be split at a non-space. If the value is
-split on a space the space will be lost when concatenation takes place. This is because of the treatment that
-spaces get as a GEDCOM delimiter, many GEDCOM values are trimmed of trailing spaces and some systems look for
-the first non-space starting after the tag to determine the beginning of the value.
+
Value: CONC
+
An indicator that additional data belongs to the superior value. The information
+from the CONC value is to be connected to the value of the superior preceding
+line without a space and without a carriage return and/or new line character.
+Values that are split for a CONC tag must always be split at a non-space. If
+the value is split on a space the space will be lost when concatenation takes
+place. This is because of the treatment that spaces get as a GEDCOM delimiter,
+many GEDCOM values are trimmed of trailing spaces and some systems look for
+the first non-space starting after the tag to determine the beginning of the
+value.
+
+
var GEDCOM_TAG_CONFIRMATION
+
+
Value: CONF
+
The religious event (not LDS) of conferring the gift of the Holy Ghost and,
+among protestants, full church membership.
+
+
var GEDCOM_TAG_CONFIRMATION_L
+
+
Value: CONL
+
The religious event by which a person receives membership in the LDS Church.
var GEDCOM_TAG_CONTINUED
-
Value: CONT
-
An indicator that additional data belongs to the superior value. The information from the CONT value is to be
-connected to the value of the superior preceding line with a carriage return and/or new line character.
-Leading spaces could be important to the formatting of the resultant text. When importing values from CONT lines
-the reader should assume only one delimiter character following the CONT tag. Assume that the rest of the leading
-spaces are to be a part of the value.
+
Value: CONT
+
An indicator that additional data belongs to the superior value. The information
+from the CONT value is to be connected to the value of the superior preceding
+line with a carriage return and/or new line character. Leading spaces could be
+important to the formatting of the resultant text. When importing values from
+CONT lines the reader should assume only one delimiter character following
+the CONT tag. Assume that the rest of the leading spaces are to be a part
+of the value.
+
+
var GEDCOM_TAG_COPYRIGHT
+
+
Value: COPR
+
A statement that accompanies data to protect it from unlawful duplication
+and distribution.
+
+
var GEDCOM_TAG_CORPORATE
+
+
Value: CORP
+
A name of an institution, agency, corporation, or company.
+
+
var GEDCOM_TAG_COUNTRY
+
+
Value: CTRY
+
The name or code of a country.
+
+
var GEDCOM_TAG_CREMATION
+
+
Value: CREM
+
Disposal of the remains of a person's body by fire.
+
+
var GEDCOM_TAG_DATA
+
+
Value: DATA
+
Pertaining to stored automation information.
var GEDCOM_TAG_DATE
-
Value: DATE
-
The time of an event in a calendar format.
+
Value: DATE
+
The time of an event in a calendar format.
var GEDCOM_TAG_DEATH
-
Value: DEAT
-
The event when mortal life terminates.
+
Value: DEAT
+
The event when mortal life terminates.
+
+
var GEDCOM_TAG_DESCENDANTS
+
+
Value: DESC
+
Pertaining to offspring of an individual.
+
+
var GEDCOM_TAG_DESCENDANTS_INT
+
+
Value: DESI
+
Indicates an interest in research to identify additional descendants of this
+individual. (See also GEDCOM_TAG_ANCES_INTEREST)
+
+
var GEDCOM_TAG_DESTINATION
+
+
Value: DEST
+
A system receiving data.
+
+
var GEDCOM_TAG_DIVORCE
+
+
Value: DIV
+
The event of disolving a marriage through civil action.
+
+
var GEDCOM_TAG_DIVORCE_FILED
+
+
Value: DIVF
+
An event of filing for a divorce by a spouse.
+
+
var GEDCOM_TAG_EDUCATION
+
+
Value: EDUC
+
Indicator of a level of education attained.
+
+
var GEDCOM_TAG_EMAIL
+
+
Value: EMAIL
+
An electronic address that can be used for contact such as an email address.
+
+
var GEDCOM_TAG_EMIGRATION
+
+
Value: EMIG
+
An event of leaving one's homeland with the intent of residing elsewhere.
+
+
var GEDCOM_TAG_ENDOWMENT
+
+
Value: ENDL
+
A religious event where an endowment ordinance for an individual was performed
+by priesthood authority in an LDS temple.
+
+
var GEDCOM_TAG_ENGAGEMENT
+
+
Value: ENGA
+
An event of recording or announcing an agreement between two people to become
+married.
+
+
var GEDCOM_TAG_EVENT
+
+
Value: EVEN
+
A noteworthy happening related to an individual, a group, or an organization.
+
+
var GEDCOM_TAG_FACT
+
+
Value: FACT
+
Pertaining to a noteworthy attribute or fact concerning an individual, a group,
+or an organization. A FACT structure is usually qualified or classified by a
+subordinate use of the GEDCOM_TAG_TYPE tag.
var GEDCOM_TAG_FAMILY
-
Value: FAM.
-
Identifies a legal, common law, or other customary relationship of man and woman and their children,
-if any, or a family created by virtue of the birth of a child to its biological father and mother.
+
Value: FAM.
+
Identifies a legal, common law, or other customary relationship of man and woman
+and their children, if any, or a family created by virtue of the birth of a
+child to its biological father and mother.
var GEDCOM_TAG_FAMILY_CHILD
-
Value: FAMC
-
Identifies the family in which an individual appears as a child.
+
Value: FAMC
+
Identifies the family in which an individual appears as a child.
+
+
var GEDCOM_TAG_FAMILY_FILE
+
+
Value: FAMF
+
Pertaining to, or the name of, a family file. Names stored in a file that are
+assigned to a family for doing temple ordinance work.
var GEDCOM_TAG_FAMILY_SPOUSE
-
Value: FAMS
-
Identifies the family in which an individual appears as a spouse.
+
Value: FAMS
+
Identifies the family in which an individual appears as a spouse.
+
+
var GEDCOM_TAG_FAX
+
+
Value: FAX
+
A FAX telephone number appropriate for sending data facsimiles.
var GEDCOM_TAG_FILE
-
Value: FILE
-
An information storage place that is ordered and arranged for preservation and reference.
+
Value: FILE
+
An information storage place that is ordered and arranged for preservation and
+reference.
+
+
var GEDCOM_TAG_FIRST_COMMUNION
+
+
Value: FCOM
+
A religious rite, the first act of sharing in the Lord's supper as part of
+church worship.
+
+
var GEDCOM_TAG_FORMAT
+
+
Value: FORM
+
An assigned name given to a consistent format in which information can be
+conveyed.
+
+
var GEDCOM_TAG_GEDCOM
+
+
Value: GEDC
+
Information about the use of GEDCOM in a transmission.
var GEDCOM_TAG_GIVEN_NAME
-
Value: GIVN
-
A given or earned name used for official identification of a person.
+
Value: GIVN
+
A given or earned name used for official identification of a person.
+
+
var GEDCOM_TAG_GRADUATION
+
+
Value: GRAD
+
An event of awarding educational diplomas or degrees to individuals.
+
+
var GEDCOM_TAG_HEADER
+
+
Value: HEAD
+
Identifies information pertaining to an entire GEDCOM transmission.
var GEDCOM_TAG_HUSBAND
-
Value: HUSB
-
An individual in the family role of a married man or father.
+
Value: HUSB
+
An individual in the family role of a married man or father.
+
+
var GEDCOM_TAG_IDENT_NUMBER
+
+
Value: IDNO
+
A number assigned to identify a person within some significant external system.
+
+
var GEDCOM_TAG_IMMIGRATION
+
+
Value: IMMI
+
An event of entering into a new locality witht he intent of residing there.
var GEDCOM_TAG_INDIVIDUAL
-
Value: INDI
-
A person.
+
Value: INDI
+
A person.
+
+
var GEDCOM_TAG_LANGUAGE
+
+
Value: LANG
+
The name of the language used in a communication or transmission of information.
+
+
var GEDCOM_TAG_LATITUDE
+
+
Value: LATI
+
A value indicating a coordinate position on a line, plane, or space.
+
+
var GEDCOM_TAG_LEGATEE
+
+
Value: LEGA
+
A role of an individual acting as a person receiving a bequest or legal devise.
+
+
var GEDCOM_TAG_LONGITUDE
+
+
Value: LONG
+
A value indicating a coordinate position on a line, plane, or space.
+
+
var GEDCOM_TAG_MAP
+
+
Value: MAP
+
Pertains to a representation of measurements usually presented in a graphical
+form.
var GEDCOM_TAG_MARRIAGE
-
Value: MARR.
-
A legal, common-law, or customary event of creating a family unit of a man and a woman as husband and wife.
+
Value: MARR.
+
A legal, common-law, or customary event of creating a family unit of a man and
+a woman as husband and wife.
+
+
var GEDCOM_TAG_MARRIAGE_BANN
+
+
Value: MARB.
+
An event of an official public notice given that two people intend to marry.
+
+
var GEDCOM_TAG_MARRIAGE_COUNT
+
+
Value: NMR
+
The number of times this person has participated in a family as a spouse or
+parent.
+
+
var GEDCOM_TAG_MARR_CONTRACT
+
+
Value: MARC.
+
An event of recording a formal agreement of marriage, including the prenuptial
+agreement in which marriage partners reach agreement about the property rights
+of one or both, securing property to their children.
+
+
var GEDCOM_TAG_MARR_LICENSE
+
+
Value: MARL.
+
An event of obtaining a legal license to marry.
+
+
var GEDCOM_TAG_MARR_SETTLEMENT
+
+
Value: MARS.
+
An event of creating an agreement between two people contemplating marriage,
+at which time they agree to release or modify property rights that would
+otherwise arise from the marriage.
+
+
var GEDCOM_TAG_MEDIA
+
+
Value: MEDI.
+
Identifies information about the media or having to do with the medium in which
+information is stored.
var GEDCOM_TAG_NAME
-
Value: NAME.
-
A word or combination of words used to help identify an individual, title, or other item.
-More than one NAME line should be used for people who were known by multiple names.
+
Value: NAME.
+
A word or combination of words used to help identify an individual, title, or
+other item. More than one NAME line should be used for people who were known
+by multiple names.
+
+
var GEDCOM_TAG_NAME_PREFIX
+
+
Value: NPFX
+
Text which appears on a name line before the given and surname parts of a name.
+i.e. ( Lt. Cmndr. ) Joseph /Allen/ jr. In this example Lt. Cmndr. is considered
+as the name prefix portion.
+
+
var GEDCOM_TAG_NAME_SUFFIX
+
+
Value: NSFX
+
Text which appears on a name line after or behind the given and surname parts
+of a name. i.e. Lt. Cmndr. Joseph /Allen/ ( jr. ) In this example jr. is
+considered as the name suffix portion.
+
+
var GEDCOM_TAG_NATIONALITY
+
+
Value: NATI
+
The national heritage of an individual.
+
+
var GEDCOM_TAG_NATURALIZATION
+
+
Value: NATU
+
The event of obtaining citizenship.
+
+
var GEDCOM_TAG_NICKNAME
+
+
Value: NICK
+
A descriptive or familiar that is used instead of, or in addition to, one's
+proper name.
+
+
var GEDCOM_TAG_NOTE
+
+
Value: NOTE
+
Additional information provided by the submitter for understanding the
+enclosing data.
var GEDCOM_TAG_OBJECT
-
Value: OBJE
-
Pertaining to a grouping of attributes used in describing something. Usually referring to the data required
-to represent a multimedia object, such an audio recording, a photograph of a person, or an image of a document.
+
Value: OBJE
+
Pertaining to a grouping of attributes used in describing something. Usually
+referring to the data required to represent a multimedia object, such an audio
+recording, a photograph of a person, or an image of a document.
var GEDCOM_TAG_OCCUPATION
-
Value: OCCU
-
The type of work or profession of an individual.
+
Value: OCCU
+
The type of work or profession of an individual.
+
+
var GEDCOM_TAG_ORDINANCE
+
+
Value: ORDI
+
Pertaining to a religious ordinance in general.
+
+
var GEDCOM_TAG_ORDINATION
+
+
Value: ORDN
+
A religious event of receiving authority to act in religious matters.
+
+
var GEDCOM_TAG_PAGE
+
+
Value: PAGE
+
A number or description to identify where information can be found in a
+referenced work.
+
+
var GEDCOM_TAG_PEDIGREE
+
+
Value: PEDI
+
Information pertaining to an individual to parent lineage chart.
+
+
var GEDCOM_TAG_PHONE
+
+
Value: PHON
+
A unique number assigned to access a specific telephone.
+
+
var GEDCOM_TAG_PHONETIC
+
+
Value: FONE
+
A phonetic variation of a superior text string.
+
+
var GEDCOM_TAG_PHY_DESCRIPTION
+
+
Value: DSCR
+
The physical characteristics of a person, place, or thing.
var GEDCOM_TAG_PLACE
-
Value: PLAC
-
A jurisdictional name to identify the place or location of an event.
+
Value: PLAC
+
A jurisdictional name to identify the place or location of an event.
+
+
var GEDCOM_TAG_POSTAL_CODE
+
+
Value: POST
+
A code used by a postal service to identify an area to facilitate mail handling.
var GEDCOM_TAG_PRIVATE
-
Value: PRIV
-
Flag for private address or event.
+
Value: PRIV
+
Flag for private address or event.
+
+
var GEDCOM_TAG_PROBATE
+
+
Value: PROB
+
An event of judicial determination of the validity of a will. May indicate
+several related court activities over several dates.
+
+
var GEDCOM_TAG_PROPERTY
+
+
Value: PROP
+
Pertaining to possessions such as real estate or other property of interest.
+
+
var GEDCOM_TAG_PUBLICATION
+
+
Value: PUBL
+
Refers to when and/or were a work was published or created.
+
+
var GEDCOM_TAG_QUALITY_OF_DATA
+
+
Value: QUAY
+
An assessment of the certainty of the evidence to support the conclusion drawn
+from evidence.
+
+
var GEDCOM_TAG_REC_FILE_NUMBER
+
+
Value: RFN
+
A permanent number assigned to a record that uniquely identifies it within a
+known file.
+
+
var GEDCOM_TAG_REC_ID_NUMBER
+
+
Value: RIN
+
A number assigned to a record by an originating automated system that can be
+used by a receiving system to report results pertaining to that record.
+
+
var GEDCOM_TAG_REFERENCE
+
+
Value: REFN
+
A description or number used to identify an item for filing, storage, or other
+reference purposes.
+
+
var GEDCOM_TAG_RELATIONSHIP
+
+
Value: RELA
+
A relationship value between the indicated contexts.
+
+
var GEDCOM_TAG_RELIGION
+
+
Value: RELI
+
A religious denomination to which a person is affiliated or for which a record
+applies.
+
+
var GEDCOM_TAG_REPOSITORY
+
+
Value: REPO
+
An institution or person that has the specified item as part of their
+collection(s).
+
+
var GEDCOM_TAG_RESIDENCE
+
+
Value: RESI
+
The act of dwelling at a place for a period of time.
+
+
var GEDCOM_TAG_RESTRICTION
+
+
Value: RESN
+
A processing indicator signifying access to information has been denied or
+otherwise restricted.
+
+
var GEDCOM_TAG_RETIREMENT
+
+
Value: RETI
+
An event of exiting an occupational relationship with an employer after a
+qualifying time period.
+
+
var GEDCOM_TAG_ROLE
+
+
Value: ROLE
+
A name given to a role played by an individual in connection with an event.
+
+
var GEDCOM_TAG_ROMANIZED
+
+
Value: ROMN
+
A romanized variation of a superior text string.
+
+
var GEDCOM_TAG_SEALING_CHILD
+
+
Value: SLGC
+
A religious event pertaining to the sealing of a child to his or her parents in
+an LDS temple ceremony.
+
+
var GEDCOM_TAG_SEALING_SPOUSE
+
+
Value: SLGS
+
A religious event pertaining to the sealing of a husband and wife in an LDS
+temple ceremony.
var GEDCOM_TAG_SEX
-
Value: SEX
-
Indicates the sex of an individual–male or female.
+
Value: SEX
+
Indicates the sex of an individual–male or female.
+
+
var GEDCOM_TAG_SOC_SEC_NUMBER
+
+
Value: SSN
+
A number assigned by the United States Social Security Administration. Used for
+tax identification purposes.
var GEDCOM_TAG_SOURCE
-
Value: SOUR
-
The initial or original material from which information was obtained.
+
Value: SOUR
+
The initial or original material from which information was obtained.
+
+
var GEDCOM_TAG_STATE
+
+
Value: STAE
+
A geographical division of a larger jurisdictional area, such as a State within
+the United States of America.
+
+
var GEDCOM_TAG_STATUS
+
+
Value: STAT
+
An assessment of the state or condition of something.
+
+
var GEDCOM_TAG_SUBMISSION
+
+
Value: SUBN
+
Pertains to a collection of data issued for processing.
+
+
var GEDCOM_TAG_SUBMITTER
+
+
Value: SUBM
+
An individual or organization who contributes genealogical data to a file or
+transfers it to someone else.
var GEDCOM_TAG_SURNAME
-
Value: SURN
-
A family name passed on or used by members of a family.
+
Value: SURN
+
A family name passed on or used by members of a family.
+
+
var GEDCOM_TAG_SURN_PREFIX
+
+
Value: SPFX
+
A name piece used as a non-indexing pre-part of a surname.
+
+
var GEDCOM_TAG_TEMPLE
+
+
Value: TEMP
+
The name or code that represents the name a temple of the LDS Church.
+
+
var GEDCOM_TAG_TEXT
+
+
Value: TEXT
+
The exact wording found in an original source document.
+
+
var GEDCOM_TAG_TIME
+
+
Value: TIME
+
A time value in a 24-hour clock format, including hours, minutes, and optional
+seconds, separated by a colon (:). Fractions of seconds are shown in decimal
+notation.
+
+
var GEDCOM_TAG_TITLE
+
+
Value: TITL
+
A description of a specific writing or other work, such as the title of a book
+when used in a source context, or a formal designation used by an individual
+in connection with positions of royalty or other social status, such as Grand
+Duke.
+
+
var GEDCOM_TAG_TRAILER
+
+
Value: TRLR
+
At level 0, specifies the end of a GEDCOM transmission.
+
+
var GEDCOM_TAG_TYPE
+
+
Value: TYPE
+
A further qualification to the meaning of the associated superior tag. The value
+does not have any computer processing reliability. It is more in the form of a
+short one or two word note that should be displayed any time the associated data
+is displayed.
+
+
var GEDCOM_TAG_VERSION
+
+
Value: VERS
+
Indicates which version of a product, item, or publication is being used or
+referenced.
var GEDCOM_TAG_WIFE
-
Value: WIFE
-
An individual in the role as a mother and/or married woman.
+
Value: WIFE
+
An individual in the role as a mother and/or married woman.
+
+
var GEDCOM_TAG_WILL
+
+
Value: WILL
+
A legal document treated as an event, by which a person disposes of his or her
+estate, to take effect after death. The event date is the date the will was
+signed while the person was alive. (See also GEDCOM_TAG_PROBATE)
diff --git a/gedcom/__init__.py b/gedcom/__init__.py
index 6fee00a..65ea462 100644
--- a/gedcom/__init__.py
+++ b/gedcom/__init__.py
@@ -41,6 +41,7 @@
"detect",
"parser",
"reader",
+ "records",
"standards",
"tags"
]
diff --git a/gedcom/detect.py b/gedcom/detect.py
index e0ad5aa..d79116c 100644
--- a/gedcom/detect.py
+++ b/gedcom/detect.py
@@ -27,12 +27,14 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Functions to detect GEDCOM encoding and version.
+Module containing functions for detecting GEDCOM file encoding and version.
"""
+from typing import Tuple
import chardet
import ansel
+import gedcom.tags as tags
import gedcom.standards as standards
from gedcom.errors import GedcomFormatViolationError
from gedcom.errors import GedcomCharacterSetUnsupportedError
@@ -40,14 +42,13 @@
ansel.register()
-def validate_encoding(file_path, codec):
- """Check the encoding is compatible with the encoding reported
- :type file_path: str
- :type codec: str
+def __validate_encoding(file_path, codec):
+ """Check the encoding is compatible with the encoding as reported by the
+ `gedcom.tags.GEDCOM_TAG_CHARACTER` header tag.
"""
with open(file_path, 'r', encoding=codec) as gedcom_data:
for line in gedcom_data:
- if 'CHAR' in line:
+ if tags.GEDCOM_TAG_CHARACTER in line:
character_set = line.split(' ')[2].lower().strip()
break
@@ -65,10 +66,11 @@ def validate_encoding(file_path, codec):
raise GedcomCharacterSetUnsupportedError(errmsg)
-def get_encoding(file_path):
- """Examines file to determine encoding to use and then validates it
- :type file_path: str
- :rtype: str
+def get_encoding(file_path: str) -> str:
+ """Probe a GEDCOM file to determine the encoding and validate it against the encoding
+ as reported in the `HEADER` record by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
+
+ Returns: codec
"""
with open(file_path, 'rb') as gedcom_data:
sample_data = gedcom_data.read(262144)
@@ -95,16 +97,15 @@ def get_encoding(file_path):
"the file.\nSee: {0}".format(standards.GEDCOM_5_5_1)
raise GedcomCharacterSetUnsupportedError(errmsg)
- validate_encoding(file_path, codec)
+ __validate_encoding(file_path, codec)
return codec
-def get_version(file_path, codec):
- """Probes Gedcom to identify version used, should expand this in future
- Returns probed version, reported version, reported format
- :type file_path: str
- :type encoding: str
- :rtype: str, str, str
+def get_version(file_path: str, codec: str) -> Tuple[str, str, str]:
+ """Probe a GEDCOM file to identify the version of the standard used as some reported 5.5
+ files are really 5.5.1.
+
+ Returns: probed version, reported version, reported format
"""
in_gedc_tag = False
gedcom_version = None
@@ -127,10 +128,10 @@ def get_version(file_path, codec):
" not found as expected.\nSee: {0}".format(standards.GEDCOM_5_5_1)
raise GedcomFormatViolationError(errmsg)
- real_version = gedcom_version
+ probed_version = gedcom_version
# UTF was added in the 5.5.1 specification
if gedcom_version == '5.5' and 'utf' in codec:
- real_version = gedcom_version
+ probed_version = gedcom_version
- return real_version, gedcom_version, gedcom_format
+ return probed_version, gedcom_version, gedcom_format
diff --git a/gedcom/element/element.py b/gedcom/element/element.py
index 3bc3520..a1e9065 100644
--- a/gedcom/element/element.py
+++ b/gedcom/element/element.py
@@ -26,18 +26,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Base GEDCOM element
+Base GEDCOM element.
"""
from sys import version_info
+from typing import List
+
from gedcom.helpers import deprecated
import gedcom.tags
class Element(object):
- """GEDCOM element
+ """GEDCOM element.
- Each line in a GEDCOM file is an element with the format
+ Each line in a GEDCOM file is an element with the format:
`level [pointer] tag [value]`
@@ -62,7 +64,8 @@ class Element(object):
Tags available to an element are seen here: `gedcom.tags`
"""
- def __init__(self, level, pointer, tag, value, crlf="\n", multi_line=True):
+ def __init__(self, level: int, pointer: str, tag: str, value: str,
+ crlf: str = "\n", multi_line: bool = True):
# basic element info
self.__level = level
self.__pointer = pointer
@@ -77,39 +80,33 @@ def __init__(self, level, pointer, tag, value, crlf="\n", multi_line=True):
if multi_line:
self.set_multi_line_value(value)
- def get_level(self):
- """Returns the level of this element from within the GEDCOM file
- :rtype: int
+ def get_level(self) -> int:
+ """Returns the level of this element from within the GEDCOM file.
"""
return self.__level
- def get_pointer(self):
- """Returns the pointer of this element from within the GEDCOM file
- :rtype: str
+ def get_pointer(self) -> str:
+ """Returns the pointer of this element from within the GEDCOM file.
"""
return self.__pointer
- def get_tag(self):
- """Returns the tag of this element from within the GEDCOM file
- :rtype: str
+ def get_tag(self) -> str:
+ """Returns the tag of this element from within the GEDCOM file.
"""
return self.__tag
- def get_value(self):
- """Return the value of this element from within the GEDCOM file
- :rtype: str
+ def get_value(self) -> str:
+ """Return the value of this element from within the GEDCOM file.
"""
return self.__value
- def set_value(self, value):
- """Sets the value of this element
- :type value: str
+ def set_value(self, value: str):
+ """Sets the value of this element.
"""
self.__value = value
- def get_multi_line_value(self):
- """Returns the value of this element including concatenations or continuations
- :rtype: str
+ def get_multi_line_value(self) -> str:
+ """Returns the value of this element including concatenations or continuations.
"""
result = self.get_value()
last_crlf = self.__crlf
@@ -123,17 +120,14 @@ def get_multi_line_value(self):
last_crlf = element.__crlf
return result
- def __available_characters(self):
+ def __available_characters(self) -> int:
"""Get the number of available characters of the elements original string
- :rtype: int
"""
element_characters = len(self.to_gedcom_string())
return 0 if element_characters > 255 else 255 - element_characters
- def __line_length(self, line):
- """@TODO Write docs.
- :type line: str
- :rtype: int
+ def __line_length(self, line: str) -> int:
+ """Return line length.
"""
total_characters = len(line)
available_characters = self.__available_characters()
@@ -146,40 +140,36 @@ def __line_length(self, line):
return available_characters
return available_characters - spaces
- def __set_bounded_value(self, value):
+ def __set_bounded_value(self, value: str) -> int:
"""@TODO Write docs.
- :type value: str
- :rtype: int
"""
line_length = self.__line_length(value)
self.set_value(value[:line_length])
return line_length
- def __add_bounded_child(self, tag, value):
+ def __add_bounded_child(self, tag: str, value: str) -> int:
"""@TODO Write docs.
- :type tag: str
- :type value: str
- :rtype: int
"""
child = self.new_child_element(tag)
return child.__set_bounded_value(value)
- def __add_concatenation(self, string):
+ def __add_concatenation(self, string: str):
"""@TODO Write docs.
- :rtype: str
"""
index = 0
size = len(string)
while index < size:
index += self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONCATENATION, string[index:])
- def set_multi_line_value(self, value):
- """Sets the value of this element, adding concatenation and continuation lines when necessary
- :type value: str
+ def set_multi_line_value(self, value: str):
+ """Sets the value of this element, adding concatenation and continuation lines
+ when necessary.
"""
self.set_value('')
self.get_child_elements()[:] = [child for child in self.get_child_elements() if
- child.get_tag() not in (gedcom.tags.GEDCOM_TAG_CONCATENATION, gedcom.tags.GEDCOM_TAG_CONTINUED)]
+ child.get_tag() not in
+ (gedcom.tags.GEDCOM_TAG_CONCATENATION,
+ gedcom.tags.GEDCOM_TAG_CONTINUED)]
lines = value.splitlines()
if lines:
@@ -191,19 +181,14 @@ def set_multi_line_value(self, value):
n = self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONTINUED, line)
self.__add_concatenation(line[n:])
- def get_child_elements(self):
- """Returns the direct child elements of this element
- :rtype: list of Element
+ def get_child_elements(self) -> List[Element]:
+ """Returns the direct child elements of this element.
"""
return self.__children
- def new_child_element(self, tag, pointer="", value=""):
- """Creates and returns a new child element of this element
-
- :type tag: str
- :type pointer: str
- :type value: str
- :rtype: Element
+ def new_child_element(self, tag: str, pointer: str = "",
+ value: str = "") -> Element:
+ """Creates and returns a new child element of this element.
"""
from gedcom.element.family import FamilyElement
from gedcom.element.individual import IndividualElement
@@ -217,68 +202,70 @@ def new_child_element(self, tag, pointer="", value=""):
# Differentiate between the type of the new child element
if tag == gedcom.tags.GEDCOM_TAG_FAMILY:
- child_element = FamilyElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = FamilyElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
- child_element = IndividualElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = IndividualElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_NOTE:
- child_element = NoteElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = NoteElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
- child_element = ObjectElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = ObjectElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_REPOSITORY:
- child_element = RepositoryElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = RepositoryElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SOURCE:
- child_element = SourceElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SourceElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SUBMITTER:
- child_element = SubmitterElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SubmitterElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SUBMISSION:
- child_element = SubmissionElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SubmissionElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_HEADER:
- child_element = HeaderElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = HeaderElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
else:
- child_element = Element(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = Element(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
self.add_child_element(child_element)
return child_element
- def add_child_element(self, element):
- """Adds a child element to this element
-
- :type element: Element
+ def add_child_element(self, element: Element):
+ """Adds a child element to this element.
"""
self.get_child_elements().append(element)
element.set_parent_element(self)
return element
- def get_parent_element(self):
- """Returns the parent element of this element
- :rtype: Element
+ def get_parent_element(self) -> Element:
+ """Returns the parent element of this element.
"""
return self.__parent
- def set_parent_element(self, element):
- """Adds a parent element to this element
+ def set_parent_element(self, element: Element):
+ """Adds a parent element to this element.
There's usually no need to call this method manually,
`add_child_element()` calls it automatically.
-
- :type element: Element
"""
self.__parent = element
@deprecated
- def get_individual(self):
- """Returns this element and all of its sub-elements represented as a GEDCOM string
+ def get_individual(self) -> str:
+ """Returns this element and all of its sub-elements represented as a GEDCOM string.
::deprecated:: As of version 1.0.0 use `to_gedcom_string()` method instead
- :rtype: str
"""
return self.to_gedcom_string(True)
- def to_gedcom_string(self, recursive=False):
- """Formats this element and optionally all of its sub-elements into a GEDCOM string
- :type recursive: bool
- :rtype: str
+ def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats this element and optionally all of its sub-elements into a GEDCOM string.
"""
result = str(self.get_level())
@@ -302,7 +289,7 @@ def to_gedcom_string(self, recursive=False):
return result
- def __str__(self):
+ def __str__(self) -> str:
""":rtype: str"""
if version_info[0] >= 3:
return self.to_gedcom_string()
diff --git a/gedcom/element/family.py b/gedcom/element/family.py
index 712c887..ff735bb 100644
--- a/gedcom/element/family.py
+++ b/gedcom/element/family.py
@@ -53,12 +53,11 @@
class FamilyElement(Element):
"""Element associated with a `FAM_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_FAMILY
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_family': self.get_pointer(),
diff --git a/gedcom/element/header.py b/gedcom/element/header.py
index 45cb8ac..55399d9 100644
--- a/gedcom/element/header.py
+++ b/gedcom/element/header.py
@@ -50,12 +50,11 @@
class HeaderElement(Element):
"""Element associated with a `HEADER`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_HEADER
- def get_record(self):
- """Parse and return the full record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'source': '',
diff --git a/gedcom/element/individual.py b/gedcom/element/individual.py
index e137c2e..f2af5d4 100644
--- a/gedcom/element/individual.py
+++ b/gedcom/element/individual.py
@@ -31,7 +31,9 @@
`gedcom.tags.GEDCOM_TAG_INDIVIDUAL` tag.
"""
+from typing import Tuple, List
import re as regex
+
import gedcom.tags as tags
from gedcom.element.element import Element
from gedcom.subparsers.personal_name_structure import personal_name_structure
@@ -60,12 +62,11 @@
class IndividualElement(Element):
"""Element associated with an `INDIVIDUAL_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_INDIVIDUAL
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_individual': self.get_pointer(),
@@ -153,9 +154,8 @@ def get_record(self):
return record
- def is_deceased(self):
- """Checks if this individual is deceased
- :rtype: bool
+ def is_deceased(self) -> bool:
+ """Checks if this individual is deceased.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_DEATH:
@@ -163,9 +163,8 @@ def is_deceased(self):
return False
- def is_child(self):
- """Checks if this element is a child of a family
- :rtype: bool
+ def is_child(self) -> bool:
+ """Checks if this element is a child of a family.
"""
found_child = False
@@ -175,9 +174,8 @@ def is_child(self):
return found_child
- def is_private(self):
- """Checks if this individual is marked private
- :rtype: bool
+ def is_private(self) -> bool:
+ """Checks if this individual is marked private.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
@@ -187,9 +185,8 @@ def is_private(self):
return False
- def get_name(self):
+ def get_name(self) -> Tuple[str, str]:
"""Returns an individual's names as a tuple: (`str` given_name, `str` surname)
- :rtype: tuple
"""
given_name = ""
surname = ""
@@ -230,38 +227,32 @@ def get_name(self):
# If we reach here we are probably returning empty strings
return given_name, surname
- def get_all_names(self):
- """Return all names"""
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
+ def get_all_names(self) -> List[str]:
+ """Return all names."""
+ return [a.get_value() for a in self.get_child_elements()
+ if a.get_tag() == tags.GEDCOM_TAG_NAME]
- def surname_match(self, surname_to_match):
- """Matches a string with the surname of an individual
- :type surname_to_match: str
- :rtype: bool
+ def surname_match(self, surname_to_match: str) -> bool:
+ """Matches a string with the surname of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(surname_to_match, surname, regex.IGNORECASE)
@deprecated
- def given_match(self, name):
- """Matches a string with the given name of an individual
+ def given_match(self, name: str) -> bool:
+ """Matches a string with the given name of an individual.
::deprecated:: As of version 1.0.0 use `given_name_match()` method instead
- :type name: str
- :rtype: bool
"""
return self.given_name_match(name)
- def given_name_match(self, given_name_to_match):
- """Matches a string with the given name of an individual
- :type given_name_to_match: str
- :rtype: bool
+ def given_name_match(self, given_name_to_match: str) -> bool:
+ """Matches a string with the given name of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(given_name_to_match, given_name, regex.IGNORECASE)
- def get_gender(self):
- """Returns the gender of a person in string format
- :rtype: str
+ def get_gender(self) -> str:
+ """Returns the gender of a person in string format.
"""
gender = ""
@@ -271,10 +262,9 @@ def get_gender(self):
return gender
- def get_birth_data(self):
+ def get_birth_data(self) -> Tuple[str, str, List[str]]:
"""Returns the birth data of a person formatted as a tuple:
(`str` date, `str` place, `list` sources)
- :rtype: tuple
"""
date = ""
place = ""
@@ -295,9 +285,8 @@ def get_birth_data(self):
return date, place, sources
- def get_birth_year(self):
- """Returns the birth year of a person in integer format
- :rtype: int
+ def get_birth_year(self) -> int:
+ """Returns the birth year of a person in integer format.
"""
date = ""
@@ -315,9 +304,9 @@ def get_birth_year(self):
except ValueError:
return -1
- def get_death_data(self):
- """Returns the death data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
- :rtype: tuple
+ def get_death_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the death data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
"""
date = ""
place = ""
@@ -335,9 +324,8 @@ def get_death_data(self):
return date, place, sources
- def get_death_year(self):
- """Returns the death year of a person in integer format
- :rtype: int
+ def get_death_year(self) -> int:
+ """Returns the death year of a person in integer format.
"""
date = ""
@@ -356,16 +344,16 @@ def get_death_year(self):
return -1
@deprecated
- def get_burial(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
+ def get_burial(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_burial_data()` method instead
- :rtype: tuple
"""
self.get_burial_data()
- def get_burial_data(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
- :rtype: tuple
+ def get_burial_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
"""
date = ""
place = ""
@@ -387,16 +375,16 @@ def get_burial_data(self):
return date, place, sources
@deprecated
- def get_census(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
+ def get_census(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_census_data()` method instead
- :rtype: list of tuple
"""
self.get_census_data()
- def get_census_data(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
- :rtype: list of tuple
+ def get_census_data(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
"""
census = []
@@ -422,9 +410,8 @@ def get_census_data(self):
return census
- def get_last_change_date(self):
- """Returns the date of when the person data was last changed formatted as a string
- :rtype: str
+ def get_last_change_date(self) -> str:
+ """Returns the date of when the person data was last changed formatted as a string.
"""
date = ""
@@ -436,9 +423,8 @@ def get_last_change_date(self):
return date
- def get_occupation(self):
- """Returns the occupation of a person
- :rtype: str
+ def get_occupation(self) -> str:
+ """Returns the occupation of a person.
"""
occupation = ""
@@ -448,18 +434,13 @@ def get_occupation(self):
return occupation
- def birth_year_match(self, year):
- """Returns `True` if the given year matches the birth year of this person
- :type year: int
- :rtype: bool
+ def birth_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the birth year of this person.
"""
return self.get_birth_year() == year
- def birth_range_match(self, from_year, to_year):
- """Checks if the birth year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def birth_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the birth year of a person lies within the given range.
"""
birth_year = self.get_birth_year()
@@ -468,18 +449,13 @@ def birth_range_match(self, from_year, to_year):
return False
- def death_year_match(self, year):
- """Returns `True` if the given year matches the death year of this person
- :type year: int
- :rtype: bool
+ def death_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the death year of this person.
"""
return self.get_death_year() == year
- def death_range_match(self, from_year, to_year):
- """Checks if the death year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def death_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the death year of a person lies within the given range.
"""
death_year = self.get_death_year()
@@ -488,8 +464,8 @@ def death_range_match(self, from_year, to_year):
return False
- def criteria_match(self, criteria):
- """Checks if this individual matches all of the given criteria
+ def criteria_match(self, criteria: str) -> bool:
+ """Checks if this individual matches all of the given criteria.
`criteria` is a colon-separated list, where each item in the
list has the form [name]=[value]. The following criteria are supported:
@@ -503,9 +479,6 @@ def criteria_match(self, criteria):
birth_range=[from_year-to_year]
Match a person whose birth year is in the range of years from
[from_year] to [to_year], including both [from_year] and [to_year].
-
- :type criteria: str
- :rtype: bool
"""
# Check if criteria is a valid criteria and can be split by `:` and `=` characters
diff --git a/gedcom/element/note.py b/gedcom/element/note.py
index 4966552..2035f54 100644
--- a/gedcom/element/note.py
+++ b/gedcom/element/note.py
@@ -41,12 +41,11 @@
class NoteElement(Element):
"""Element associated with a `NOTE_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_NOTE
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_note': self.get_pointer(),
diff --git a/gedcom/element/object.py b/gedcom/element/object.py
index 924356f..5942545 100644
--- a/gedcom/element/object.py
+++ b/gedcom/element/object.py
@@ -42,12 +42,11 @@
class ObjectElement(Element):
"""Element associated with a `MULTIMEDIA_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_OBJECT
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_object': self.get_pointer(),
diff --git a/gedcom/element/repository.py b/gedcom/element/repository.py
index 7f14db5..f0dc469 100644
--- a/gedcom/element/repository.py
+++ b/gedcom/element/repository.py
@@ -42,12 +42,11 @@
class RepositoryElement(Element):
"""Element associated with a `REPOSITORY_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_REPOSITORY
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_repository': self.get_pointer(),
diff --git a/gedcom/element/root.py b/gedcom/element/root.py
index 826c378..6ad719a 100644
--- a/gedcom/element/root.py
+++ b/gedcom/element/root.py
@@ -31,7 +31,8 @@
class RootElement(Element):
- """Virtual GEDCOM root element containing all logical records as children"""
+ """Virtual GEDCOM root element containing all logical records as children."""
- def __init__(self, level=-1, pointer="", tag="ROOT", value="", crlf="\n", multi_line=True):
+ def __init__(self, level: int = -1, pointer: str = "", tag: str = "ROOT", value: str = "",
+ crlf: str = "\n", multi_line: bool = True):
super(RootElement, self).__init__(level, pointer, tag, value, crlf, multi_line)
diff --git a/gedcom/element/source.py b/gedcom/element/source.py
index e58a6f2..e73b52c 100644
--- a/gedcom/element/source.py
+++ b/gedcom/element/source.py
@@ -56,12 +56,11 @@
class SourceElement(Element):
"""Element associated with a SOURCE_RECORD"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_SOURCE
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_source': self.get_pointer(),
diff --git a/gedcom/element/submission.py b/gedcom/element/submission.py
index 78399a9..7eb90d3 100644
--- a/gedcom/element/submission.py
+++ b/gedcom/element/submission.py
@@ -50,12 +50,11 @@
class SubmissionElement(Element):
"""Element associated with a `SUBMISSION_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_SUBMISSION
- def get_record(self):
+ def get_record(self) -> dict:
"""Parse and return the record in dictionary format
- :rtype: dict
"""
record = {
'key_to_submission': self.get_pointer(),
diff --git a/gedcom/element/submitter.py b/gedcom/element/submitter.py
index f89c818..8e48737 100644
--- a/gedcom/element/submitter.py
+++ b/gedcom/element/submitter.py
@@ -42,12 +42,11 @@
class SubmitterElement(Element):
"""Element associated with a `SUBMITTER_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_SUBMITTER
- def get_record(self):
+ def get_record(self) -> dict:
"""Parse and return the record in dictionary format
- :rtype: dict
"""
record = {
'key_to_submitter': self.get_pointer(),
diff --git a/gedcom/errors.py b/gedcom/errors.py
index 4522de0..f8885f2 100644
--- a/gedcom/errors.py
+++ b/gedcom/errors.py
@@ -51,16 +51,16 @@ class GedcomCharacterSetUnsupportedError(Exception):
class GedcomVersionUnsupportedError(Exception):
"""Raised when a particular GEDCOM version is not supported
- by the parser and the standard for the version requires the
+ by the parser and the standard for that version requires the
parser to reject it.
"""
class GedcomFormatUnsupportedError(Exception):
"""Raised if the GEDCOM format is not recognized by the
- parser. Note some misspellings as documented on page 148
- in the 5.5.5 standard are treated as LINEAGE-LINKED and
- allowed.
+ parser. Note some common misspellings as documented on page 148
+ in the 5.5.5 GEDCOM standard are treated as `LINEAGE-LINKED`
+ and allowed when parsing older GEDCOM data.
"""
diff --git a/gedcom/parser.py b/gedcom/parser.py
index b4a7848..c0eeea1 100644
--- a/gedcom/parser.py
+++ b/gedcom/parser.py
@@ -32,7 +32,9 @@
"""
import re as regex
+from sys import stdout
from sys import version_info
+from typing import Tuple, List, IO
import gedcom.tags as tags
import gedcom.standards as standards
@@ -78,10 +80,10 @@
class Parser():
- """Parses and manipulates GEDCOM 5.5 format data
+ """Parses and manipulates GEDCOM formatted data.
- For documentation of the GEDCOM 5.5 format, see:
- http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
+ For documentation of the different GEDCOM standards see the
+ links defined in `gedcom.standards`
This parser reads and parses a GEDCOM file.
@@ -106,8 +108,8 @@ def invalidate_cache(self):
self.__element_list = []
self.__element_dictionary = {}
- def get_element_list(self):
- """Returns a list containing all elements from within the GEDCOM file
+ def get_element_list(self) -> List[Element]:
+ """Returns a list containing all elements from within the GEDCOM file.
By default elements are in the same order as they appeared in the file.
@@ -118,17 +120,15 @@ def get_element_list(self):
Consider using `gedcom.parser.Parser.get_root_element()` or
`gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
-
- :rtype: list of Element
"""
if not self.__element_list:
for element in self.get_root_child_elements():
self.__build_list(element, self.__element_list)
return self.__element_list
- def get_element_dictionary(self):
+ def get_element_dictionary(self) -> dict:
"""Returns a dictionary containing all elements, identified by a pointer,
- from within the GEDCOM file
+ from within the GEDCOM file.
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -136,8 +136,6 @@ def get_element_dictionary(self):
This dictionary gets generated on-the-fly, but gets cached. If the
database was modified, you should call `invalidate_cache()` once to let
this method return updated data.
-
- :rtype: dict of Element
"""
if not self.__element_dictionary:
self.__element_dictionary = {
@@ -147,28 +145,22 @@ def get_element_dictionary(self):
return self.__element_dictionary
- def get_root_element(self):
- """Returns a virtual root element containing all logical records as children
+ def get_root_element(self) -> RootElement:
+ """Returns a virtual root element containing all logical records as children.
When printed, this element converts to an empty string.
-
- :rtype: RootElement
"""
return self.__root_element
- def get_root_child_elements(self):
- """Returns a list of logical records in the GEDCOM file
+ def get_root_child_elements(self) -> List[Element]:
+ """Returns a list of logical records in the GEDCOM file.
By default, elements are in the same order as they appeared in the file.
-
- :rtype: list of Element
"""
return self.get_root_element().get_child_elements()
- def parse_file(self, file_path, strict=True):
- """Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
- :type file_path: str
- :type strict: bool
+ def parse_file(self, file_path: str, strict: bool = True):
+ """Opens and parses a file, from the given file path, as GEDCOM formatted data.
"""
codec = get_encoding(file_path)
real_version, reported_version, reported_format = get_version(file_path, codec)
@@ -187,10 +179,8 @@ def parse_file(self, file_path, strict=True):
with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
- def parse(self, gedcom_stream, strict=True):
- """Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
- :type gedcom_stream: a file stream, or str array of lines with new line at the end
- :type strict: bool
+ def parse(self, gedcom_stream: IO, strict: bool = True):
+ """Parses a stream, or an array of lines, as GEDCOM formatted data.
"""
self.invalidate_cache()
self.__root_element = RootElement()
@@ -205,18 +195,12 @@ def parse(self, gedcom_stream, strict=True):
# Private methods
@staticmethod
- def __parse_line(line_number, line, last_element, strict=True):
- """Parse a line from a GEDCOM 5.5 formatted document
+ def __parse_line(line_number: int, line: str, last_element: Element,
+ strict: bool = True) -> Element:
+ """Parse a line from a GEDCOM formatted document.
Each line should have the following (bracketed items optional):
level + ' ' + [pointer + ' ' +] tag + [' ' + line_value]
-
- :type line_number: int
- :type line: str
- :type last_element: Element
- :type strict: bool
-
- :rtype: Element
"""
# Level must start with non-negative int, no leading zeros.
@@ -305,10 +289,8 @@ def __parse_line(line_number, line, last_element, strict=True):
return element
- def __build_list(self, element, element_list):
- """Recursively add elements to a list containing elements
- :type element: Element
- :type element_list: list of Element
+ def __build_list(self, element: Element, element_list: List[Element]):
+ """Recursively add elements to a list containing elements.
"""
element_list.append(element)
for child in element.get_child_elements():
@@ -316,10 +298,9 @@ def __build_list(self, element, element_list):
# Methods for analyzing individuals and relationships between individuals
- def get_marriages(self, individual):
- """Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
- :type individual: IndividualElement
- :rtype: tuple
+ def get_marriages(self, individual: IndividualElement) -> Tuple[str, str]:
+ """Returns a list of marriages of an individual formatted as a tuple:
+ (`str` date, `str` place)
"""
marriages = []
if not isinstance(individual, IndividualElement):
@@ -341,10 +322,8 @@ def get_marriages(self, individual):
marriages.append((date, place))
return marriages
- def get_marriage_years(self, individual):
- """Returns a list of marriage years (as integers) for an individual
- :type individual: IndividualElement
- :rtype: list of int
+ def get_marriage_years(self, individual: IndividualElement) -> List[int]:
+ """Returns a list of marriage years for an individual.
"""
dates = []
@@ -358,20 +337,18 @@ def get_marriage_years(self, individual):
for family in families:
for child in family.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value().split()[-1]
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value().split()[-1]
try:
dates.append(int(date))
except ValueError:
pass
return dates
- def marriage_year_match(self, individual, year):
- """Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
- :type individual: IndividualElement
- :type year: int
- :rtype: bool
+ def marriage_year_match(self, individual: IndividualElement, year: int) -> bool:
+ """Checks if one of the marriage years of an individual matches the supplied year.
+ Year is an integer.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -381,12 +358,10 @@ def marriage_year_match(self, individual, year):
years = self.get_marriage_years(individual)
return year in years
- def marriage_range_match(self, individual, from_year, to_year):
- """Check if one of the marriage years of an individual is in a given range. Years are integers.
- :type individual: IndividualElement
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def marriage_range_match(self, individual: IndividualElement,
+ from_year: int, to_year: int) -> bool:
+ """Check if one of the marriage years of an individual is in a given range.
+ Years are integers.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -399,14 +374,15 @@ def marriage_range_match(self, individual, from_year, to_year):
return True
return False
- def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
- """Return family elements listed for an individual
- family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
- :type individual: IndividualElement
- :type family_type: str
- :rtype: list of FamilyElement
+ def get_families(self, individual: IndividualElement,
+ family_type: str = tags.GEDCOM_TAG_FAMILY_SPOUSE) -> List[FamilyElement]:
+ """Return family elements listed for an individual.
+
+ Optional argument `family_type` can be used to return specific subsets:
+
+ `tags.GEDCOM_TAG_FAMILY_SPOUSE`: Default, families where the individual is a spouse.
+
+ `tags.GEDCOM_TAG_FAMILY_CHILD`: Families where the individual is a child.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -425,13 +401,15 @@ def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
return families
- def get_ancestors(self, individual, ancestor_type="ALL"):
- """Return elements corresponding to ancestors of an individual
- Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
- used to specify only natural (genetic) ancestors.
- :type individual: IndividualElement
- :type ancestor_type: str
- :rtype: list of Element
+ def get_ancestors(self, individual: IndividualElement,
+ ancestor_type: str = "ALL") -> List[Element]:
+ """Return elements corresponding to ancestors of an individual.
+
+ Optional argument `ancestor_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all ancestors.
+
+ "NAT": Return only natural (genetic) ancestors.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -447,13 +425,15 @@ def get_ancestors(self, individual, ancestor_type="ALL"):
return ancestors
- def get_parents(self, individual, parent_type="ALL"):
- """Return elements corresponding to parents of an individual
- Optional parent_type. Default "ALL" returns all parents. "NAT" can be
- used to specify only natural (genetic) parents.
- :type individual: IndividualElement
- :type parent_type: str
- :rtype: list of IndividualElement
+ def get_parents(self, individual: IndividualElement,
+ parent_type: str = "ALL") -> List[IndividualElement]:
+ """Return elements corresponding to parents of an individual.
+
+ Optional argument `parent_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all parents.
+
+ "NAT": Return only natural (genetic) parents.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -473,19 +453,23 @@ def get_parents(self, individual, parent_type="ALL"):
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ parents += self.get_family_members(family,
+ tags.GEDCOM_TAG_WIFE)
elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
+ parents += self.get_family_members(family,
+ tags.GEDCOM_TAG_HUSBAND)
else:
parents += self.get_family_members(family, "PARENTS")
return parents
- def find_path_to_ancestor(self, descendant, ancestor, path=None):
- """Return path from descendant to ancestor
+ def find_path_to_ancestor(self, descendant: IndividualElement,
+ ancestor: IndividualElement, path: str = None):
+ """Return path from descendant to ancestor.
:rtype: object
"""
- if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
+ if not isinstance(descendant, IndividualElement) and isinstance(ancestor,
+ IndividualElement):
raise NotAnActualIndividualError(
"Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
@@ -495,26 +479,30 @@ def find_path_to_ancestor(self, descendant, ancestor, path=None):
if path[-1].get_pointer() == ancestor.get_pointer():
return path
- else:
- parents = self.get_parents(descendant, "NAT")
- for parent in parents:
- potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
- if potential_path is not None:
- return potential_path
+
+ parents = self.get_parents(descendant, "NAT")
+ for parent in parents:
+ potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
+ if potential_path is not None:
+ return potential_path
return None
- def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
- """Return array of family members: individual, spouse, and children
+ def get_family_members(self, family: FamilyElement,
+ members_type: str = FAMILY_MEMBERS_TYPE_ALL) -> List[IndividualElement]:
+ """Return array of family members: individual, spouse, and children.
+
Optional argument `members_type` can be used to return specific subsets:
+
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
+
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
+
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
+
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
- :type family: FamilyElement
- :type members_type: str
- :rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
@@ -547,9 +535,9 @@ def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
# Other methods
- def to_gedcom_string(self, recursive=False):
- """Formats all elements and optionally all of the sub-elements into a GEDCOM string
- :type recursive: bool
+ def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats all elements and optionally all of the sub-elements into a
+ GEDCOM string.
"""
is_gte_python_3 = version_info[0] >= 3
output = '' if is_gte_python_3 else b''
@@ -563,13 +551,10 @@ def to_gedcom_string(self, recursive=False):
return output
def print_gedcom(self):
- """Write GEDCOM data to stdout"""
- from sys import stdout
+ """Write GEDCOM data to stdout."""
self.save_gedcom(stdout)
- def save_gedcom(self, open_file, recursive=True):
- """Save GEDCOM data to a file
- :type open_file: file
- :type recursive: bool
+ def save_gedcom(self, open_file: IO, recursive: bool = True):
+ """Save GEDCOM data to a file.
"""
open_file.write(self.to_gedcom_string(recursive))
diff --git a/gedcom/reader.py b/gedcom/reader.py
index e52bca2..cac6727 100644
--- a/gedcom/reader.py
+++ b/gedcom/reader.py
@@ -28,9 +28,11 @@
"""
Module containing a `gedcom.reader.Reader` with higher order methods than the
-base `gedcom.parser.Parser`
+base `gedcom.parser.Parser` for extracting records as structured data.
"""
+from typing import Union
+
from gedcom.parser import Parser
from gedcom.element.header import HeaderElement
from gedcom.element.individual import IndividualElement
@@ -68,15 +70,14 @@
class Reader(Parser):
- """Simple wrapper class around the core parser with simple methods for
+ """Simple wrapper around the core `gedcom.parser.Parser` with methods for
extracting parsed records as structured data.
"""
- def get_records_by_type(self, record_type, output='list'):
- """Return either a list or dictionary with all the requested records
- :type: record_type: str
- :type: output: str
- :rtype: list or dict
+ def get_records_by_type(self, record_type: str,
+ return_output_as_list: bool = True) -> Union[list, dict]:
+ """Return either a list or dictionary with all of the requested records for the
+ given `gedcom.records` record type.
"""
record_list = []
record_dict = {}
@@ -84,7 +85,7 @@ def get_records_by_type(self, record_type, output='list'):
for element in self.get_root_child_elements():
if isinstance(element, ELEMENT_TYPES[record_type]):
record = element.get_record()
- if output == 'list':
+ if return_output_as_list:
record_list.append(record)
else:
if RECORD_KEYS[record_type] is not None:
@@ -92,19 +93,18 @@ def get_records_by_type(self, record_type, output='list'):
else:
record_dict.update({'@HEAD@': record})
- if output == 'list':
+ if return_output_as_list:
return record_list
return record_dict
- def get_all_records(self, entries='list'):
- """Return a dictionary with all the requested records
- :type: entries: str
- :rtype: dict
- """
+ def get_all_records(self, return_entries_as_list: bool = True) -> dict:
+ """Return a dictionary with all of the available records in the GEDCOM broken
+ down by record type."""
record_dict = {}
+
for key in RECORD_KEYS:
- if entries == 'list':
+ if return_entries_as_list:
record_dict.update({key: []})
else:
record_dict.update({key: {}})
@@ -113,7 +113,7 @@ def get_all_records(self, entries='list'):
for key in ELEMENT_TYPES:
if isinstance(element, ELEMENT_TYPES[key]):
record = element.get_record()
- if entries == 'list':
+ if return_entries_as_list:
record_dict[key].append(record)
else:
if key != 'header':
diff --git a/gedcom/standards.py b/gedcom/standards.py
index 43dabfd..7bbd9b1 100644
--- a/gedcom/standards.py
+++ b/gedcom/standards.py
@@ -26,17 +26,19 @@
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""The official FamilySearch 5.5 standard"""
+"""Module containing links to the documentation for the various GEDCOM standards."""
+
GEDCOM_5_5 = "https://edge.fscdn.org/assets/img/documents/" + \
"gedcom55-82e1509bd8dbe7477e3b500e4f62c240.pdf"
+"""The official FamilySearch GEDCOM 5.5 Standard."""
-"""The official FamilySearch 5.5.1 standard"""
GEDCOM_5_5_1 = "https://edge.fscdn.org/assets/img/documents/" + \
"ged551-5bac5e57fe88dd37df0e153d9c515335.pdf"
+"""The official FamilySearch GEDCOM 5.5.1 Standard."""
-"""The GEDCOM-L working group 5.5.1 addendum"""
GEDCOM_5_5_1_GEDCOM_L_ADDENDUM = "https://genealogy.net/GEDCOM/" + \
"GEDCOM551%20GEDCOM-L%20Addendum-R1.pdf"
+"""The GEDCOM-L working group GEDCOM 5.5.1 Addendum."""
-"""The gedcom.org 5.5.5 specification with annotations"""
GEDCOM_5_5_5 = "https://www.gedcom.org/specs/GEDCOM555.zip"
+"""The gedcom.org GEDCOM 5.5.5 Specification With Annotations."""
diff --git a/gedcom/subparsers/address_structure.py b/gedcom/subparsers/address_structure.py
index bc18eea..873c8c4 100644
--- a/gedcom/subparsers/address_structure.py
+++ b/gedcom/subparsers/address_structure.py
@@ -21,14 +21,15 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the ADDRESS_STRUCTURE embedded record.
+Substructure parser for a `ADDRESS_STRUCTURE` embedded record.
-Note this is usually referenced as part of a larger structure and the
-`gedcom.tags.GEDCOM_TAG_ADDRESS` tag is at the same level as some of
+This is referenced as part of a larger structure so there is no anchor tag.
+The `gedcom.tags.GEDCOM_TAG_ADDRESS` tag is at the same level as some of
the other parts of this structure.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
ADDRESS_TAGS = {
tags.GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE: 'addresse',
@@ -49,9 +50,10 @@
}
-def address_structure(element):
- """Parses and extracts the ADDRESS_STRUCTURE
- :rtype: dict
+def address_structure(element: Element) -> dict:
+ """Parses and extracts a `ADDRESS_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'address': '',
diff --git a/gedcom/subparsers/association_structure.py b/gedcom/subparsers/association_structure.py
index 53e5891..45dd76e 100644
--- a/gedcom/subparsers/association_structure.py
+++ b/gedcom/subparsers/association_structure.py
@@ -21,18 +21,21 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the ASSOCIATION_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_ASSOCIATES` tag.
+Substructure parser for the `ASSOCIATION_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_ASSOCIATES` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
-def association_structure(element):
- """Parses and extracts the ASSOCIATION_STRUCTURE
- :rtype: dict
+def association_structure(element: Element) -> dict:
+ """Parses and extracts the `ASSOCIATION_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_ASSOCIATES` tag.
"""
record = {
'key_to_individual': element.get_value(),
diff --git a/gedcom/subparsers/change_date.py b/gedcom/subparsers/change_date.py
index d40b771..f53823d 100644
--- a/gedcom/subparsers/change_date.py
+++ b/gedcom/subparsers/change_date.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the CHANGE_DATE record identified by the
-`gedcom.tags.GEDCOM_TAG_CHANGE` tag.
+Substructure parser for a `CHANGE_DATE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_CHANGE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def change_date(element):
- """Parses and extracts the CHANGE_DATE
- :rtype: dict
+def change_date(element: Element) -> dict:
+ """Parses and extracts a `CHANGE_DATE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_CHANGE` tag.
"""
record = {
'date': '',
diff --git a/gedcom/subparsers/child_to_family_link.py b/gedcom/subparsers/child_to_family_link.py
index 1ced20a..8f63141 100644
--- a/gedcom/subparsers/child_to_family_link.py
+++ b/gedcom/subparsers/child_to_family_link.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the CHILD_TO_FAMILY_LINK record identified by the
-`gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` tag.
+Substructure parser for a `CHILD_TO_FAMILY_LINK` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def child_to_family_link(element):
- """Parses and extracts the CHILD_TO_FAMILY_LINK
- :rtype: dict
+def child_to_family_link(element: Element) -> dict:
+ """Parses and extracts a `CHILD_TO_FAMILY_LINK` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` tag.
"""
record = {
'key_to_family': element.get_value(),
diff --git a/gedcom/subparsers/event_detail.py b/gedcom/subparsers/event_detail.py
index 00333ad..2dac099 100644
--- a/gedcom/subparsers/event_detail.py
+++ b/gedcom/subparsers/event_detail.py
@@ -21,11 +21,13 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the EVENT_DETAIL embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `EVENT_DETAIL` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.place_structure import place_structure
from gedcom.subparsers.address_structure import address_structure
from gedcom.subparsers.note_structure import note_structure
@@ -42,9 +44,10 @@
}
-def event_detail(element):
- """Parses and extracts the EVENT_DETAIL
- :rtype: dict
+def event_detail(element: Element) -> dict:
+ """Parses and extracts a `EVENT_DETAIL` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'type': '',
diff --git a/gedcom/subparsers/family_event_detail.py b/gedcom/subparsers/family_event_detail.py
index ef17927..4b1ba9b 100644
--- a/gedcom/subparsers/family_event_detail.py
+++ b/gedcom/subparsers/family_event_detail.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `FAMILY_EVENT_DETAIL` emdedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.event_detail import event_detail
-def family_event_detail(element):
- """Parses and extracts the FAMILY_EVENT_DETAIL
- :rtype: dict
+def family_event_detail(element: Element) -> dict:
+ """Parses and extracts a `FAMILY_EVENT_DETAIL` structure.
+
+ The `element` shouldbe the parent that contains it.
"""
record = event_detail(element)
record['husband_age'] = ''
diff --git a/gedcom/subparsers/family_event_structure.py b/gedcom/subparsers/family_event_structure.py
index b243115..1dac1af 100644
--- a/gedcom/subparsers/family_event_structure.py
+++ b/gedcom/subparsers/family_event_structure.py
@@ -21,11 +21,15 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `FAMILY_EVENT_STRUCTURE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.family_event_detail import family_event_detail
EVENT_TAGS = {
@@ -44,9 +48,10 @@
}
-def family_event_structure(element):
- """Parses and extracts the FAMILY_EVENT_STRUCTURE
- :rtype: dict
+def family_event_structure(element: Element) -> List[dict]:
+ """Parses and extracts a `FAMILY_EVENT_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/gedcom/subparsers/individual_attribute_structure.py b/gedcom/subparsers/individual_attribute_structure.py
index 920ede4..43a2d0f 100644
--- a/gedcom/subparsers/individual_attribute_structure.py
+++ b/gedcom/subparsers/individual_attribute_structure.py
@@ -21,11 +21,15 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record. As
-this is referenced in place as part of another structure there is no identifier tag.
+Substructure parser for the `INDIVIDUAL_ATTRIBUTE_STRUCTURE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.individual_event_detail import individual_event_detail
ATTRIBUTE_TAGS = {
@@ -47,9 +51,10 @@
}
-def individual_attribute_structure(element):
- """Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
- :rtype: dict
+def individual_attribute_structure(element: Element) -> List[dict]:
+ """Parses and extracts the `INDIVIDUAL_ATTRIBUTE_STRUCTURE` structures.
+
+ The `element` should be the parent that contains them.
"""
records = []
for child in element.get_child_elements():
diff --git a/gedcom/subparsers/individual_event_detail.py b/gedcom/subparsers/individual_event_detail.py
index 09e4cfe..58e55a3 100644
--- a/gedcom/subparsers/individual_event_detail.py
+++ b/gedcom/subparsers/individual_event_detail.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the INDIVIDUAL_EVENT_DETAIL emdedded record. As this
-is referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `INDIVIDUAL_EVENT_DETAIL` emdedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.event_detail import event_detail
-def individual_event_detail(element):
- """Parses and extracts INDIVIDUAL_EVENT_DETAIL
- :rtype: dict
+def individual_event_detail(element: Element) -> dict:
+ """Parses and extracts a `INDIVIDUAL_EVENT_DETAIL` structure.
+
+ The `element` should be the parent that contains it.
"""
record = event_detail(element)
record['age'] = ''
diff --git a/gedcom/subparsers/individual_event_structure.py b/gedcom/subparsers/individual_event_structure.py
index ffa01e2..5304a61 100644
--- a/gedcom/subparsers/individual_event_structure.py
+++ b/gedcom/subparsers/individual_event_structure.py
@@ -21,11 +21,15 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the INDIVIDUAL_EVENT_STRUCTURE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `INDIVIDUAL_EVENT_STRUCTURE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.individual_event_detail import individual_event_detail
EVENT_TAGS = {
@@ -61,9 +65,10 @@
}
-def individual_event_structure(element):
- """Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
- :rtype: dict
+def individual_event_structure(element: Element) -> List[dict]:
+ """Parses and extracts a `INDIVIDUAL_EVENT_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/gedcom/subparsers/lds_individual_ordinance.py b/gedcom/subparsers/lds_individual_ordinance.py
index 35c0aae..2588558 100644
--- a/gedcom/subparsers/lds_individual_ordinance.py
+++ b/gedcom/subparsers/lds_individual_ordinance.py
@@ -21,11 +21,15 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the LDS_INDIVIDUAL_ORDINANCE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `LDS_INDIVIDUAL_ORDINANCE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
@@ -44,9 +48,10 @@
}
-def lds_individual_ordinance(element):
- """Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
- :rtype: dict
+def lds_individual_ordinance(element: Element) -> List[dict]:
+ """Parses and extracts a `LDS_INDIVIDUAL_ORDINANCE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/gedcom/subparsers/lds_spouse_sealing.py b/gedcom/subparsers/lds_spouse_sealing.py
index 69a8657..cdc4545 100644
--- a/gedcom/subparsers/lds_spouse_sealing.py
+++ b/gedcom/subparsers/lds_spouse_sealing.py
@@ -21,11 +21,15 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `LDS_SPOUSE_SEALING` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
@@ -37,9 +41,10 @@
}
-def lds_spouse_sealing(element):
- """Parses and extracts the LDS_SPOUSE_SEALING
- :rtype: dict
+def lds_spouse_sealing(element: Element) -> List[dict]:
+ """Parses and extracts a `LDS_SPOUSE_SEALING` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/gedcom/subparsers/multimedia_link.py b/gedcom/subparsers/multimedia_link.py
index cc4ccc9..3e0bc3f 100644
--- a/gedcom/subparsers/multimedia_link.py
+++ b/gedcom/subparsers/multimedia_link.py
@@ -21,11 +21,13 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the MULTIMEDIA_LINK record identified by the
-`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
+Substructure parser for a `MULTIMEDIA_LINK` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_OBJECT` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
MEDIA_TAGS = {
tags.GEDCOM_TAG_FILE: 'file',
@@ -37,9 +39,10 @@
}
-def multimedia_link(element):
- """Parse and extract a MULTIMEDIA_LINK
- :rtype: dict
+def multimedia_link(element: Element) -> dict:
+ """Parse and extract a `MULTIMEDIA_LINK` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_OBJECT` tag.
"""
record = {
'key_to_object': element.get_value(),
diff --git a/gedcom/subparsers/note_structure.py b/gedcom/subparsers/note_structure.py
index 0ce65cd..45f1c52 100644
--- a/gedcom/subparsers/note_structure.py
+++ b/gedcom/subparsers/note_structure.py
@@ -21,14 +21,18 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the NOTE_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_NOTE` tag.
+Substructure parser for a `NOTE_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_NOTE` tag.
"""
+from gedcom.element.element import Element
+
+
+def note_structure(element: Element) -> dict:
+ """Parse and extract a `NOTE_STRUCTURE` structure.
-def note_structure(element):
- """Parse and extract a NOTE_STRUCTURE
- :rtype: dict
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_NOTE` tag.
"""
record = {
'key_to_note': element.get_value(),
diff --git a/gedcom/subparsers/personal_name_pieces.py b/gedcom/subparsers/personal_name_pieces.py
index 1745450..d7c78e6 100644
--- a/gedcom/subparsers/personal_name_pieces.py
+++ b/gedcom/subparsers/personal_name_pieces.py
@@ -21,11 +21,13 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
-referenced in place in part of another structure there is no identifier tag.
+Substructure parser for a `PERSONAL_NAME_PIECES` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
@@ -40,9 +42,10 @@
}
-def personal_name_pieces(element):
- """Parse and extract PERSONAL_NAME_PIECES
- :rtype: dict
+def personal_name_pieces(element: Element) -> dict:
+ """Parse and extract a `PERSONAL_NAME_PIECES` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'prefix': '',
diff --git a/gedcom/subparsers/personal_name_structure.py b/gedcom/subparsers/personal_name_structure.py
index ec63a9b..c20fd5b 100644
--- a/gedcom/subparsers/personal_name_structure.py
+++ b/gedcom/subparsers/personal_name_structure.py
@@ -21,17 +21,26 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the PERSONAL_NAME_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_NAME` tag.
+Substructure parser for a `PERSONAL_NAME_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_NAME` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.personal_name_pieces import personal_name_pieces
-def extract_name(element):
- """Parse and extract name record in a PERSONAL_NAME_STRUCTURE
- :rtype: dict
+def extract_name(element: Element) -> dict:
+ """Parse and extract a `NAME` for a `PERSONAL_NAME_STRUCTURE` structure.
+
+ The `element` should contain one of the name tags:
+
+ `gedcom.tags.GEDCOM_TAG_NAME`
+
+ `gedcom.tags.GEDCOM_TAG_PHONETIC`
+
+ `gedcom.tags.GEDCOM_TAG_ROMANIZED`
"""
record = {
'name': '',
@@ -46,9 +55,10 @@ def extract_name(element):
return record
-def personal_name_structure(element):
- """Parse and extract a PERSONAL_NAME_STRUCTURE
- :rtype: dict
+def personal_name_structure(element: Element) -> dict:
+ """Parse and extract a `PERSONAL_NAME_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_NAME` tag.
"""
record = extract_name(element)
record['phonetic'] = []
diff --git a/gedcom/subparsers/place_structure.py b/gedcom/subparsers/place_structure.py
index 94b02ad..13ac917 100644
--- a/gedcom/subparsers/place_structure.py
+++ b/gedcom/subparsers/place_structure.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the PLACE_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_PLACE` tag.
+Substructure parser for a `PLACE_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_PLACE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def place_structure(element):
- """Parse and extract a PLACE_STRUCTURE
- :rtype: dict
+def place_structure(element: Element) -> dict:
+ """Parse and extract a `PLACE_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_PLACE` tag.
"""
record = {
'name': element.get_value(),
diff --git a/gedcom/subparsers/source_citation.py b/gedcom/subparsers/source_citation.py
index 8069960..ef61f03 100644
--- a/gedcom/subparsers/source_citation.py
+++ b/gedcom/subparsers/source_citation.py
@@ -21,11 +21,13 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the SOURCE_CITATION record identified by the
-`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
+Substructure parser for a `SOURCE_CITATION` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_SOURCE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.multimedia_link import multimedia_link
from gedcom.subparsers.note_structure import note_structure
@@ -37,9 +39,10 @@
}
-def source_citation(element):
- """Parse and extract a SOURCE_CITATION
- :rtype: dict
+def source_citation(element: Element) -> dict:
+ """Parse and extract a `SOURCE_CITATION` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_SOURCE` tag.
"""
record = {
'key_to_source': element.get_value(),
diff --git a/gedcom/subparsers/source_repository_citation.py b/gedcom/subparsers/source_repository_citation.py
index 4a897b9..dc67f40 100644
--- a/gedcom/subparsers/source_repository_citation.py
+++ b/gedcom/subparsers/source_repository_citation.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the SOURCE_REPOSITORY_CITATION record identified by the
-`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
+Substructure parser for a `SOURCE_REPOSITORY_CITATION` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def source_repository_citation(element):
- """Parse and extract a SOURCE_REPOSITORY_CITATION
- :rtype: dict
+def source_repository_citation(element: Element) -> dict:
+ """Parse and extract a `SOURCE_REPOSITORY_CITATION` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
"""
record = {
'key_to_repository': element.get_value(),
diff --git a/gedcom/subparsers/spouse_to_family_link.py b/gedcom/subparsers/spouse_to_family_link.py
index 1142191..3891c5f 100644
--- a/gedcom/subparsers/spouse_to_family_link.py
+++ b/gedcom/subparsers/spouse_to_family_link.py
@@ -21,17 +21,20 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the SPOUSE_TO_FAMILY_LINK record identified by the
-`gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` tag.
+Substructure parser for a `SPOUSE_TO_FAMILY_LINK` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def spouse_to_family_link(element):
- """Parse and extract a SPOUSE_TO_FAMILY_LINK
- :rtype: dict
+def spouse_to_family_link(element: Element) -> dict:
+ """Parse and extract a `SPOUSE_TO_FAMILY_LINK` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` tag.
"""
record = {
'key_to_family': element.get_value(),
diff --git a/gedcom/subparsers/user_reference_number.py b/gedcom/subparsers/user_reference_number.py
index ae6e8c4..f87428e 100644
--- a/gedcom/subparsers/user_reference_number.py
+++ b/gedcom/subparsers/user_reference_number.py
@@ -21,16 +21,21 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Parser for a USER_REFERENCE_NUMBER structure identified by the top level
-`gedcom.tags.GEDCOM_TAG_REFERENCE` tag.
+Parser for a `USER_REFERENCE_NUMBER` structure.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_REFERENCE` tag.
+
+This is not a formally documented structure in the standard but it is
+a substructure that repeats itself in a number of record types.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
+def user_reference_number(element: Element) -> dict:
+ """Parse and extract a `USER_REFERENCE_NUMBER` structure.
-def user_reference_number(element):
- """Parse and extract USER_REFERENCE_NUMBER
- :rtype: dict
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_REFERENCE` tag.
"""
record = {
'reference': element.get_value(),
diff --git a/gedcom/tags.py b/gedcom/tags.py
index 9bee8d2..63c6e95 100644
--- a/gedcom/tags.py
+++ b/gedcom/tags.py
@@ -27,21 +27,32 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Standard GEDCOM tags and some common program defined extensions
+Module containing the standard GEDCOM tags and some of the most common program defined extensions.
"""
+GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE = "_NAME"
+"""Value: `_NAME`
+
+Name of addresse in a `gedcom.tags.GEDCOM_TAG_ADDRESS` structure.
+
+5.5.1 GEDCOM-L Addendum."""
+
GEDCOM_PROGRAM_DEFINED_TAG_ADMINISTRATIVE_ID = "_AIDN"
"""Value: `_AIDN`
Identifier for a location with the intention of an administrative authority,
-e.g. community identifier. GEDCOM-L Addendum."""
+e.g. community identifier.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_APID = "_APID"
"""Value: `_APID`
Ancestry page identifier. For a citation, points to the page in a Ancestry
database for the record supporting the citation. For a source record it
-points to the database as a whole."""
+points to the database as a whole.
+
+Ancestry.com Extension."""
GEDCOM_PROGRAM_DEFINED_TAG_DCAUSE = "_DCAUSE"
"""Value: `_DCAUSE`
@@ -57,12 +68,13 @@
"""Value: `_DMGD`
A number of ojects, during an ascertainment, e.g. the count of households.
-GEDCOM-L Addendum"""
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_FREL = "_FREL"
"""Value: `_FREL`
-Relationship to a father."""
+Type of relationship between child and the father in a family."""
GEDCOM_PROGRAM_DEFINED_TAG_FUNERAL = "_FUN"
"""Value: `_FUN`
@@ -73,13 +85,17 @@
"""Value: `_GOV`
The official government id of the object in the Historical Place Register /
-Historic Gazeteer. GEDCOM-L Addendum."""
+Historic Gazeteer.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT_TYPE = "_GOVTYPE"
"""Value: `_GOVTYPE`
An integer positive number as defined in the GOV system.
-See http://gov.genealogy.net.net/type/list. GEDCOM-L Addendum."""
+See http://gov.genealogy.net.net/type/list.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON = "_HME"
"""Value: `_HME`
@@ -89,12 +105,16 @@
GEDCOM_PROGRAM_DEFINED_TAG_LOCATION = "_LOC"
"""Value: `_LOC`
-Location data record. GEDCOM-L Addendum."""
+Location data record.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_MAIDENHEAD = "_MAIDENHEAD"
"""Value: `_MAIDENHEAD`
-The maidenhead code. GEDCOM-L Addendum."""
+The maidenhead code.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL = "_MDCL"
"""Value: `_MDCL`
@@ -109,13 +129,7 @@
GEDCOM_PROGRAM_DEFINED_TAG_MREL = "_MREL"
"""Value: `_MREL`
-Relationship to a mother."""
-
-GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE = "_NAME"
-"""Value: `_NAME`
-
-Name of addresse in a `gedcom.tags.GEDCOM_TAG_ADDRESS` structure.
-GEDCOM-L Addendum."""
+Type of relationship between child and the mother in a family."""
GEDCOM_PROGRAM_DEFINED_TAG_PHOTO = "_PHOTO"
"""Value: `_PHOTO`
@@ -127,7 +141,8 @@
"""Value: `_POST`
The official zip code, called ADDRESS_POSTAL_CODE in the standard.
-GEDCOM-L Addendum."""
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_PREFERRED = "_PREF"
"""Value: `_PREF`
@@ -142,19 +157,23 @@
GEDCOM_PROGRAM_DEFINED_TAG_SCHEMA = "_SCHEMA"
"""Value: `_SCHEMA`
-Schema substructure extension to describe user defined tags. GEDCOM-L
-Addendum."""
+Schema substructure extension to describe user defined tags.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_RUFNAME = "_RUFNAME"
"""Value: `_RUFNAME`
An official given name of a German individual used in legal documents.
-GEDCOM-L Addendum."""
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_PROGRAM_DEFINED_TAG_UUID = "_UID"
"""Value: `_UID`
-Universal identification number. GEDCOM-L Addendum."""
+Universal identification number.
+
+5.5.1 GEDCOM-L Addendum."""
GEDCOM_TAG_ABBREVIATION = "ABBR"
"""Value: `ABBR`
From ab32bf3488ed062cb05f0f2b24ca129f37973972 Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 18:12:30 -0400
Subject: [PATCH 22/23] docs: added doc string
---
gedcom/subparsers/__init__.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/gedcom/subparsers/__init__.py b/gedcom/subparsers/__init__.py
index c170727..69162ac 100644
--- a/gedcom/subparsers/__init__.py
+++ b/gedcom/subparsers/__init__.py
@@ -20,6 +20,9 @@
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+"""Module containing parsers for extracting various substructures from the
+different record types as defined in the GEDCOM standard."""
+
__all__ = [
"address_structure",
"association_structure",
From c6e91e00762e292775b66b0841d15c4f320909ed Mon Sep 17 00:00:00 2001
From: Christopher Horn
Date: Sun, 24 May 2020 19:02:44 -0400
Subject: [PATCH 23/23] docs: update docs again
---
docs/gedcom/detect.html | 93 +--
docs/gedcom/element/element.html | 492 ++++++------
docs/gedcom/element/family.html | 26 +-
docs/gedcom/element/header.html | 26 +-
docs/gedcom/element/index.html | 2 +-
docs/gedcom/element/individual.html | 572 ++++++--------
docs/gedcom/element/note.html | 26 +-
docs/gedcom/element/object.html | 26 +-
docs/gedcom/element/repository.html | 26 +-
docs/gedcom/element/root.html | 14 +-
docs/gedcom/element/source.html | 26 +-
docs/gedcom/element/submission.html | 20 +-
docs/gedcom/element/submitter.html | 20 +-
docs/gedcom/errors.html | 24 +-
docs/gedcom/index.html | 18 +-
docs/gedcom/parser.html | 731 ++++++++----------
docs/gedcom/reader.html | 107 ++-
docs/gedcom/records.html | 163 ++++
docs/gedcom/standards.html | 27 +-
docs/gedcom/subparsers/address_structure.html | 35 +-
.../subparsers/association_structure.html | 33 +-
docs/gedcom/subparsers/change_date.html | 33 +-
.../subparsers/child_to_family_link.html | 33 +-
docs/gedcom/subparsers/event_detail.html | 33 +-
.../subparsers/family_event_detail.html | 33 +-
.../subparsers/family_event_structure.html | 35 +-
docs/gedcom/subparsers/index.html | 70 +-
.../individual_attribute_structure.html | 35 +-
.../subparsers/individual_event_detail.html | 33 +-
.../individual_event_structure.html | 35 +-
.../subparsers/lds_individual_ordinance.html | 35 +-
.../gedcom/subparsers/lds_spouse_sealing.html | 35 +-
docs/gedcom/subparsers/multimedia_link.html | 33 +-
docs/gedcom/subparsers/note_structure.html | 34 +-
.../subparsers/personal_name_pieces.html | 33 +-
.../subparsers/personal_name_structure.html | 68 +-
docs/gedcom/subparsers/place_structure.html | 33 +-
docs/gedcom/subparsers/source_citation.html | 33 +-
.../source_repository_citation.html | 33 +-
.../subparsers/spouse_to_family_link.html | 33 +-
.../subparsers/user_reference_number.html | 38 +-
docs/gedcom/tags.html | 6 +-
gedcom/element/element.py | 10 +-
gedcom/subparsers/spouse_to_family_link.py | 2 +-
gedcom/subparsers/user_reference_number.py | 1 +
45 files changed, 1621 insertions(+), 1653 deletions(-)
create mode 100644 docs/gedcom/records.html
diff --git a/docs/gedcom/detect.html b/docs/gedcom/detect.html
index a0aa942..60b9b94 100644
--- a/docs/gedcom/detect.html
+++ b/docs/gedcom/detect.html
@@ -5,7 +5,7 @@
gedcom.detect API documentation
-
+
@@ -20,7 +20,7 @@
Module gedcom.detect
-
Functions to detect GEDCOM encoding and version.
+
Module containing functions for detecting GEDCOM file encoding and version.
Expand source code
@@ -54,9 +54,10 @@
Module gedcom.detect
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Functions to detect GEDCOM encoding and version.
+Module containing functions for detecting GEDCOM file encoding and version.
"""
+from typing import Tuple
import chardet
import ansel
@@ -69,11 +70,8 @@
Module gedcom.detect
def __validate_encoding(file_path, codec):
- """Check the encoding is compatible with the encoding as reported by the `gedcom.tags.GEDCOM_TAG_CHARACTER` header tag.
-
- :type file_path: str
-
- :type codec: str
+ """Check the encoding is compatible with the encoding as reported by the
+ `gedcom.tags.GEDCOM_TAG_CHARACTER` header tag.
"""
with open(file_path, 'r', encoding=codec) as gedcom_data:
for line in gedcom_data:
@@ -95,12 +93,11 @@
Module gedcom.detect
raise GedcomCharacterSetUnsupportedError(errmsg)
-def get_encoding(file_path):
- """Probe a GEDCOM file to determine the encoding and validate it against the encoding reported in the file header by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
-
- :type file_path: str
+def get_encoding(file_path: str) -> str:
+ """Probe a GEDCOM file to determine the encoding and validate it against the encoding
+ as reported in the `HEADER` record by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
- :rtype: str
+ Returns: codec
"""
with open(file_path, 'rb') as gedcom_data:
sample_data = gedcom_data.read(262144)
@@ -131,18 +128,11 @@
Module gedcom.detect
return codec
-def get_version(file_path, codec):
- """Probes a GEDCOM file to identify the version of the standard used as some reported 5.5 files are really 5.5.1. Returns probed version, reported version, reported format
-
- :type file_path: str
-
- :type codec: str
-
- :rtype real_version: str
+def get_version(file_path: str, codec: str) -> Tuple[str, str, str]:
+ """Probe a GEDCOM file to identify the version of the standard used as some reported 5.5
+ files are really 5.5.1.
- :rtype reported_version: str
-
- :rtype reported_format: str
+ Returns: probed version, reported version, reported format
"""
in_gedc_tag = False
gedcom_version = None
@@ -165,13 +155,13 @@
Module gedcom.detect
" not found as expected.\nSee: {0}".format(standards.GEDCOM_5_5_1)
raise GedcomFormatViolationError(errmsg)
- real_version = gedcom_version
+ probed_version = gedcom_version
# UTF was added in the 5.5.1 specification
if gedcom_version == '5.5' and 'utf' in codec:
- real_version = gedcom_version
+ probed_version = gedcom_version
- return real_version, gedcom_version, gedcom_format
+ return probed_version, gedcom_version, gedcom_format
@@ -182,22 +172,21 @@
Probe a GEDCOM file to determine the encoding and validate it against the encoding reported in the file header by the GEDCOM_TAG_CHARACTER tag.
-
:type file_path: str
-
:rtype: str
+
Probe a GEDCOM file to determine the encoding and validate it against the encoding
+as reported in the HEADER record by the GEDCOM_TAG_CHARACTER tag.
+
Returns: codec
Expand source code
-
def get_encoding(file_path):
- """Probe a GEDCOM file to determine the encoding and validate it against the encoding reported in the file header by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
-
- :type file_path: str
+
def get_encoding(file_path: str) -> str:
+ """Probe a GEDCOM file to determine the encoding and validate it against the encoding
+ as reported in the `HEADER` record by the `gedcom.tags.GEDCOM_TAG_CHARACTER` tag.
- :rtype: str
+ Returns: codec
"""
with open(file_path, 'rb') as gedcom_data:
sample_data = gedcom_data.read(262144)
@@ -229,31 +218,21 @@
Probes a GEDCOM file to identify the version of the standard used as some reported 5.5 files are really 5.5.1. Returns probed version, reported version, reported format
-
:type file_path: str
-
:type codec: str
-
:rtype real_version: str
-
:rtype reported_version: str
-
:rtype reported_format: str
+
Probe a GEDCOM file to identify the version of the standard used as some reported 5.5
+files are really 5.5.1.
+
Returns: probed version, reported version, reported format
Expand source code
-
def get_version(file_path, codec):
- """Probes a GEDCOM file to identify the version of the standard used as some reported 5.5 files are really 5.5.1. Returns probed version, reported version, reported format
-
- :type file_path: str
-
- :type codec: str
-
- :rtype real_version: str
-
- :rtype reported_version: str
+
def get_version(file_path: str, codec: str) -> Tuple[str, str, str]:
+ """Probe a GEDCOM file to identify the version of the standard used as some reported 5.5
+ files are really 5.5.1.
- :rtype reported_format: str
+ Returns: probed version, reported version, reported format
"""
in_gedc_tag = False
gedcom_version = None
@@ -276,13 +255,13 @@
Functions
" not found as expected.\nSee: {0}".format(standards.GEDCOM_5_5_1)
raise GedcomFormatViolationError(errmsg)
- real_version = gedcom_version
+ probed_version = gedcom_version
# UTF was added in the 5.5.1 specification
if gedcom_version == '5.5' and 'utf' in codec:
- real_version = gedcom_version
+ probed_version = gedcom_version
- return real_version, gedcom_version, gedcom_format
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Base GEDCOM element
+Base GEDCOM element.
"""
from sys import version_info
+from typing import List
+
from gedcom.helpers import deprecated
import gedcom.tags
class Element(object):
- """GEDCOM element
+ """GEDCOM element.
- Each line in a GEDCOM file is an element with the format
+ Each line in a GEDCOM file is an element with the format:
`level [pointer] tag [value]`
@@ -89,7 +91,8 @@
Module gedcom.element.element
Tags available to an element are seen here: `gedcom.tags`
"""
- def __init__(self, level, pointer, tag, value, crlf="\n", multi_line=True):
+ def __init__(self, level: int, pointer: str, tag: str, value: str,
+ crlf: str = "\n", multi_line: bool = True):
# basic element info
self.__level = level
self.__pointer = pointer
@@ -104,39 +107,33 @@
Module gedcom.element.element
if multi_line:
self.set_multi_line_value(value)
- def get_level(self):
- """Returns the level of this element from within the GEDCOM file
- :rtype: int
+ def get_level(self) -> int:
+ """Returns the level of this element from within the GEDCOM file.
"""
return self.__level
- def get_pointer(self):
- """Returns the pointer of this element from within the GEDCOM file
- :rtype: str
+ def get_pointer(self) -> str:
+ """Returns the pointer of this element from within the GEDCOM file.
"""
return self.__pointer
- def get_tag(self):
- """Returns the tag of this element from within the GEDCOM file
- :rtype: str
+ def get_tag(self) -> str:
+ """Returns the tag of this element from within the GEDCOM file.
"""
return self.__tag
- def get_value(self):
- """Return the value of this element from within the GEDCOM file
- :rtype: str
+ def get_value(self) -> str:
+ """Return the value of this element from within the GEDCOM file.
"""
return self.__value
- def set_value(self, value):
- """Sets the value of this element
- :type value: str
+ def set_value(self, value: str):
+ """Sets the value of this element.
"""
self.__value = value
- def get_multi_line_value(self):
- """Returns the value of this element including concatenations or continuations
- :rtype: str
+ def get_multi_line_value(self) -> str:
+ """Returns the value of this element including concatenations or continuations.
"""
result = self.get_value()
last_crlf = self.__crlf
@@ -150,17 +147,14 @@
Module gedcom.element.element
last_crlf = element.__crlf
return result
- def __available_characters(self):
+ def __available_characters(self) -> int:
"""Get the number of available characters of the elements original string
- :rtype: int
"""
element_characters = len(self.to_gedcom_string())
return 0 if element_characters > 255 else 255 - element_characters
- def __line_length(self, line):
- """@TODO Write docs.
- :type line: str
- :rtype: int
+ def __line_length(self, line: str) -> int:
+ """Return line length.
"""
total_characters = len(line)
available_characters = self.__available_characters()
@@ -173,40 +167,36 @@
Module gedcom.element.element
return available_characters
return available_characters - spaces
- def __set_bounded_value(self, value):
+ def __set_bounded_value(self, value: str) -> int:
"""@TODO Write docs.
- :type value: str
- :rtype: int
"""
line_length = self.__line_length(value)
self.set_value(value[:line_length])
return line_length
- def __add_bounded_child(self, tag, value):
+ def __add_bounded_child(self, tag: str, value: str) -> int:
"""@TODO Write docs.
- :type tag: str
- :type value: str
- :rtype: int
"""
child = self.new_child_element(tag)
return child.__set_bounded_value(value)
- def __add_concatenation(self, string):
+ def __add_concatenation(self, string: str):
"""@TODO Write docs.
- :rtype: str
"""
index = 0
size = len(string)
while index < size:
index += self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONCATENATION, string[index:])
- def set_multi_line_value(self, value):
- """Sets the value of this element, adding concatenation and continuation lines when necessary
- :type value: str
+ def set_multi_line_value(self, value: str):
+ """Sets the value of this element, adding concatenation and continuation lines
+ when necessary.
"""
self.set_value('')
self.get_child_elements()[:] = [child for child in self.get_child_elements() if
- child.get_tag() not in (gedcom.tags.GEDCOM_TAG_CONCATENATION, gedcom.tags.GEDCOM_TAG_CONTINUED)]
+ child.get_tag() not in
+ (gedcom.tags.GEDCOM_TAG_CONCATENATION,
+ gedcom.tags.GEDCOM_TAG_CONTINUED)]
lines = value.splitlines()
if lines:
@@ -218,19 +208,14 @@
Module gedcom.element.element
n = self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONTINUED, line)
self.__add_concatenation(line[n:])
- def get_child_elements(self):
- """Returns the direct child elements of this element
- :rtype: list of Element
+ def get_child_elements(self) -> List['Element']:
+ """Returns the direct child elements of this element.
"""
return self.__children
- def new_child_element(self, tag, pointer="", value=""):
- """Creates and returns a new child element of this element
-
- :type tag: str
- :type pointer: str
- :type value: str
- :rtype: Element
+ def new_child_element(self, tag: str, pointer: str = "",
+ value: str = "") -> 'Element':
+ """Creates and returns a new child element of this element.
"""
from gedcom.element.family import FamilyElement
from gedcom.element.individual import IndividualElement
@@ -244,68 +229,70 @@
Module gedcom.element.element
# Differentiate between the type of the new child element
if tag == gedcom.tags.GEDCOM_TAG_FAMILY:
- child_element = FamilyElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = FamilyElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
- child_element = IndividualElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = IndividualElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_NOTE:
- child_element = NoteElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = NoteElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
- child_element = ObjectElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = ObjectElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_REPOSITORY:
- child_element = RepositoryElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = RepositoryElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SOURCE:
- child_element = SourceElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SourceElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SUBMITTER:
- child_element = SubmitterElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SubmitterElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SUBMISSION:
- child_element = SubmissionElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SubmissionElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_HEADER:
- child_element = HeaderElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = HeaderElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
else:
- child_element = Element(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = Element(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
self.add_child_element(child_element)
return child_element
- def add_child_element(self, element):
- """Adds a child element to this element
-
- :type element: Element
+ def add_child_element(self, element: 'Element'):
+ """Adds a child element to this element.
"""
self.get_child_elements().append(element)
element.set_parent_element(self)
return element
- def get_parent_element(self):
- """Returns the parent element of this element
- :rtype: Element
+ def get_parent_element(self) -> 'Element':
+ """Returns the parent element of this element.
"""
return self.__parent
- def set_parent_element(self, element):
- """Adds a parent element to this element
+ def set_parent_element(self, element: 'Element'):
+ """Adds a parent element to this element.
There's usually no need to call this method manually,
`add_child_element()` calls it automatically.
-
- :type element: Element
"""
self.__parent = element
@deprecated
- def get_individual(self):
- """Returns this element and all of its sub-elements represented as a GEDCOM string
+ def get_individual(self) -> str:
+ """Returns this element and all of its sub-elements represented as a GEDCOM string.
::deprecated:: As of version 1.0.0 use `to_gedcom_string()` method instead
- :rtype: str
"""
return self.to_gedcom_string(True)
- def to_gedcom_string(self, recursive=False):
- """Formats this element and optionally all of its sub-elements into a GEDCOM string
- :type recursive: bool
- :rtype: str
+ def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats this element and optionally all of its sub-elements into a GEDCOM string.
"""
result = str(self.get_level())
@@ -329,7 +316,7 @@
Each line in a GEDCOM file is an element with the format
+
GEDCOM element.
+
Each line in a GEDCOM file is an element with the format:
level [pointer] tag [value]
where level and tag are required, and pointer and value are
optional.
@@ -377,9 +364,9 @@
Classes
Expand source code
class Element(object):
- """GEDCOM element
+ """GEDCOM element.
- Each line in a GEDCOM file is an element with the format
+ Each line in a GEDCOM file is an element with the format:
`level [pointer] tag [value]`
@@ -404,7 +391,8 @@
Classes
Tags available to an element are seen here: `gedcom.tags`
"""
- def __init__(self, level, pointer, tag, value, crlf="\n", multi_line=True):
+ def __init__(self, level: int, pointer: str, tag: str, value: str,
+ crlf: str = "\n", multi_line: bool = True):
# basic element info
self.__level = level
self.__pointer = pointer
@@ -419,39 +407,33 @@
Classes
if multi_line:
self.set_multi_line_value(value)
- def get_level(self):
- """Returns the level of this element from within the GEDCOM file
- :rtype: int
+ def get_level(self) -> int:
+ """Returns the level of this element from within the GEDCOM file.
"""
return self.__level
- def get_pointer(self):
- """Returns the pointer of this element from within the GEDCOM file
- :rtype: str
+ def get_pointer(self) -> str:
+ """Returns the pointer of this element from within the GEDCOM file.
"""
return self.__pointer
- def get_tag(self):
- """Returns the tag of this element from within the GEDCOM file
- :rtype: str
+ def get_tag(self) -> str:
+ """Returns the tag of this element from within the GEDCOM file.
"""
return self.__tag
- def get_value(self):
- """Return the value of this element from within the GEDCOM file
- :rtype: str
+ def get_value(self) -> str:
+ """Return the value of this element from within the GEDCOM file.
"""
return self.__value
- def set_value(self, value):
- """Sets the value of this element
- :type value: str
+ def set_value(self, value: str):
+ """Sets the value of this element.
"""
self.__value = value
- def get_multi_line_value(self):
- """Returns the value of this element including concatenations or continuations
- :rtype: str
+ def get_multi_line_value(self) -> str:
+ """Returns the value of this element including concatenations or continuations.
"""
result = self.get_value()
last_crlf = self.__crlf
@@ -465,17 +447,14 @@
Classes
last_crlf = element.__crlf
return result
- def __available_characters(self):
+ def __available_characters(self) -> int:
"""Get the number of available characters of the elements original string
- :rtype: int
"""
element_characters = len(self.to_gedcom_string())
return 0 if element_characters > 255 else 255 - element_characters
- def __line_length(self, line):
- """@TODO Write docs.
- :type line: str
- :rtype: int
+ def __line_length(self, line: str) -> int:
+ """Return line length.
"""
total_characters = len(line)
available_characters = self.__available_characters()
@@ -488,40 +467,36 @@
Classes
return available_characters
return available_characters - spaces
- def __set_bounded_value(self, value):
+ def __set_bounded_value(self, value: str) -> int:
"""@TODO Write docs.
- :type value: str
- :rtype: int
"""
line_length = self.__line_length(value)
self.set_value(value[:line_length])
return line_length
- def __add_bounded_child(self, tag, value):
+ def __add_bounded_child(self, tag: str, value: str) -> int:
"""@TODO Write docs.
- :type tag: str
- :type value: str
- :rtype: int
"""
child = self.new_child_element(tag)
return child.__set_bounded_value(value)
- def __add_concatenation(self, string):
+ def __add_concatenation(self, string: str):
"""@TODO Write docs.
- :rtype: str
"""
index = 0
size = len(string)
while index < size:
index += self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONCATENATION, string[index:])
- def set_multi_line_value(self, value):
- """Sets the value of this element, adding concatenation and continuation lines when necessary
- :type value: str
+ def set_multi_line_value(self, value: str):
+ """Sets the value of this element, adding concatenation and continuation lines
+ when necessary.
"""
self.set_value('')
self.get_child_elements()[:] = [child for child in self.get_child_elements() if
- child.get_tag() not in (gedcom.tags.GEDCOM_TAG_CONCATENATION, gedcom.tags.GEDCOM_TAG_CONTINUED)]
+ child.get_tag() not in
+ (gedcom.tags.GEDCOM_TAG_CONCATENATION,
+ gedcom.tags.GEDCOM_TAG_CONTINUED)]
lines = value.splitlines()
if lines:
@@ -533,19 +508,14 @@
Classes
n = self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONTINUED, line)
self.__add_concatenation(line[n:])
- def get_child_elements(self):
- """Returns the direct child elements of this element
- :rtype: list of Element
+ def get_child_elements(self) -> List['Element']:
+ """Returns the direct child elements of this element.
"""
return self.__children
- def new_child_element(self, tag, pointer="", value=""):
- """Creates and returns a new child element of this element
-
- :type tag: str
- :type pointer: str
- :type value: str
- :rtype: Element
+ def new_child_element(self, tag: str, pointer: str = "",
+ value: str = "") -> 'Element':
+ """Creates and returns a new child element of this element.
"""
from gedcom.element.family import FamilyElement
from gedcom.element.individual import IndividualElement
@@ -559,68 +529,70 @@
Classes
# Differentiate between the type of the new child element
if tag == gedcom.tags.GEDCOM_TAG_FAMILY:
- child_element = FamilyElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = FamilyElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_INDIVIDUAL:
- child_element = IndividualElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = IndividualElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_NOTE:
- child_element = NoteElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = NoteElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_OBJECT:
- child_element = ObjectElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = ObjectElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_REPOSITORY:
- child_element = RepositoryElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = RepositoryElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SOURCE:
- child_element = SourceElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SourceElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SUBMITTER:
- child_element = SubmitterElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SubmitterElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_SUBMISSION:
- child_element = SubmissionElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = SubmissionElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
elif tag == gedcom.tags.GEDCOM_TAG_HEADER:
- child_element = HeaderElement(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = HeaderElement(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
else:
- child_element = Element(self.get_level() + 1, pointer, tag, value, self.__crlf)
+ child_element = Element(self.get_level() + 1, pointer, tag,
+ value, self.__crlf)
self.add_child_element(child_element)
return child_element
- def add_child_element(self, element):
- """Adds a child element to this element
-
- :type element: Element
+ def add_child_element(self, element: 'Element'):
+ """Adds a child element to this element.
"""
self.get_child_elements().append(element)
element.set_parent_element(self)
return element
- def get_parent_element(self):
- """Returns the parent element of this element
- :rtype: Element
+ def get_parent_element(self) -> 'Element':
+ """Returns the parent element of this element.
"""
return self.__parent
- def set_parent_element(self, element):
- """Adds a parent element to this element
+ def set_parent_element(self, element: 'Element'):
+ """Adds a parent element to this element.
There's usually no need to call this method manually,
`add_child_element()` calls it automatically.
-
- :type element: Element
"""
self.__parent = element
@deprecated
- def get_individual(self):
- """Returns this element and all of its sub-elements represented as a GEDCOM string
+ def get_individual(self) -> str:
+ """Returns this element and all of its sub-elements represented as a GEDCOM string.
::deprecated:: As of version 1.0.0 use `to_gedcom_string()` method instead
- :rtype: str
"""
return self.to_gedcom_string(True)
- def to_gedcom_string(self, recursive=False):
- """Formats this element and optionally all of its sub-elements into a GEDCOM string
- :type recursive: bool
- :rtype: str
+ def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats this element and optionally all of its sub-elements into a GEDCOM string.
"""
result = str(self.get_level())
@@ -644,7 +616,7 @@
def add_child_element(self, element):
- """Adds a child element to this element
-
- :type element: Element
+
def add_child_element(self, element: 'Element'):
+ """Adds a child element to this element.
"""
self.get_child_elements().append(element)
element.set_parent_element(self)
@@ -688,72 +657,64 @@
Returns this element and all of its sub-elements represented as a GEDCOM string
-::deprecated:: As of version 1.0.0 use to_gedcom_string() method instead
-:rtype: str
+
Returns this element and all of its sub-elements represented as a GEDCOM string.
+::deprecated:: As of version 1.0.0 use to_gedcom_string() method instead
Expand source code
@deprecated
-def get_individual(self):
- """Returns this element and all of its sub-elements represented as a GEDCOM string
+def get_individual(self) -> str:
+ """Returns this element and all of its sub-elements represented as a GEDCOM string.
::deprecated:: As of version 1.0.0 use `to_gedcom_string()` method instead
- :rtype: str
"""
return self.to_gedcom_string(True)
-def get_level(self)
+def get_level(self) -> int
-
Returns the level of this element from within the GEDCOM file
-:rtype: int
+
Returns the level of this element from within the GEDCOM file.
Expand source code
-
def get_level(self):
- """Returns the level of this element from within the GEDCOM file
- :rtype: int
+
def get_level(self) -> int:
+ """Returns the level of this element from within the GEDCOM file.
"""
return self.__level
Returns the value of this element including concatenations or continuations
-:rtype: str
+
Returns the value of this element including concatenations or continuations.
Expand source code
-
def get_multi_line_value(self):
- """Returns the value of this element including concatenations or continuations
- :rtype: str
+
def get_multi_line_value(self) -> str:
+ """Returns the value of this element including concatenations or continuations.
"""
result = self.get_value()
last_crlf = self.__crlf
@@ -769,93 +730,77 @@
Methods
-def get_parent_element(self)
+def get_parent_element(self) -> Element
-
Returns the parent element of this element
-:rtype: Element
+
Returns the parent element of this element.
Expand source code
-
def get_parent_element(self):
- """Returns the parent element of this element
- :rtype: Element
+
def get_parent_element(self) -> 'Element':
+ """Returns the parent element of this element.
"""
return self.__parent
Creates and returns a new child element of this element.
Expand source code
-
def new_child_element(self, tag, pointer="", value=""):
- """Creates and returns a new child element of this element
-
- :type tag: str
- :type pointer: str
- :type value: str
- :rtype: Element
+
def new_child_element(self, tag: str, pointer: str = "",
+ value: str = "") -> 'Element':
+ """Creates and returns a new child element of this element.
"""
from gedcom.element.family import FamilyElement
from gedcom.element.individual import IndividualElement
@@ -869,25 +814,35 @@
Sets the value of this element, adding concatenation and continuation lines when necessary
-:type value: str
+
Sets the value of this element, adding concatenation and continuation lines
+when necessary.
Expand source code
-
def set_multi_line_value(self, value):
- """Sets the value of this element, adding concatenation and continuation lines when necessary
- :type value: str
+
def set_multi_line_value(self, value: str):
+ """Sets the value of this element, adding concatenation and continuation lines
+ when necessary.
"""
self.set_value('')
self.get_child_elements()[:] = [child for child in self.get_child_elements() if
- child.get_tag() not in (gedcom.tags.GEDCOM_TAG_CONCATENATION, gedcom.tags.GEDCOM_TAG_CONTINUED)]
+ child.get_tag() not in
+ (gedcom.tags.GEDCOM_TAG_CONCATENATION,
+ gedcom.tags.GEDCOM_TAG_CONTINUED)]
lines = value.splitlines()
if lines:
@@ -924,60 +881,51 @@
There's usually no need to call this method manually,
-add_child_element() calls it automatically.
-
:type element: Element
+add_child_element() calls it automatically.
Expand source code
-
def set_parent_element(self, element):
- """Adds a parent element to this element
+
def set_parent_element(self, element: 'Element'):
+ """Adds a parent element to this element.
There's usually no need to call this method manually,
`add_child_element()` calls it automatically.
-
- :type element: Element
"""
self.__parent = element
Formats this element and optionally all of its sub-elements into a GEDCOM string
-:type recursive: bool
-:rtype: str
+
Formats this element and optionally all of its sub-elements into a GEDCOM string.
Expand source code
-
def to_gedcom_string(self, recursive=False):
- """Formats this element and optionally all of its sub-elements into a GEDCOM string
- :type recursive: bool
- :rtype: str
+
def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats this element and optionally all of its sub-elements into a GEDCOM string.
"""
result = str(self.get_level())
diff --git a/docs/gedcom/element/family.html b/docs/gedcom/element/family.html
index 11fab4a..4c91975 100644
--- a/docs/gedcom/element/family.html
+++ b/docs/gedcom/element/family.html
@@ -82,12 +82,11 @@
Module gedcom.element.family
class FamilyElement(Element):
"""Element associated with a `FAM_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_FAMILY
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_family': self.get_pointer(),
@@ -170,7 +169,7 @@
class FamilyElement(Element):
"""Element associated with a `FAM_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_FAMILY
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_family': self.get_pointer(),
@@ -264,18 +262,16 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_family': self.get_pointer(),
diff --git a/docs/gedcom/element/header.html b/docs/gedcom/element/header.html
index 5b3ce5e..b3d0a70 100644
--- a/docs/gedcom/element/header.html
+++ b/docs/gedcom/element/header.html
@@ -79,12 +79,11 @@
Module gedcom.element.header
class HeaderElement(Element):
"""Element associated with a `HEADER`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_HEADER
- def get_record(self):
- """Parse and return the full record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'source': '',
@@ -200,7 +199,7 @@
class HeaderElement(Element):
"""Element associated with a `HEADER`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_HEADER
- def get_record(self):
- """Parse and return the full record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'source': '',
@@ -327,18 +325,16 @@
Parse and return the full record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the full record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'source': '',
diff --git a/docs/gedcom/element/index.html b/docs/gedcom/element/index.html
index a15aee5..22738d6 100644
--- a/docs/gedcom/element/index.html
+++ b/docs/gedcom/element/index.html
@@ -79,7 +79,7 @@
`gedcom.tags.GEDCOM_TAG_INDIVIDUAL` tag.
"""
+from typing import Tuple, List
import re as regex
+
import gedcom.tags as tags
from gedcom.element.element import Element
from gedcom.subparsers.personal_name_structure import personal_name_structure
@@ -89,12 +91,11 @@
Module gedcom.element.individual
class IndividualElement(Element):
"""Element associated with an `INDIVIDUAL_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_INDIVIDUAL
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_individual': self.get_pointer(),
@@ -182,9 +183,8 @@
Module gedcom.element.individual
return record
- def is_deceased(self):
- """Checks if this individual is deceased
- :rtype: bool
+ def is_deceased(self) -> bool:
+ """Checks if this individual is deceased.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_DEATH:
@@ -192,9 +192,8 @@
Module gedcom.element.individual
return False
- def is_child(self):
- """Checks if this element is a child of a family
- :rtype: bool
+ def is_child(self) -> bool:
+ """Checks if this element is a child of a family.
"""
found_child = False
@@ -204,9 +203,8 @@
Module gedcom.element.individual
return found_child
- def is_private(self):
- """Checks if this individual is marked private
- :rtype: bool
+ def is_private(self) -> bool:
+ """Checks if this individual is marked private.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
@@ -216,9 +214,8 @@
# If we reach here we are probably returning empty strings
return given_name, surname
- def get_all_names(self):
- """Return all names"""
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
+ def get_all_names(self) -> List[str]:
+ """Return all names."""
+ return [a.get_value() for a in self.get_child_elements()
+ if a.get_tag() == tags.GEDCOM_TAG_NAME]
- def surname_match(self, surname_to_match):
- """Matches a string with the surname of an individual
- :type surname_to_match: str
- :rtype: bool
+ def surname_match(self, surname_to_match: str) -> bool:
+ """Matches a string with the surname of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(surname_to_match, surname, regex.IGNORECASE)
@deprecated
- def given_match(self, name):
- """Matches a string with the given name of an individual
+ def given_match(self, name: str) -> bool:
+ """Matches a string with the given name of an individual.
::deprecated:: As of version 1.0.0 use `given_name_match()` method instead
- :type name: str
- :rtype: bool
"""
return self.given_name_match(name)
- def given_name_match(self, given_name_to_match):
- """Matches a string with the given name of an individual
- :type given_name_to_match: str
- :rtype: bool
+ def given_name_match(self, given_name_to_match: str) -> bool:
+ """Matches a string with the given name of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(given_name_to_match, given_name, regex.IGNORECASE)
- def get_gender(self):
- """Returns the gender of a person in string format
- :rtype: str
+ def get_gender(self) -> str:
+ """Returns the gender of a person in string format.
"""
gender = ""
@@ -300,10 +291,9 @@
Module gedcom.element.individual
return gender
- def get_birth_data(self):
+ def get_birth_data(self) -> Tuple[str, str, List[str]]:
"""Returns the birth data of a person formatted as a tuple:
(`str` date, `str` place, `list` sources)
- :rtype: tuple
"""
date = ""
place = ""
@@ -324,9 +314,8 @@
Module gedcom.element.individual
return date, place, sources
- def get_birth_year(self):
- """Returns the birth year of a person in integer format
- :rtype: int
+ def get_birth_year(self) -> int:
+ """Returns the birth year of a person in integer format.
"""
date = ""
@@ -344,9 +333,9 @@
Module gedcom.element.individual
except ValueError:
return -1
- def get_death_data(self):
- """Returns the death data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
- :rtype: tuple
+ def get_death_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the death data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
"""
date = ""
place = ""
@@ -364,9 +353,8 @@
Module gedcom.element.individual
return date, place, sources
- def get_death_year(self):
- """Returns the death year of a person in integer format
- :rtype: int
+ def get_death_year(self) -> int:
+ """Returns the death year of a person in integer format.
"""
date = ""
@@ -385,16 +373,16 @@
Module gedcom.element.individual
return -1
@deprecated
- def get_burial(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
+ def get_burial(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_burial_data()` method instead
- :rtype: tuple
"""
self.get_burial_data()
- def get_burial_data(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
- :rtype: tuple
+ def get_burial_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
"""
date = ""
place = ""
@@ -416,16 +404,16 @@
Module gedcom.element.individual
return date, place, sources
@deprecated
- def get_census(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
+ def get_census(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_census_data()` method instead
- :rtype: list of tuple
"""
self.get_census_data()
- def get_census_data(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
- :rtype: list of tuple
+ def get_census_data(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
"""
census = []
@@ -451,9 +439,8 @@
Module gedcom.element.individual
return census
- def get_last_change_date(self):
- """Returns the date of when the person data was last changed formatted as a string
- :rtype: str
+ def get_last_change_date(self) -> str:
+ """Returns the date of when the person data was last changed formatted as a string.
"""
date = ""
@@ -465,9 +452,8 @@
Module gedcom.element.individual
return date
- def get_occupation(self):
- """Returns the occupation of a person
- :rtype: str
+ def get_occupation(self) -> str:
+ """Returns the occupation of a person.
"""
occupation = ""
@@ -477,18 +463,13 @@
Module gedcom.element.individual
return occupation
- def birth_year_match(self, year):
- """Returns `True` if the given year matches the birth year of this person
- :type year: int
- :rtype: bool
+ def birth_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the birth year of this person.
"""
return self.get_birth_year() == year
- def birth_range_match(self, from_year, to_year):
- """Checks if the birth year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def birth_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the birth year of a person lies within the given range.
"""
birth_year = self.get_birth_year()
@@ -497,18 +478,13 @@
Module gedcom.element.individual
return False
- def death_year_match(self, year):
- """Returns `True` if the given year matches the death year of this person
- :type year: int
- :rtype: bool
+ def death_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the death year of this person.
"""
return self.get_death_year() == year
- def death_range_match(self, from_year, to_year):
- """Checks if the death year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def death_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the death year of a person lies within the given range.
"""
death_year = self.get_death_year()
@@ -517,8 +493,8 @@
Module gedcom.element.individual
return False
- def criteria_match(self, criteria):
- """Checks if this individual matches all of the given criteria
+ def criteria_match(self, criteria: str) -> bool:
+ """Checks if this individual matches all of the given criteria.
`criteria` is a colon-separated list, where each item in the
list has the form [name]=[value]. The following criteria are supported:
@@ -532,9 +508,6 @@
Module gedcom.element.individual
birth_range=[from_year-to_year]
Match a person whose birth year is in the range of years from
[from_year] to [to_year], including both [from_year] and [to_year].
-
- :type criteria: str
- :rtype: bool
"""
# Check if criteria is a valid criteria and can be split by `:` and `=` characters
@@ -607,7 +580,7 @@
class IndividualElement(Element):
"""Element associated with an `INDIVIDUAL_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_INDIVIDUAL
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_individual': self.get_pointer(),
@@ -711,9 +683,8 @@
Classes
return record
- def is_deceased(self):
- """Checks if this individual is deceased
- :rtype: bool
+ def is_deceased(self) -> bool:
+ """Checks if this individual is deceased.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_DEATH:
@@ -721,9 +692,8 @@
Classes
return False
- def is_child(self):
- """Checks if this element is a child of a family
- :rtype: bool
+ def is_child(self) -> bool:
+ """Checks if this element is a child of a family.
"""
found_child = False
@@ -733,9 +703,8 @@
Classes
return found_child
- def is_private(self):
- """Checks if this individual is marked private
- :rtype: bool
+ def is_private(self) -> bool:
+ """Checks if this individual is marked private.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
@@ -745,9 +714,8 @@
# If we reach here we are probably returning empty strings
return given_name, surname
- def get_all_names(self):
- """Return all names"""
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
+ def get_all_names(self) -> List[str]:
+ """Return all names."""
+ return [a.get_value() for a in self.get_child_elements()
+ if a.get_tag() == tags.GEDCOM_TAG_NAME]
- def surname_match(self, surname_to_match):
- """Matches a string with the surname of an individual
- :type surname_to_match: str
- :rtype: bool
+ def surname_match(self, surname_to_match: str) -> bool:
+ """Matches a string with the surname of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(surname_to_match, surname, regex.IGNORECASE)
@deprecated
- def given_match(self, name):
- """Matches a string with the given name of an individual
+ def given_match(self, name: str) -> bool:
+ """Matches a string with the given name of an individual.
::deprecated:: As of version 1.0.0 use `given_name_match()` method instead
- :type name: str
- :rtype: bool
"""
return self.given_name_match(name)
- def given_name_match(self, given_name_to_match):
- """Matches a string with the given name of an individual
- :type given_name_to_match: str
- :rtype: bool
+ def given_name_match(self, given_name_to_match: str) -> bool:
+ """Matches a string with the given name of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(given_name_to_match, given_name, regex.IGNORECASE)
- def get_gender(self):
- """Returns the gender of a person in string format
- :rtype: str
+ def get_gender(self) -> str:
+ """Returns the gender of a person in string format.
"""
gender = ""
@@ -829,10 +791,9 @@
Classes
return gender
- def get_birth_data(self):
+ def get_birth_data(self) -> Tuple[str, str, List[str]]:
"""Returns the birth data of a person formatted as a tuple:
(`str` date, `str` place, `list` sources)
- :rtype: tuple
"""
date = ""
place = ""
@@ -853,9 +814,8 @@
Classes
return date, place, sources
- def get_birth_year(self):
- """Returns the birth year of a person in integer format
- :rtype: int
+ def get_birth_year(self) -> int:
+ """Returns the birth year of a person in integer format.
"""
date = ""
@@ -873,9 +833,9 @@
Classes
except ValueError:
return -1
- def get_death_data(self):
- """Returns the death data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
- :rtype: tuple
+ def get_death_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the death data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
"""
date = ""
place = ""
@@ -893,9 +853,8 @@
Classes
return date, place, sources
- def get_death_year(self):
- """Returns the death year of a person in integer format
- :rtype: int
+ def get_death_year(self) -> int:
+ """Returns the death year of a person in integer format.
"""
date = ""
@@ -914,16 +873,16 @@
Classes
return -1
@deprecated
- def get_burial(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
+ def get_burial(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_burial_data()` method instead
- :rtype: tuple
"""
self.get_burial_data()
- def get_burial_data(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
- :rtype: tuple
+ def get_burial_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
"""
date = ""
place = ""
@@ -945,16 +904,16 @@
Classes
return date, place, sources
@deprecated
- def get_census(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
+ def get_census(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_census_data()` method instead
- :rtype: list of tuple
"""
self.get_census_data()
- def get_census_data(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
- :rtype: list of tuple
+ def get_census_data(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
"""
census = []
@@ -980,9 +939,8 @@
Classes
return census
- def get_last_change_date(self):
- """Returns the date of when the person data was last changed formatted as a string
- :rtype: str
+ def get_last_change_date(self) -> str:
+ """Returns the date of when the person data was last changed formatted as a string.
"""
date = ""
@@ -994,9 +952,8 @@
Classes
return date
- def get_occupation(self):
- """Returns the occupation of a person
- :rtype: str
+ def get_occupation(self) -> str:
+ """Returns the occupation of a person.
"""
occupation = ""
@@ -1006,18 +963,13 @@
Classes
return occupation
- def birth_year_match(self, year):
- """Returns `True` if the given year matches the birth year of this person
- :type year: int
- :rtype: bool
+ def birth_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the birth year of this person.
"""
return self.get_birth_year() == year
- def birth_range_match(self, from_year, to_year):
- """Checks if the birth year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def birth_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the birth year of a person lies within the given range.
"""
birth_year = self.get_birth_year()
@@ -1026,18 +978,13 @@
Classes
return False
- def death_year_match(self, year):
- """Returns `True` if the given year matches the death year of this person
- :type year: int
- :rtype: bool
+ def death_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the death year of this person.
"""
return self.get_death_year() == year
- def death_range_match(self, from_year, to_year):
- """Checks if the death year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def death_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the death year of a person lies within the given range.
"""
death_year = self.get_death_year()
@@ -1046,8 +993,8 @@
Classes
return False
- def criteria_match(self, criteria):
- """Checks if this individual matches all of the given criteria
+ def criteria_match(self, criteria: str) -> bool:
+ """Checks if this individual matches all of the given criteria.
`criteria` is a colon-separated list, where each item in the
list has the form [name]=[value]. The following criteria are supported:
@@ -1061,9 +1008,6 @@
Classes
birth_range=[from_year-to_year]
Match a person whose birth year is in the range of years from
[from_year] to [to_year], including both [from_year] and [to_year].
-
- :type criteria: str
- :rtype: bool
"""
# Check if criteria is a valid criteria and can be split by `:` and `=` characters
@@ -1131,22 +1075,16 @@
Checks if the birth year of a person lies within the given range
-:type from_year: int
-:type to_year: int
-:rtype: bool
+
Checks if the birth year of a person lies within the given range.
Expand source code
-
def birth_range_match(self, from_year, to_year):
- """Checks if the birth year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+
def birth_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the birth year of a person lies within the given range.
"""
birth_year = self.get_birth_year()
@@ -1157,29 +1095,25 @@
Returns True if the given year matches the birth year of this person
-:type year: int
-:rtype: bool
+
Returns True if the given year matches the birth year of this person.
Expand source code
-
def birth_year_match(self, year):
- """Returns `True` if the given year matches the birth year of this person
- :type year: int
- :rtype: bool
+
def birth_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the birth year of this person.
"""
return self.get_birth_year() == year
Checks if this individual matches all of the given criteria
+
Checks if this individual matches all of the given criteria.
criteria is a colon-separated list, where each item in the
list has the form [name]=[value]. The following criteria are supported:
surname=[name]
@@ -1190,15 +1124,13 @@
Methods
Match a person whose birth year is a four-digit [year].
birth_range=[from_year-to_year]
Match a person whose birth year is in the range of years from
-[from_year] to [to_year], including both [from_year] and [to_year].
-
:type criteria: str
-:rtype: bool
+[from_year] to [to_year], including both [from_year] and [to_year].
Expand source code
-
def criteria_match(self, criteria):
- """Checks if this individual matches all of the given criteria
+
def criteria_match(self, criteria: str) -> bool:
+ """Checks if this individual matches all of the given criteria.
`criteria` is a colon-separated list, where each item in the
list has the form [name]=[value]. The following criteria are supported:
@@ -1212,9 +1144,6 @@
Methods
birth_range=[from_year-to_year]
Match a person whose birth year is in the range of years from
[from_year] to [to_year], including both [from_year] and [to_year].
-
- :type criteria: str
- :rtype: bool
"""
# Check if criteria is a valid criteria and can be split by `:` and `=` characters
@@ -1277,22 +1206,16 @@
Checks if the death year of a person lies within the given range
-:type from_year: int
-:type to_year: int
-:rtype: bool
+
Checks if the death year of a person lies within the given range.
Expand source code
-
def death_range_match(self, from_year, to_year):
- """Checks if the death year of a person lies within the given range
- :type from_year: int
- :type to_year: int
- :rtype: bool
+
def death_range_match(self, from_year: int, to_year: int) -> bool:
+ """Checks if the death year of a person lies within the given range.
"""
death_year = self.get_death_year()
@@ -1303,53 +1226,48 @@
Returns True if the given year matches the death year of this person
-:type year: int
-:rtype: bool
+
Returns True if the given year matches the death year of this person.
Expand source code
-
def death_year_match(self, year):
- """Returns `True` if the given year matches the death year of this person
- :type year: int
- :rtype: bool
+
def death_year_match(self, year: int) -> bool:
+ """Returns `True` if the given year matches the death year of this person.
"""
return self.get_death_year() == year
def get_all_names(self):
- """Return all names"""
- return [a.get_value() for a in self.get_child_elements() if a.get_tag() == tags.GEDCOM_TAG_NAME]
+
def get_all_names(self) -> List[str]:
+ """Return all names."""
+ return [a.get_value() for a in self.get_child_elements()
+ if a.get_tag() == tags.GEDCOM_TAG_NAME]
Returns the birth data of a person formatted as a tuple:
-(str date, str place, list sources)
-:rtype: tuple
+(str date, str place, list sources)
Expand source code
-
def get_birth_data(self):
+
def get_birth_data(self) -> Tuple[str, str, List[str]]:
"""Returns the birth data of a person formatted as a tuple:
(`str` date, `str` place, `list` sources)
- :rtype: tuple
"""
date = ""
place = ""
@@ -1372,18 +1290,16 @@
Methods
-def get_birth_year(self)
+def get_birth_year(self) -> int
-
Returns the birth year of a person in integer format
-:rtype: int
+
Returns the birth year of a person in integer format.
Expand source code
-
def get_birth_year(self):
- """Returns the birth year of a person in integer format
- :rtype: int
+
def get_birth_year(self) -> int:
+ """Returns the birth year of a person in integer format.
"""
date = ""
@@ -1403,38 +1319,38 @@
Returns the burial data of a person formatted as a tuple: (str date, str´ place,list` sources)
-::deprecated:: As of version 1.0.0 use get_burial_data() method instead
-:rtype: tuple
+
Returns the burial data of a person formatted as a tuple:
+(str date, str´ place,list` sources)
+::deprecated:: As of version 1.0.0 use get_burial_data() method instead
Expand source code
@deprecated
-def get_burial(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
+def get_burial(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_burial_data()` method instead
- :rtype: tuple
"""
self.get_burial_data()
Returns the burial data of a person formatted as a tuple: (str date, str´ place,list` sources)
-:rtype: tuple
+
Returns the burial data of a person formatted as a tuple:
+(str date, str´ place,list` sources)
Expand source code
-
def get_burial_data(self):
- """Returns the burial data of a person formatted as a tuple: (`str` date, `str´ place, `list` sources)
- :rtype: tuple
+
def get_burial_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the burial data of a person formatted as a tuple:
+ (`str` date, `str´ place, `list` sources)
"""
date = ""
place = ""
@@ -1457,38 +1373,38 @@
Returns a list of censuses of an individual formatted as tuples: (str date, str´ place,list` sources)
-::deprecated:: As of version 1.0.0 use get_census_data() method instead
-:rtype: list of tuple
+
Returns a list of censuses of an individual formatted as tuples:
+(str date, str´ place,list` sources)
+::deprecated:: As of version 1.0.0 use get_census_data() method instead
Expand source code
@deprecated
-def get_census(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
+def get_census(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
::deprecated:: As of version 1.0.0 use `get_census_data()` method instead
- :rtype: list of tuple
"""
self.get_census_data()
Returns a list of censuses of an individual formatted as tuples: (str date, str´ place,list` sources)
-:rtype: list of tuple
+
Returns a list of censuses of an individual formatted as tuples:
+(str date, str´ place,list` sources)
Expand source code
-
def get_census_data(self):
- """Returns a list of censuses of an individual formatted as tuples: (`str` date, `str´ place, `list` sources)
- :rtype: list of tuple
+
def get_census_data(self) -> List[Tuple[str, str, List[str]]]:
+ """Returns a list of censuses of an individual formatted as tuples:
+ (`str` date, `str´ place, `list` sources)
"""
census = []
@@ -1516,18 +1432,18 @@
Returns the death data of a person formatted as a tuple: (str date, str place, list sources)
-:rtype: tuple
+
Returns the death data of a person formatted as a tuple:
+(str date, str place, list sources)
Expand source code
-
def get_death_data(self):
- """Returns the death data of a person formatted as a tuple: (`str` date, `str` place, `list` sources)
- :rtype: tuple
+
def get_death_data(self) -> Tuple[str, str, List[str]]:
+ """Returns the death data of a person formatted as a tuple:
+ (`str` date, `str` place, `list` sources)
"""
date = ""
place = ""
@@ -1547,18 +1463,16 @@
Methods
-def get_death_year(self)
+def get_death_year(self) -> int
-
Returns the death year of a person in integer format
-:rtype: int
+
Returns the death year of a person in integer format.
Expand source code
-
def get_death_year(self):
- """Returns the death year of a person in integer format
- :rtype: int
+
def get_death_year(self) -> int:
+ """Returns the death year of a person in integer format.
"""
date = ""
@@ -1578,18 +1492,16 @@
Returns the date of when the person data was last changed formatted as a string
-:rtype: str
+
Returns the date of when the person data was last changed formatted as a string.
Expand source code
-
def get_last_change_date(self):
- """Returns the date of when the person data was last changed formatted as a string
- :rtype: str
+
def get_last_change_date(self) -> str:
+ """Returns the date of when the person data was last changed formatted as a string.
"""
date = ""
@@ -1626,18 +1536,16 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_individual': self.get_pointer(),
@@ -1804,60 +1708,50 @@
Matches a string with the given name of an individual
-::deprecated:: As of version 1.0.0 use given_name_match() method instead
-:type name: str
-:rtype: bool
+
Matches a string with the given name of an individual.
+::deprecated:: As of version 1.0.0 use given_name_match() method instead
Expand source code
@deprecated
-def given_match(self, name):
- """Matches a string with the given name of an individual
+def given_match(self, name: str) -> bool:
+ """Matches a string with the given name of an individual.
::deprecated:: As of version 1.0.0 use `given_name_match()` method instead
- :type name: str
- :rtype: bool
"""
return self.given_name_match(name)
Matches a string with the given name of an individual
-:type given_name_to_match: str
-:rtype: bool
+
Matches a string with the given name of an individual.
Expand source code
-
def given_name_match(self, given_name_to_match):
- """Matches a string with the given name of an individual
- :type given_name_to_match: str
- :rtype: bool
+
def given_name_match(self, given_name_to_match: str) -> bool:
+ """Matches a string with the given name of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(given_name_to_match, given_name, regex.IGNORECASE)
-def is_child(self)
+def is_child(self) -> bool
-
Checks if this element is a child of a family
-:rtype: bool
+
Checks if this element is a child of a family.
Expand source code
-
def is_child(self):
- """Checks if this element is a child of a family
- :rtype: bool
+
def is_child(self) -> bool:
+ """Checks if this element is a child of a family.
"""
found_child = False
@@ -1869,18 +1763,16 @@
Checks if this individual is deceased
-:rtype: bool
+
Checks if this individual is deceased.
Expand source code
-
def is_deceased(self):
- """Checks if this individual is deceased
- :rtype: bool
+
def is_deceased(self) -> bool:
+ """Checks if this individual is deceased.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_DEATH:
@@ -1890,18 +1782,16 @@
Checks if this individual is marked private
-:rtype: bool
+
Checks if this individual is marked private.
Expand source code
-
def is_private(self):
- """Checks if this individual is marked private
- :rtype: bool
+
def is_private(self) -> bool:
+ """Checks if this individual is marked private.
"""
for child in self.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_PRIVATE:
@@ -1913,20 +1803,16 @@
Matches a string with the surname of an individual
-:type surname_to_match: str
-:rtype: bool
+
Matches a string with the surname of an individual.
Expand source code
-
def surname_match(self, surname_to_match):
- """Matches a string with the surname of an individual
- :type surname_to_match: str
- :rtype: bool
+
def surname_match(self, surname_to_match: str) -> bool:
+ """Matches a string with the surname of an individual.
"""
(given_name, surname) = self.get_name()
return regex.search(surname_to_match, surname, regex.IGNORECASE)
class NoteElement(Element):
"""Element associated with a `NOTE_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_NOTE
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_note': self.get_pointer(),
@@ -115,7 +114,7 @@
class NoteElement(Element):
"""Element associated with a `NOTE_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_NOTE
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_note': self.get_pointer(),
@@ -166,18 +164,16 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_note': self.get_pointer(),
diff --git a/docs/gedcom/element/object.html b/docs/gedcom/element/object.html
index bfadd75..9f89ec5 100644
--- a/docs/gedcom/element/object.html
+++ b/docs/gedcom/element/object.html
@@ -71,12 +71,11 @@
Module gedcom.element.object
class ObjectElement(Element):
"""Element associated with a `MULTIMEDIA_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_OBJECT
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_object': self.get_pointer(),
@@ -149,7 +148,7 @@
class ObjectElement(Element):
"""Element associated with a `MULTIMEDIA_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_OBJECT
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_object': self.get_pointer(),
@@ -233,18 +231,16 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_object': self.get_pointer(),
diff --git a/docs/gedcom/element/repository.html b/docs/gedcom/element/repository.html
index a256297..2369196 100644
--- a/docs/gedcom/element/repository.html
+++ b/docs/gedcom/element/repository.html
@@ -71,12 +71,11 @@
Module gedcom.element.repository
class RepositoryElement(Element):
"""Element associated with a `REPOSITORY_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_REPOSITORY
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_repository': self.get_pointer(),
@@ -125,7 +124,7 @@
class RepositoryElement(Element):
"""Element associated with a `REPOSITORY_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_REPOSITORY
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_repository': self.get_pointer(),
@@ -185,18 +183,16 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_repository': self.get_pointer(),
diff --git a/docs/gedcom/element/root.html b/docs/gedcom/element/root.html
index 7968e89..2609f10 100644
--- a/docs/gedcom/element/root.html
+++ b/docs/gedcom/element/root.html
@@ -58,9 +58,10 @@
Module gedcom.element.root
class RootElement(Element):
- """Virtual GEDCOM root element containing all logical records as children"""
+ """Virtual GEDCOM root element containing all logical records as children."""
- def __init__(self, level=-1, pointer="", tag="ROOT", value="", crlf="\n", multi_line=True):
+ def __init__(self, level: int = -1, pointer: str = "", tag: str = "ROOT", value: str = "",
+ crlf: str = "\n", multi_line: bool = True):
super(RootElement, self).__init__(level, pointer, tag, value, crlf, multi_line)
class SourceElement(Element):
"""Element associated with a SOURCE_RECORD"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_SOURCE
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_source': self.get_pointer(),
@@ -178,7 +177,7 @@
class SourceElement(Element):
"""Element associated with a SOURCE_RECORD"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_SOURCE
- def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+ def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_source': self.get_pointer(),
@@ -277,18 +275,16 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the full record in dictionary format.
Expand source code
-
def get_record(self):
- """Parse and return the record in dictionary format
- :rtype: dict
+
def get_record(self) -> dict:
+ """Parse and return the full record in dictionary format.
"""
record = {
'key_to_source': self.get_pointer(),
diff --git a/docs/gedcom/element/submission.html b/docs/gedcom/element/submission.html
index 95097e3..c4bdb9e 100644
--- a/docs/gedcom/element/submission.html
+++ b/docs/gedcom/element/submission.html
@@ -79,12 +79,11 @@
Module gedcom.element.submission
class SubmissionElement(Element):
"""Element associated with a `SUBMISSION_RECORD`"""
- def get_tag(self):
+ def get_tag(self) -> str:
return tags.GEDCOM_TAG_SUBMISSION
- def get_record(self):
+ def get_record(self) -> dict:
"""Parse and return the record in dictionary format
- :rtype: dict
"""
record = {
'key_to_submission': self.get_pointer(),
@@ -124,7 +123,7 @@
Parse and return the record in dictionary format
-:rtype: dict
+
Parse and return the record in dictionary format
Expand source code
-
def get_record(self):
+
def get_record(self) -> dict:
"""Parse and return the record in dictionary format
- :rtype: dict
"""
record = {
'key_to_submitter': self.get_pointer(),
diff --git a/docs/gedcom/errors.html b/docs/gedcom/errors.html
index b6fe2eb..bc3b49f 100644
--- a/docs/gedcom/errors.html
+++ b/docs/gedcom/errors.html
@@ -78,16 +78,16 @@
Module gedcom.errors
class GedcomVersionUnsupportedError(Exception):
"""Raised when a particular GEDCOM version is not supported
- by the parser and the standard for the version requires the
+ by the parser and the standard for that version requires the
parser to reject it.
"""
class GedcomFormatUnsupportedError(Exception):
"""Raised if the GEDCOM format is not recognized by the
- parser. Note some misspellings as documented on page 148
- in the 5.5.5 standard are treated as LINEAGE-LINKED and
- allowed.
+ parser. Note some common misspellings as documented on page 148
+ in the 5.5.5 GEDCOM standard are treated as `LINEAGE-LINKED`
+ and allowed when parsing older GEDCOM data.
"""
@@ -164,18 +164,18 @@
Ancestors
Raised if the GEDCOM format is not recognized by the
-parser. Note some misspellings as documented on page 148
-in the 5.5.5 standard are treated as LINEAGE-LINKED and
-allowed.
+parser. Note some common misspellings as documented on page 148
+in the 5.5.5 GEDCOM standard are treated as LINEAGE-LINKED
+and allowed when parsing older GEDCOM data.
Expand source code
class GedcomFormatUnsupportedError(Exception):
"""Raised if the GEDCOM format is not recognized by the
- parser. Note some misspellings as documented on page 148
- in the 5.5.5 standard are treated as LINEAGE-LINKED and
- allowed.
+ parser. Note some common misspellings as documented on page 148
+ in the 5.5.5 GEDCOM standard are treated as `LINEAGE-LINKED`
+ and allowed when parsing older GEDCOM data.
"""
Ancestors
@@ -234,7 +234,7 @@
Ancestors
Raised when a particular GEDCOM version is not supported
-by the parser and the standard for the version requires the
+by the parser and the standard for that version requires the
parser to reject it.
@@ -242,7 +242,7 @@
Ancestors
class GedcomVersionUnsupportedError(Exception):
"""Raised when a particular GEDCOM version is not supported
- by the parser and the standard for the version requires the
+ by the parser and the standard for that version requires the
parser to reject it.
"""
"""
import re as regex
+from sys import stdout
from sys import version_info
+from typing import Tuple, List, IO
import gedcom.tags as tags
import gedcom.standards as standards
@@ -107,10 +109,10 @@
Module gedcom.parser
class Parser():
- """Parses and manipulates GEDCOM 5.5 format data
+ """Parses and manipulates GEDCOM formatted data.
- For documentation of the GEDCOM 5.5 format, see:
- http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
+ For documentation of the different GEDCOM standards see the
+ links defined in `gedcom.standards`
This parser reads and parses a GEDCOM file.
@@ -135,8 +137,8 @@
Module gedcom.parser
self.__element_list = []
self.__element_dictionary = {}
- def get_element_list(self):
- """Returns a list containing all elements from within the GEDCOM file
+ def get_element_list(self) -> List[Element]:
+ """Returns a list containing all elements from within the GEDCOM file.
By default elements are in the same order as they appeared in the file.
@@ -147,17 +149,15 @@
Module gedcom.parser
Consider using `gedcom.parser.Parser.get_root_element()` or
`gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
-
- :rtype: list of Element
"""
if not self.__element_list:
for element in self.get_root_child_elements():
self.__build_list(element, self.__element_list)
return self.__element_list
- def get_element_dictionary(self):
+ def get_element_dictionary(self) -> dict:
"""Returns a dictionary containing all elements, identified by a pointer,
- from within the GEDCOM file
+ from within the GEDCOM file.
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -165,8 +165,6 @@
Module gedcom.parser
This dictionary gets generated on-the-fly, but gets cached. If the
database was modified, you should call `invalidate_cache()` once to let
this method return updated data.
-
- :rtype: dict of Element
"""
if not self.__element_dictionary:
self.__element_dictionary = {
@@ -176,28 +174,22 @@
Module gedcom.parser
return self.__element_dictionary
- def get_root_element(self):
- """Returns a virtual root element containing all logical records as children
+ def get_root_element(self) -> RootElement:
+ """Returns a virtual root element containing all logical records as children.
When printed, this element converts to an empty string.
-
- :rtype: RootElement
"""
return self.__root_element
- def get_root_child_elements(self):
- """Returns a list of logical records in the GEDCOM file
+ def get_root_child_elements(self) -> List[Element]:
+ """Returns a list of logical records in the GEDCOM file.
By default, elements are in the same order as they appeared in the file.
-
- :rtype: list of Element
"""
return self.get_root_element().get_child_elements()
- def parse_file(self, file_path, strict=True):
- """Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
- :type file_path: str
- :type strict: bool
+ def parse_file(self, file_path: str, strict: bool = True):
+ """Opens and parses a file, from the given file path, as GEDCOM formatted data.
"""
codec = get_encoding(file_path)
real_version, reported_version, reported_format = get_version(file_path, codec)
@@ -216,10 +208,8 @@
Module gedcom.parser
with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
- def parse(self, gedcom_stream, strict=True):
- """Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
- :type gedcom_stream: a file stream, or str array of lines with new line at the end
- :type strict: bool
+ def parse(self, gedcom_stream: IO, strict: bool = True):
+ """Parses a stream, or an array of lines, as GEDCOM formatted data.
"""
self.invalidate_cache()
self.__root_element = RootElement()
@@ -234,18 +224,12 @@
Module gedcom.parser
# Private methods
@staticmethod
- def __parse_line(line_number, line, last_element, strict=True):
- """Parse a line from a GEDCOM 5.5 formatted document
+ def __parse_line(line_number: int, line: str, last_element: Element,
+ strict: bool = True) -> Element:
+ """Parse a line from a GEDCOM formatted document.
Each line should have the following (bracketed items optional):
level + ' ' + [pointer + ' ' +] tag + [' ' + line_value]
-
- :type line_number: int
- :type line: str
- :type last_element: Element
- :type strict: bool
-
- :rtype: Element
"""
# Level must start with non-negative int, no leading zeros.
@@ -334,10 +318,8 @@
Module gedcom.parser
return element
- def __build_list(self, element, element_list):
- """Recursively add elements to a list containing elements
- :type element: Element
- :type element_list: list of Element
+ def __build_list(self, element: Element, element_list: List[Element]):
+ """Recursively add elements to a list containing elements.
"""
element_list.append(element)
for child in element.get_child_elements():
@@ -345,10 +327,9 @@
Module gedcom.parser
# Methods for analyzing individuals and relationships between individuals
- def get_marriages(self, individual):
- """Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
- :type individual: IndividualElement
- :rtype: tuple
+ def get_marriages(self, individual: IndividualElement) -> Tuple[str, str]:
+ """Returns a list of marriages of an individual formatted as a tuple:
+ (`str` date, `str` place)
"""
marriages = []
if not isinstance(individual, IndividualElement):
@@ -370,10 +351,8 @@
Module gedcom.parser
marriages.append((date, place))
return marriages
- def get_marriage_years(self, individual):
- """Returns a list of marriage years (as integers) for an individual
- :type individual: IndividualElement
- :rtype: list of int
+ def get_marriage_years(self, individual: IndividualElement) -> List[int]:
+ """Returns a list of marriage years for an individual.
"""
dates = []
@@ -387,20 +366,18 @@
Module gedcom.parser
for family in families:
for child in family.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value().split()[-1]
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value().split()[-1]
try:
dates.append(int(date))
except ValueError:
pass
return dates
- def marriage_year_match(self, individual, year):
- """Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
- :type individual: IndividualElement
- :type year: int
- :rtype: bool
+ def marriage_year_match(self, individual: IndividualElement, year: int) -> bool:
+ """Checks if one of the marriage years of an individual matches the supplied year.
+ Year is an integer.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -410,12 +387,10 @@
Module gedcom.parser
years = self.get_marriage_years(individual)
return year in years
- def marriage_range_match(self, individual, from_year, to_year):
- """Check if one of the marriage years of an individual is in a given range. Years are integers.
- :type individual: IndividualElement
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def marriage_range_match(self, individual: IndividualElement,
+ from_year: int, to_year: int) -> bool:
+ """Check if one of the marriage years of an individual is in a given range.
+ Years are integers.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -428,14 +403,15 @@
Module gedcom.parser
return True
return False
- def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
- """Return family elements listed for an individual
- family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
- :type individual: IndividualElement
- :type family_type: str
- :rtype: list of FamilyElement
+ def get_families(self, individual: IndividualElement,
+ family_type: str = tags.GEDCOM_TAG_FAMILY_SPOUSE) -> List[FamilyElement]:
+ """Return family elements listed for an individual.
+
+ Optional argument `family_type` can be used to return specific subsets:
+
+ `tags.GEDCOM_TAG_FAMILY_SPOUSE`: Default, families where the individual is a spouse.
+
+ `tags.GEDCOM_TAG_FAMILY_CHILD`: Families where the individual is a child.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -454,13 +430,15 @@
Module gedcom.parser
return families
- def get_ancestors(self, individual, ancestor_type="ALL"):
- """Return elements corresponding to ancestors of an individual
- Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
- used to specify only natural (genetic) ancestors.
- :type individual: IndividualElement
- :type ancestor_type: str
- :rtype: list of Element
+ def get_ancestors(self, individual: IndividualElement,
+ ancestor_type: str = "ALL") -> List[Element]:
+ """Return elements corresponding to ancestors of an individual.
+
+ Optional argument `ancestor_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all ancestors.
+
+ "NAT": Return only natural (genetic) ancestors.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -476,13 +454,15 @@
Module gedcom.parser
return ancestors
- def get_parents(self, individual, parent_type="ALL"):
- """Return elements corresponding to parents of an individual
- Optional parent_type. Default "ALL" returns all parents. "NAT" can be
- used to specify only natural (genetic) parents.
- :type individual: IndividualElement
- :type parent_type: str
- :rtype: list of IndividualElement
+ def get_parents(self, individual: IndividualElement,
+ parent_type: str = "ALL") -> List[IndividualElement]:
+ """Return elements corresponding to parents of an individual.
+
+ Optional argument `parent_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all parents.
+
+ "NAT": Return only natural (genetic) parents.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -502,19 +482,23 @@
Module gedcom.parser
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ parents += self.get_family_members(family,
+ tags.GEDCOM_TAG_WIFE)
elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
+ parents += self.get_family_members(family,
+ tags.GEDCOM_TAG_HUSBAND)
else:
parents += self.get_family_members(family, "PARENTS")
return parents
- def find_path_to_ancestor(self, descendant, ancestor, path=None):
- """Return path from descendant to ancestor
+ def find_path_to_ancestor(self, descendant: IndividualElement,
+ ancestor: IndividualElement, path: str = None):
+ """Return path from descendant to ancestor.
:rtype: object
"""
- if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
+ if not isinstance(descendant, IndividualElement) and isinstance(ancestor,
+ IndividualElement):
raise NotAnActualIndividualError(
"Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
@@ -524,26 +508,30 @@
Module gedcom.parser
if path[-1].get_pointer() == ancestor.get_pointer():
return path
- else:
- parents = self.get_parents(descendant, "NAT")
- for parent in parents:
- potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
- if potential_path is not None:
- return potential_path
+
+ parents = self.get_parents(descendant, "NAT")
+ for parent in parents:
+ potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
+ if potential_path is not None:
+ return potential_path
return None
- def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
- """Return array of family members: individual, spouse, and children
+ def get_family_members(self, family: FamilyElement,
+ members_type: str = FAMILY_MEMBERS_TYPE_ALL) -> List[IndividualElement]:
+ """Return array of family members: individual, spouse, and children.
+
Optional argument `members_type` can be used to return specific subsets:
+
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
+
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
+
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
+
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
- :type family: FamilyElement
- :type members_type: str
- :rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
@@ -576,9 +564,9 @@
Module gedcom.parser
# Other methods
- def to_gedcom_string(self, recursive=False):
- """Formats all elements and optionally all of the sub-elements into a GEDCOM string
- :type recursive: bool
+ def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats all elements and optionally all of the sub-elements into a
+ GEDCOM string.
"""
is_gte_python_3 = version_info[0] >= 3
output = '' if is_gte_python_3 else b''
@@ -592,14 +580,11 @@
Module gedcom.parser
return output
def print_gedcom(self):
- """Write GEDCOM data to stdout"""
- from sys import stdout
+ """Write GEDCOM data to stdout."""
self.save_gedcom(stdout)
- def save_gedcom(self, open_file, recursive=True):
- """Save GEDCOM data to a file
- :type open_file: file
- :type recursive: bool
+ def save_gedcom(self, open_file: IO, recursive: bool = True):
+ """Save GEDCOM data to a file.
"""
open_file.write(self.to_gedcom_string(recursive))
For documentation of the different GEDCOM standards see the
+links defined in gedcom.standards
This parser reads and parses a GEDCOM file.
Elements may be accessed via:
@@ -631,10 +616,10 @@
Classes
Expand source code
class Parser():
- """Parses and manipulates GEDCOM 5.5 format data
+ """Parses and manipulates GEDCOM formatted data.
- For documentation of the GEDCOM 5.5 format, see:
- http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm
+ For documentation of the different GEDCOM standards see the
+ links defined in `gedcom.standards`
This parser reads and parses a GEDCOM file.
@@ -659,8 +644,8 @@
Classes
self.__element_list = []
self.__element_dictionary = {}
- def get_element_list(self):
- """Returns a list containing all elements from within the GEDCOM file
+ def get_element_list(self) -> List[Element]:
+ """Returns a list containing all elements from within the GEDCOM file.
By default elements are in the same order as they appeared in the file.
@@ -671,17 +656,15 @@
Classes
Consider using `gedcom.parser.Parser.get_root_element()` or
`gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
-
- :rtype: list of Element
"""
if not self.__element_list:
for element in self.get_root_child_elements():
self.__build_list(element, self.__element_list)
return self.__element_list
- def get_element_dictionary(self):
+ def get_element_dictionary(self) -> dict:
"""Returns a dictionary containing all elements, identified by a pointer,
- from within the GEDCOM file
+ from within the GEDCOM file.
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -689,8 +672,6 @@
Classes
This dictionary gets generated on-the-fly, but gets cached. If the
database was modified, you should call `invalidate_cache()` once to let
this method return updated data.
-
- :rtype: dict of Element
"""
if not self.__element_dictionary:
self.__element_dictionary = {
@@ -700,28 +681,22 @@
Classes
return self.__element_dictionary
- def get_root_element(self):
- """Returns a virtual root element containing all logical records as children
+ def get_root_element(self) -> RootElement:
+ """Returns a virtual root element containing all logical records as children.
When printed, this element converts to an empty string.
-
- :rtype: RootElement
"""
return self.__root_element
- def get_root_child_elements(self):
- """Returns a list of logical records in the GEDCOM file
+ def get_root_child_elements(self) -> List[Element]:
+ """Returns a list of logical records in the GEDCOM file.
By default, elements are in the same order as they appeared in the file.
-
- :rtype: list of Element
"""
return self.get_root_element().get_child_elements()
- def parse_file(self, file_path, strict=True):
- """Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
- :type file_path: str
- :type strict: bool
+ def parse_file(self, file_path: str, strict: bool = True):
+ """Opens and parses a file, from the given file path, as GEDCOM formatted data.
"""
codec = get_encoding(file_path)
real_version, reported_version, reported_format = get_version(file_path, codec)
@@ -740,10 +715,8 @@
Classes
with open(file_path, 'r', encoding=codec) as gedcom_stream:
self.parse(gedcom_stream, strict)
- def parse(self, gedcom_stream, strict=True):
- """Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
- :type gedcom_stream: a file stream, or str array of lines with new line at the end
- :type strict: bool
+ def parse(self, gedcom_stream: IO, strict: bool = True):
+ """Parses a stream, or an array of lines, as GEDCOM formatted data.
"""
self.invalidate_cache()
self.__root_element = RootElement()
@@ -758,18 +731,12 @@
Classes
# Private methods
@staticmethod
- def __parse_line(line_number, line, last_element, strict=True):
- """Parse a line from a GEDCOM 5.5 formatted document
+ def __parse_line(line_number: int, line: str, last_element: Element,
+ strict: bool = True) -> Element:
+ """Parse a line from a GEDCOM formatted document.
Each line should have the following (bracketed items optional):
level + ' ' + [pointer + ' ' +] tag + [' ' + line_value]
-
- :type line_number: int
- :type line: str
- :type last_element: Element
- :type strict: bool
-
- :rtype: Element
"""
# Level must start with non-negative int, no leading zeros.
@@ -858,10 +825,8 @@
Classes
return element
- def __build_list(self, element, element_list):
- """Recursively add elements to a list containing elements
- :type element: Element
- :type element_list: list of Element
+ def __build_list(self, element: Element, element_list: List[Element]):
+ """Recursively add elements to a list containing elements.
"""
element_list.append(element)
for child in element.get_child_elements():
@@ -869,10 +834,9 @@
Classes
# Methods for analyzing individuals and relationships between individuals
- def get_marriages(self, individual):
- """Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
- :type individual: IndividualElement
- :rtype: tuple
+ def get_marriages(self, individual: IndividualElement) -> Tuple[str, str]:
+ """Returns a list of marriages of an individual formatted as a tuple:
+ (`str` date, `str` place)
"""
marriages = []
if not isinstance(individual, IndividualElement):
@@ -894,10 +858,8 @@
Classes
marriages.append((date, place))
return marriages
- def get_marriage_years(self, individual):
- """Returns a list of marriage years (as integers) for an individual
- :type individual: IndividualElement
- :rtype: list of int
+ def get_marriage_years(self, individual: IndividualElement) -> List[int]:
+ """Returns a list of marriage years for an individual.
"""
dates = []
@@ -911,20 +873,18 @@
Classes
for family in families:
for child in family.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value().split()[-1]
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value().split()[-1]
try:
dates.append(int(date))
except ValueError:
pass
return dates
- def marriage_year_match(self, individual, year):
- """Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
- :type individual: IndividualElement
- :type year: int
- :rtype: bool
+ def marriage_year_match(self, individual: IndividualElement, year: int) -> bool:
+ """Checks if one of the marriage years of an individual matches the supplied year.
+ Year is an integer.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -934,12 +894,10 @@
Classes
years = self.get_marriage_years(individual)
return year in years
- def marriage_range_match(self, individual, from_year, to_year):
- """Check if one of the marriage years of an individual is in a given range. Years are integers.
- :type individual: IndividualElement
- :type from_year: int
- :type to_year: int
- :rtype: bool
+ def marriage_range_match(self, individual: IndividualElement,
+ from_year: int, to_year: int) -> bool:
+ """Check if one of the marriage years of an individual is in a given range.
+ Years are integers.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -952,14 +910,15 @@
Classes
return True
return False
- def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
- """Return family elements listed for an individual
- family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
- :type individual: IndividualElement
- :type family_type: str
- :rtype: list of FamilyElement
+ def get_families(self, individual: IndividualElement,
+ family_type: str = tags.GEDCOM_TAG_FAMILY_SPOUSE) -> List[FamilyElement]:
+ """Return family elements listed for an individual.
+
+ Optional argument `family_type` can be used to return specific subsets:
+
+ `tags.GEDCOM_TAG_FAMILY_SPOUSE`: Default, families where the individual is a spouse.
+
+ `tags.GEDCOM_TAG_FAMILY_CHILD`: Families where the individual is a child.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -978,13 +937,15 @@
Classes
return families
- def get_ancestors(self, individual, ancestor_type="ALL"):
- """Return elements corresponding to ancestors of an individual
- Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
- used to specify only natural (genetic) ancestors.
- :type individual: IndividualElement
- :type ancestor_type: str
- :rtype: list of Element
+ def get_ancestors(self, individual: IndividualElement,
+ ancestor_type: str = "ALL") -> List[Element]:
+ """Return elements corresponding to ancestors of an individual.
+
+ Optional argument `ancestor_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all ancestors.
+
+ "NAT": Return only natural (genetic) ancestors.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1000,13 +961,15 @@
Classes
return ancestors
- def get_parents(self, individual, parent_type="ALL"):
- """Return elements corresponding to parents of an individual
- Optional parent_type. Default "ALL" returns all parents. "NAT" can be
- used to specify only natural (genetic) parents.
- :type individual: IndividualElement
- :type parent_type: str
- :rtype: list of IndividualElement
+ def get_parents(self, individual: IndividualElement,
+ parent_type: str = "ALL") -> List[IndividualElement]:
+ """Return elements corresponding to parents of an individual.
+
+ Optional argument `parent_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all parents.
+
+ "NAT": Return only natural (genetic) parents.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1026,19 +989,23 @@
Classes
for child in family_member.get_child_elements():
if child.get_value() == "Natural":
if child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_MREL:
- parents += self.get_family_members(family, tags.GEDCOM_TAG_WIFE)
+ parents += self.get_family_members(family,
+ tags.GEDCOM_TAG_WIFE)
elif child.get_tag() == tags.GEDCOM_PROGRAM_DEFINED_TAG_FREL:
- parents += self.get_family_members(family, tags.GEDCOM_TAG_HUSBAND)
+ parents += self.get_family_members(family,
+ tags.GEDCOM_TAG_HUSBAND)
else:
parents += self.get_family_members(family, "PARENTS")
return parents
- def find_path_to_ancestor(self, descendant, ancestor, path=None):
- """Return path from descendant to ancestor
+ def find_path_to_ancestor(self, descendant: IndividualElement,
+ ancestor: IndividualElement, path: str = None):
+ """Return path from descendant to ancestor.
:rtype: object
"""
- if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
+ if not isinstance(descendant, IndividualElement) and isinstance(ancestor,
+ IndividualElement):
raise NotAnActualIndividualError(
"Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
@@ -1048,26 +1015,30 @@
Classes
if path[-1].get_pointer() == ancestor.get_pointer():
return path
- else:
- parents = self.get_parents(descendant, "NAT")
- for parent in parents:
- potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
- if potential_path is not None:
- return potential_path
+
+ parents = self.get_parents(descendant, "NAT")
+ for parent in parents:
+ potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
+ if potential_path is not None:
+ return potential_path
return None
- def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
- """Return array of family members: individual, spouse, and children
+ def get_family_members(self, family: FamilyElement,
+ members_type: str = FAMILY_MEMBERS_TYPE_ALL) -> List[IndividualElement]:
+ """Return array of family members: individual, spouse, and children.
+
Optional argument `members_type` can be used to return specific subsets:
+
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
+
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
+
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
+
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
- :type family: FamilyElement
- :type members_type: str
- :rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
@@ -1100,9 +1071,9 @@
Classes
# Other methods
- def to_gedcom_string(self, recursive=False):
- """Formats all elements and optionally all of the sub-elements into a GEDCOM string
- :type recursive: bool
+ def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats all elements and optionally all of the sub-elements into a
+ GEDCOM string.
"""
is_gte_python_3 = version_info[0] >= 3
output = '' if is_gte_python_3 else b''
@@ -1116,14 +1087,11 @@
Classes
return output
def print_gedcom(self):
- """Write GEDCOM data to stdout"""
- from sys import stdout
+ """Write GEDCOM data to stdout."""
self.save_gedcom(stdout)
- def save_gedcom(self, open_file, recursive=True):
- """Save GEDCOM data to a file
- :type open_file: file
- :type recursive: bool
+ def save_gedcom(self, open_file: IO, recursive: bool = True):
+ """Save GEDCOM data to a file.
"""
open_file.write(self.to_gedcom_string(recursive))
Return path from descendant to ancestor.
:rtype: object
Expand source code
-
def find_path_to_ancestor(self, descendant, ancestor, path=None):
- """Return path from descendant to ancestor
+
def find_path_to_ancestor(self, descendant: IndividualElement,
+ ancestor: IndividualElement, path: str = None):
+ """Return path from descendant to ancestor.
:rtype: object
"""
- if not isinstance(descendant, IndividualElement) and isinstance(ancestor, IndividualElement):
+ if not isinstance(descendant, IndividualElement) and isinstance(ancestor,
+ IndividualElement):
raise NotAnActualIndividualError(
"Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
)
@@ -1157,37 +1127,37 @@
Methods
if path[-1].get_pointer() == ancestor.get_pointer():
return path
- else:
- parents = self.get_parents(descendant, "NAT")
- for parent in parents:
- potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
- if potential_path is not None:
- return potential_path
+
+ parents = self.get_parents(descendant, "NAT")
+ for parent in parents:
+ potential_path = self.find_path_to_ancestor(parent, ancestor, path + [parent])
+ if potential_path is not None:
+ return potential_path
return None
Return elements corresponding to ancestors of an individual
-Optional ancestor_type. Default "ALL" returns all ancestors, "NAT" can be
-used to specify only natural (genetic) ancestors.
-:type individual: IndividualElement
-:type ancestor_type: str
-:rtype: list of Element
+
Return elements corresponding to ancestors of an individual.
+
Optional argument ancestor_type can be used to return specific subsets:
+
"ALL": Default, returns all ancestors.
+
"NAT": Return only natural (genetic) ancestors.
Expand source code
-
def get_ancestors(self, individual, ancestor_type="ALL"):
- """Return elements corresponding to ancestors of an individual
- Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
- used to specify only natural (genetic) ancestors.
- :type individual: IndividualElement
- :type ancestor_type: str
- :rtype: list of Element
+
def get_ancestors(self, individual: IndividualElement,
+ ancestor_type: str = "ALL") -> List[Element]:
+ """Return elements corresponding to ancestors of an individual.
+
+ Optional argument `ancestor_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all ancestors.
+
+ "NAT": Return only natural (genetic) ancestors.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1205,24 +1175,23 @@
Returns a dictionary containing all elements, identified by a pointer,
-from within the GEDCOM file
+from within the GEDCOM file.
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
This dictionary gets generated on-the-fly, but gets cached. If the
database was modified, you should call invalidate_cache() once to let
-this method return updated data.
-
:rtype: dict of Element
+this method return updated data.
Expand source code
-
def get_element_dictionary(self):
+
def get_element_dictionary(self) -> dict:
"""Returns a dictionary containing all elements, identified by a pointer,
- from within the GEDCOM file
+ from within the GEDCOM file.
Only elements identified by a pointer are listed in the dictionary.
The keys for the dictionary are the pointers.
@@ -1230,8 +1199,6 @@
Methods
This dictionary gets generated on-the-fly, but gets cached. If the
database was modified, you should call `invalidate_cache()` once to let
this method return updated data.
-
- :rtype: dict of Element
"""
if not self.__element_dictionary:
self.__element_dictionary = {
@@ -1243,24 +1210,23 @@
Returns a list containing all elements from within the GEDCOM file
+
Returns a list containing all elements from within the GEDCOM file.
By default elements are in the same order as they appeared in the file.
This list gets generated on-the-fly, but gets cached. If the database
was modified, you should call Parser.invalidate_cache() once
to let this method return updated data.
+the hierarchical GEDCOM tree, unless you rarely modify the database.
Expand source code
-
def get_element_list(self):
- """Returns a list containing all elements from within the GEDCOM file
+
def get_element_list(self) -> List[Element]:
+ """Returns a list containing all elements from within the GEDCOM file.
By default elements are in the same order as they appeared in the file.
@@ -1271,8 +1237,6 @@
Methods
Consider using `gedcom.parser.Parser.get_root_element()` or
`gedcom.parser.Parser.get_root_child_elements()` to access
the hierarchical GEDCOM tree, unless you rarely modify the database.
-
- :rtype: list of Element
"""
if not self.__element_list:
for element in self.get_root_child_elements():
@@ -1281,28 +1245,26 @@
Return family elements listed for an individual
-family_type can be tags.GEDCOM_TAG_FAMILY_SPOUSE (families where the individual is a spouse) or
-tags.GEDCOM_TAG_FAMILY_CHILD (families where the individual is a child). If a value is not
-provided, tags.GEDCOM_TAG_FAMILY_SPOUSE is default value.
-:type individual: IndividualElement
-:type family_type: str
-:rtype: list of FamilyElement
+
Return family elements listed for an individual.
+
Optional argument family_type can be used to return specific subsets:
+
tags.GEDCOM_TAG_FAMILY_SPOUSE: Default, families where the individual is a spouse.
+
tags.GEDCOM_TAG_FAMILY_CHILD: Families where the individual is a child.
Expand source code
-
def get_families(self, individual, family_type=tags.GEDCOM_TAG_FAMILY_SPOUSE):
- """Return family elements listed for an individual
- family_type can be `tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
- `tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
- provided, `tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.
- :type individual: IndividualElement
- :type family_type: str
- :rtype: list of FamilyElement
+
def get_families(self, individual: IndividualElement,
+ family_type: str = tags.GEDCOM_TAG_FAMILY_SPOUSE) -> List[FamilyElement]:
+ """Return family elements listed for an individual.
+
+ Optional argument `family_type` can be used to return specific subsets:
+
+ `tags.GEDCOM_TAG_FAMILY_SPOUSE`: Default, families where the individual is a spouse.
+
+ `tags.GEDCOM_TAG_FAMILY_CHILD`: Families where the individual is a child.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1323,34 +1285,35 @@
Return array of family members: individual, spouse, and children
-Optional argument members_type can be used to return specific subsets:
-"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
-"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
-"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
-"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
-"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
-:type family: FamilyElement
-:type members_type: str
-:rtype: list of IndividualElement
+
Return array of family members: individual, spouse, and children.
+
Optional argument members_type can be used to return specific subsets:
+
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
+
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
+
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
+
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
Expand source code
-
def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL):
- """Return array of family members: individual, spouse, and children
+
def get_family_members(self, family: FamilyElement,
+ members_type: str = FAMILY_MEMBERS_TYPE_ALL) -> List[IndividualElement]:
+ """Return array of family members: individual, spouse, and children.
+
Optional argument `members_type` can be used to return specific subsets:
+
"FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
+
"FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
+
"FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
+
"FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
+
"FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
- :type family: FamilyElement
- :type members_type: str
- :rtype: list of IndividualElement
"""
if not isinstance(family, FamilyElement):
raise NotAnActualFamilyError(
@@ -1383,20 +1346,16 @@
Returns a list of marriage years (as integers) for an individual
-:type individual: IndividualElement
-:rtype: list of int
+
Returns a list of marriage years for an individual.
Expand source code
-
def get_marriage_years(self, individual):
- """Returns a list of marriage years (as integers) for an individual
- :type individual: IndividualElement
- :rtype: list of int
+
def get_marriage_years(self, individual: IndividualElement) -> List[int]:
+ """Returns a list of marriage years for an individual.
"""
dates = []
@@ -1410,9 +1369,9 @@
Methods
for family in families:
for child in family.get_child_elements():
if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
- for childOfChild in child.get_child_elements():
- if childOfChild.get_tag() == tags.GEDCOM_TAG_DATE:
- date = childOfChild.get_value().split()[-1]
+ for gchild in child.get_child_elements():
+ if gchild.get_tag() == tags.GEDCOM_TAG_DATE:
+ date = gchild.get_value().split()[-1]
try:
dates.append(int(date))
except ValueError:
@@ -1421,20 +1380,18 @@
Returns a list of marriages of an individual formatted as a tuple (str date, str place)
-:type individual: IndividualElement
-:rtype: tuple
+
Returns a list of marriages of an individual formatted as a tuple:
+(str date, str place)
Expand source code
-
def get_marriages(self, individual):
- """Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
- :type individual: IndividualElement
- :rtype: tuple
+
def get_marriages(self, individual: IndividualElement) -> Tuple[str, str]:
+ """Returns a list of marriages of an individual formatted as a tuple:
+ (`str` date, `str` place)
"""
marriages = []
if not isinstance(individual, IndividualElement):
@@ -1458,26 +1415,26 @@
Return elements corresponding to parents of an individual
-Optional parent_type. Default "ALL" returns all parents. "NAT" can be
-used to specify only natural (genetic) parents.
-:type individual: IndividualElement
-:type parent_type: str
-:rtype: list of IndividualElement
+
Return elements corresponding to parents of an individual.
+
Optional argument parent_type can be used to return specific subsets:
+
"ALL": Default, returns all parents.
+
"NAT": Return only natural (genetic) parents.
Expand source code
-
def get_parents(self, individual, parent_type="ALL"):
- """Return elements corresponding to parents of an individual
- Optional parent_type. Default "ALL" returns all parents. "NAT" can be
- used to specify only natural (genetic) parents.
- :type individual: IndividualElement
- :type parent_type: str
- :rtype: list of IndividualElement
+
def get_parents(self, individual: IndividualElement,
+ parent_type: str = "ALL") -> List[IndividualElement]:
+ """Return elements corresponding to parents of an individual.
+
+ Optional argument `parent_type` can be used to return specific subsets:
+
+ "ALL": Default, returns all parents.
+
+ "NAT": Return only natural (genetic) parents.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1497,9 +1454,11 @@
Returns a list of logical records in the GEDCOM file
-
By default, elements are in the same order as they appeared in the file.
-
:rtype: list of Element
+
Returns a list of logical records in the GEDCOM file.
+
By default, elements are in the same order as they appeared in the file.
Expand source code
-
def get_root_child_elements(self):
- """Returns a list of logical records in the GEDCOM file
+
def get_root_child_elements(self) -> List[Element]:
+ """Returns a list of logical records in the GEDCOM file.
By default, elements are in the same order as they appeared in the file.
-
- :rtype: list of Element
"""
return self.get_root_element().get_child_elements()
Returns a virtual root element containing all logical records as children
-
When printed, this element converts to an empty string.
-
:rtype: RootElement
+
Returns a virtual root element containing all logical records as children.
+
When printed, this element converts to an empty string.
Expand source code
-
def get_root_element(self):
- """Returns a virtual root element containing all logical records as children
+
def get_root_element(self) -> RootElement:
+ """Returns a virtual root element containing all logical records as children.
When printed, this element converts to an empty string.
-
- :rtype: RootElement
"""
return self.__root_element
Check if one of the marriage years of an individual is in a given range. Years are integers.
-:type individual: IndividualElement
-:type from_year: int
-:type to_year: int
-:rtype: bool
+
Check if one of the marriage years of an individual is in a given range.
+Years are integers.
Expand source code
-
def marriage_range_match(self, individual, from_year, to_year):
- """Check if one of the marriage years of an individual is in a given range. Years are integers.
- :type individual: IndividualElement
- :type from_year: int
- :type to_year: int
- :rtype: bool
+
def marriage_range_match(self, individual: IndividualElement,
+ from_year: int, to_year: int) -> bool:
+ """Check if one of the marriage years of an individual is in a given range.
+ Years are integers.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1604,22 +1552,18 @@
Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
-:type individual: IndividualElement
-:type year: int
-:rtype: bool
+
Checks if one of the marriage years of an individual matches the supplied year.
+Year is an integer.
Expand source code
-
def marriage_year_match(self, individual, year):
- """Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
- :type individual: IndividualElement
- :type year: int
- :rtype: bool
+
def marriage_year_match(self, individual: IndividualElement, year: int) -> bool:
+ """Checks if one of the marriage years of an individual matches the supplied year.
+ Year is an integer.
"""
if not isinstance(individual, IndividualElement):
raise NotAnActualIndividualError(
@@ -1631,20 +1575,16 @@
Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
-:type gedcom_stream: a file stream, or str array of lines with new line at the end
-:type strict: bool
+
Parses a stream, or an array of lines, as GEDCOM formatted data.
Expand source code
-
def parse(self, gedcom_stream, strict=True):
- """Parses a stream, or an array of lines, as GEDCOM 5.5 formatted data
- :type gedcom_stream: a file stream, or str array of lines with new line at the end
- :type strict: bool
+
def parse(self, gedcom_stream: IO, strict: bool = True):
+ """Parses a stream, or an array of lines, as GEDCOM formatted data.
"""
self.invalidate_cache()
self.__root_element = RootElement()
@@ -1658,20 +1598,16 @@
Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
-:type file_path: str
-:type strict: bool
+
Opens and parses a file, from the given file path, as GEDCOM formatted data.
Expand source code
-
def parse_file(self, file_path, strict=True):
- """Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
- :type file_path: str
- :type strict: bool
+
def parse_file(self, file_path: str, strict: bool = True):
+ """Opens and parses a file, from the given file path, as GEDCOM formatted data.
"""
codec = get_encoding(file_path)
real_version, reported_version, reported_format = get_version(file_path, codec)
@@ -1695,49 +1631,44 @@
Methods
def print_gedcom(self)
-
Write GEDCOM data to stdout
+
Write GEDCOM data to stdout.
Expand source code
def print_gedcom(self):
- """Write GEDCOM data to stdout"""
- from sys import stdout
+ """Write GEDCOM data to stdout."""
self.save_gedcom(stdout)
Formats all elements and optionally all of the sub-elements into a GEDCOM string
-:type recursive: bool
+
Formats all elements and optionally all of the sub-elements into a
+GEDCOM string.
Expand source code
-
def to_gedcom_string(self, recursive=False):
- """Formats all elements and optionally all of the sub-elements into a GEDCOM string
- :type recursive: bool
+
def to_gedcom_string(self, recursive: bool = False) -> str:
+ """Formats all elements and optionally all of the sub-elements into a
+ GEDCOM string.
"""
is_gte_python_3 = version_info[0] >= 3
output = '' if is_gte_python_3 else b''
diff --git a/docs/gedcom/reader.html b/docs/gedcom/reader.html
index 52a87c7..51b5dee 100644
--- a/docs/gedcom/reader.html
+++ b/docs/gedcom/reader.html
@@ -6,7 +6,7 @@
gedcom.reader API documentation
+base `gedcom.parser.Parser` for extracting records as structured data." />
@@ -22,7 +22,7 @@
Module gedcom.reader
Module containing a Reader with higher order methods than the
-base Parser
+base Parser for extracting records as structured data.
Expand source code
@@ -57,9 +57,11 @@
Module gedcom.reader
"""
Module containing a `gedcom.reader.Reader` with higher order methods than the
-base `gedcom.parser.Parser`
+base `gedcom.parser.Parser` for extracting records as structured data.
"""
+from typing import Union
+
from gedcom.parser import Parser
from gedcom.element.header import HeaderElement
from gedcom.element.individual import IndividualElement
@@ -97,15 +99,14 @@
Module gedcom.reader
class Reader(Parser):
- """Simple wrapper class around the core parser with simple methods for
+ """Simple wrapper around the core `gedcom.parser.Parser` with methods for
extracting parsed records as structured data.
"""
- def get_records_by_type(self, record_type, output='list'):
- """Return either a list or dictionary with all the requested records
- :type: record_type: str
- :type: output: str
- :rtype: list or dict
+ def get_records_by_type(self, record_type: str,
+ return_output_as_list: bool = True) -> Union[list, dict]:
+ """Return either a list or dictionary with all of the requested records for the
+ given `gedcom.records` record type.
"""
record_list = []
record_dict = {}
@@ -113,7 +114,7 @@
Module gedcom.reader
for element in self.get_root_child_elements():
if isinstance(element, ELEMENT_TYPES[record_type]):
record = element.get_record()
- if output == 'list':
+ if return_output_as_list:
record_list.append(record)
else:
if RECORD_KEYS[record_type] is not None:
@@ -121,19 +122,18 @@
Module gedcom.reader
else:
record_dict.update({'@HEAD@': record})
- if output == 'list':
+ if return_output_as_list:
return record_list
return record_dict
- def get_all_records(self, entries='list'):
- """Return a dictionary with all the requested records
- :type: entries: str
- :rtype: dict
- """
+ def get_all_records(self, return_entries_as_list: bool = True) -> dict:
+ """Return a dictionary with all of the available records in the GEDCOM broken
+ down by record type."""
record_dict = {}
+
for key in RECORD_KEYS:
- if entries == 'list':
+ if return_entries_as_list:
record_dict.update({key: []})
else:
record_dict.update({key: {}})
@@ -142,7 +142,7 @@
Module gedcom.reader
for key in ELEMENT_TYPES:
if isinstance(element, ELEMENT_TYPES[key]):
record = element.get_record()
- if entries == 'list':
+ if return_entries_as_list:
record_dict[key].append(record)
else:
if key != 'header':
@@ -166,22 +166,21 @@
Classes
class Reader
-
Simple wrapper class around the core parser with simple methods for
+
Simple wrapper around the core Parser with methods for
extracting parsed records as structured data.
Expand source code
class Reader(Parser):
- """Simple wrapper class around the core parser with simple methods for
+ """Simple wrapper around the core `gedcom.parser.Parser` with methods for
extracting parsed records as structured data.
"""
- def get_records_by_type(self, record_type, output='list'):
- """Return either a list or dictionary with all the requested records
- :type: record_type: str
- :type: output: str
- :rtype: list or dict
+ def get_records_by_type(self, record_type: str,
+ return_output_as_list: bool = True) -> Union[list, dict]:
+ """Return either a list or dictionary with all of the requested records for the
+ given `gedcom.records` record type.
"""
record_list = []
record_dict = {}
@@ -189,7 +188,7 @@
Classes
for element in self.get_root_child_elements():
if isinstance(element, ELEMENT_TYPES[record_type]):
record = element.get_record()
- if output == 'list':
+ if return_output_as_list:
record_list.append(record)
else:
if RECORD_KEYS[record_type] is not None:
@@ -197,19 +196,18 @@
Classes
else:
record_dict.update({'@HEAD@': record})
- if output == 'list':
+ if return_output_as_list:
return record_list
return record_dict
- def get_all_records(self, entries='list'):
- """Return a dictionary with all the requested records
- :type: entries: str
- :rtype: dict
- """
+ def get_all_records(self, return_entries_as_list: bool = True) -> dict:
+ """Return a dictionary with all of the available records in the GEDCOM broken
+ down by record type."""
record_dict = {}
+
for key in RECORD_KEYS:
- if entries == 'list':
+ if return_entries_as_list:
record_dict.update({key: []})
else:
record_dict.update({key: {}})
@@ -218,7 +216,7 @@
Classes
for key in ELEMENT_TYPES:
if isinstance(element, ELEMENT_TYPES[key]):
record = element.get_record()
- if entries == 'list':
+ if return_entries_as_list:
record_dict[key].append(record)
else:
if key != 'header':
@@ -235,24 +233,22 @@
Return a dictionary with all the requested records
-:type: entries: str
-:rtype: dict
+
Return a dictionary with all of the available records in the GEDCOM broken
+down by record type.
Expand source code
-
def get_all_records(self, entries='list'):
- """Return a dictionary with all the requested records
- :type: entries: str
- :rtype: dict
- """
+
def get_all_records(self, return_entries_as_list: bool = True) -> dict:
+ """Return a dictionary with all of the available records in the GEDCOM broken
+ down by record type."""
record_dict = {}
+
for key in RECORD_KEYS:
- if entries == 'list':
+ if return_entries_as_list:
record_dict.update({key: []})
else:
record_dict.update({key: {}})
@@ -261,7 +257,7 @@
Methods
for key in ELEMENT_TYPES:
if isinstance(element, ELEMENT_TYPES[key]):
record = element.get_record()
- if entries == 'list':
+ if return_entries_as_list:
record_dict[key].append(record)
else:
if key != 'header':
@@ -273,22 +269,19 @@
Return either a list or dictionary with all the requested records
-:type: record_type: str
-:type: output: str
-:rtype: list or dict
+
Return either a list or dictionary with all of the requested records for the
+given gedcom.records record type.
Expand source code
-
def get_records_by_type(self, record_type, output='list'):
- """Return either a list or dictionary with all the requested records
- :type: record_type: str
- :type: output: str
- :rtype: list or dict
+
def get_records_by_type(self, record_type: str,
+ return_output_as_list: bool = True) -> Union[list, dict]:
+ """Return either a list or dictionary with all of the requested records for the
+ given `gedcom.records` record type.
"""
record_list = []
record_dict = {}
@@ -296,7 +289,7 @@
Methods
for element in self.get_root_child_elements():
if isinstance(element, ELEMENT_TYPES[record_type]):
record = element.get_record()
- if output == 'list':
+ if return_output_as_list:
record_list.append(record)
else:
if RECORD_KEYS[record_type] is not None:
@@ -304,7 +297,7 @@
Methods
else:
record_dict.update({'@HEAD@': record})
- if output == 'list':
+ if return_output_as_list:
return record_list
return record_dict
Module containing the standard GEDCOM record types recognized by the
+GEDCOM Reader.
+
+
+Expand source code
+
+
# -*- coding: utf-8 -*-
+
+# Python GEDCOM Parser
+#
+# Copyright (C) 2020 Christopher Horn (cdhorn at embarqmail dot com)
+# Copyright (C) 2018 Damon Brodie (damon.brodie at gmail.com)
+# Copyright (C) 2018-2019 Nicklas Reincke (contact at reynke.com)
+# Copyright (C) 2016 Andreas Oberritter
+# Copyright (C) 2012 Madeleine Price Ball
+# Copyright (C) 2005 Daniel Zappala (zappala at cs.byu.edu)
+# Copyright (C) 2005 Brigham Young University
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+
+"""Module containing the standard GEDCOM record types recognized by the
+GEDCOM `gedcom.reader.Reader`."""
+
+
+GEDCOM_RECORD_FAMILY = 'family'
+"""Identifies the `FAM_RECORD` record type."""
+
+GEDCOM_RECORD_HEADER = 'header'
+"""Identifies the `HEADER` record type."""
+
+GEDCOM_RECORD_INDIVIDUAL = 'individual'
+"""Identifies the `INDIVIDUAL_RECORD` record type."""
+
+GEDCOM_RECORD_NOTE = 'note'
+"""Identifies the `NOTE_RECORD` record type."""
+
+GEDCOM_RECORD_SOURCE = 'source'
+"""Identifies the `SOURCE_RECORD` record type."""
+
+GEDCOM_RECORD_REPOSITORY = 'repository'
+"""Identifies the `REPOSITORY_RECORD` record type."""
+
+GEDCOM_RECORD_SUBMISSION = 'submission'
+"""Identifies the `SUBMISSION_RECORD` record type."""
+
+GEDCOM_RECORD_SUBMITTER = 'submitter'
+"""Identifies the `SUBMITTER_RECORD` record type."""
+
+
+
+
+
+
Global variables
+
+
var GEDCOM_RECORD_FAMILY
+
+
Identifies the FAM_RECORD record type.
+
+
var GEDCOM_RECORD_HEADER
+
+
Identifies the HEADER record type.
+
+
var GEDCOM_RECORD_INDIVIDUAL
+
+
Identifies the INDIVIDUAL_RECORD record type.
+
+
var GEDCOM_RECORD_NOTE
+
+
Identifies the NOTE_RECORD record type.
+
+
var GEDCOM_RECORD_REPOSITORY
+
+
Identifies the REPOSITORY_RECORD record type.
+
+
var GEDCOM_RECORD_SOURCE
+
+
Identifies the SOURCE_RECORD record type.
+
+
var GEDCOM_RECORD_SUBMISSION
+
+
Identifies the SUBMISSION_RECORD record type.
+
+
var GEDCOM_RECORD_SUBMITTER
+
+
Identifies the SUBMITTER_RECORD record type.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/gedcom/standards.html b/docs/gedcom/standards.html
index 5f7af48..59fa416 100644
--- a/docs/gedcom/standards.html
+++ b/docs/gedcom/standards.html
@@ -5,7 +5,7 @@
gedcom.standards API documentation
-
+
@@ -20,7 +20,7 @@
Module gedcom.standards
-
The official FamilySearch 5.5 standard
+
Module containing links to the documentation for the various GEDCOM standards.
Expand source code
@@ -53,20 +53,22 @@
Module gedcom.standards
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
-"""The official FamilySearch 5.5 standard"""
+"""Module containing links to the documentation for the various GEDCOM standards."""
+
GEDCOM_5_5 = "https://edge.fscdn.org/assets/img/documents/" + \
"gedcom55-82e1509bd8dbe7477e3b500e4f62c240.pdf"
+"""The official FamilySearch GEDCOM 5.5 Standard."""
-"""The official FamilySearch 5.5.1 standard"""
GEDCOM_5_5_1 = "https://edge.fscdn.org/assets/img/documents/" + \
"ged551-5bac5e57fe88dd37df0e153d9c515335.pdf"
+"""The official FamilySearch GEDCOM 5.5.1 Standard."""
-"""The GEDCOM-L working group 5.5.1 addendum"""
GEDCOM_5_5_1_GEDCOM_L_ADDENDUM = "https://genealogy.net/GEDCOM/" + \
"GEDCOM551%20GEDCOM-L%20Addendum-R1.pdf"
+"""The GEDCOM-L working group GEDCOM 5.5.1 Addendum."""
-"""The gedcom.org 5.5.5 specification with annotations"""
-GEDCOM_5_5_5 = "https://www.gedcom.org/specs/GEDCOM555.zip"
+GEDCOM_5_5_5 = "https://www.gedcom.org/specs/GEDCOM555.zip"
+"""The gedcom.org GEDCOM 5.5.5 Specification With Annotations."""
@@ -76,15 +78,19 @@
Global variables
var GEDCOM_5_5
-
The official FamilySearch 5.5.1 standard
+
The official FamilySearch GEDCOM 5.5 Standard.
var GEDCOM_5_5_1
-
The GEDCOM-L working group 5.5.1 addendum
+
The official FamilySearch GEDCOM 5.5.1 Standard.
var GEDCOM_5_5_1_GEDCOM_L_ADDENDUM
-
The gedcom.org 5.5.5 specification with annotations
+
The GEDCOM-L working group GEDCOM 5.5.1 Addendum.
+
+
var GEDCOM_5_5_5
+
+
The gedcom.org GEDCOM 5.5.5 Specification With Annotations.
Substructure parser for the ADDRESS_STRUCTURE embedded record.
-
Note this is usually referenced as part of a larger structure and the
-GEDCOM_TAG_ADDRESS tag is at the same level as some of
+
Substructure parser for a ADDRESS_STRUCTURE embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
+The GEDCOM_TAG_ADDRESS tag is at the same level as some of
the other parts of this structure.
@@ -51,14 +51,15 @@
Module gedcom.subparsers.address_structure
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the ADDRESS_STRUCTURE embedded record.
+Substructure parser for a `ADDRESS_STRUCTURE` embedded record.
-Note this is usually referenced as part of a larger structure and the
-`gedcom.tags.GEDCOM_TAG_ADDRESS` tag is at the same level as some of
+This is referenced as part of a larger structure so there is no anchor tag.
+The `gedcom.tags.GEDCOM_TAG_ADDRESS` tag is at the same level as some of
the other parts of this structure.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
ADDRESS_TAGS = {
tags.GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE: 'addresse',
@@ -79,9 +80,10 @@
Module gedcom.subparsers.address_structure
}
-def address_structure(element):
- """Parses and extracts the ADDRESS_STRUCTURE
- :rtype: dict
+def address_structure(element: Element) -> dict:
+ """Parses and extracts a `ADDRESS_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'address': '',
@@ -120,18 +122,19 @@
Parses and extracts the ADDRESS_STRUCTURE
-:rtype: dict
+
Parses and extracts a ADDRESS_STRUCTURE structure.
+
The element should be the parent that contains it.
Expand source code
-
def address_structure(element):
- """Parses and extracts the ADDRESS_STRUCTURE
- :rtype: dict
+
def address_structure(element: Element) -> dict:
+ """Parses and extracts a `ADDRESS_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'address': '',
diff --git a/docs/gedcom/subparsers/association_structure.html b/docs/gedcom/subparsers/association_structure.html
index b196418..b5ccdcd 100644
--- a/docs/gedcom/subparsers/association_structure.html
+++ b/docs/gedcom/subparsers/association_structure.html
@@ -5,8 +5,7 @@
gedcom.subparsers.association_structure API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.association_structure
-
Substructure parser for the ASSOCIATION_STRUCTURE record identified by the
-GEDCOM_TAG_ASSOCIATES tag.
+
Substructure parser for the ASSOCIATION_STRUCTURE record.
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the CHANGE_DATE record identified by the
-`gedcom.tags.GEDCOM_TAG_CHANGE` tag.
+Substructure parser for a `CHANGE_DATE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_CHANGE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def change_date(element):
- """Parses and extracts the CHANGE_DATE
- :rtype: dict
+def change_date(element: Element) -> dict:
+ """Parses and extracts a `CHANGE_DATE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_CHANGE` tag.
"""
record = {
'date': '',
@@ -90,18 +92,19 @@
def child_to_family_link(element):
- """Parses and extracts the CHILD_TO_FAMILY_LINK
- :rtype: dict
+
def child_to_family_link(element: Element) -> dict:
+ """Parses and extracts a `CHILD_TO_FAMILY_LINK` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` tag.
"""
record = {
'key_to_family': element.get_value(),
diff --git a/docs/gedcom/subparsers/event_detail.html b/docs/gedcom/subparsers/event_detail.html
index e9969bc..6e6e876 100644
--- a/docs/gedcom/subparsers/event_detail.html
+++ b/docs/gedcom/subparsers/event_detail.html
@@ -5,8 +5,7 @@
gedcom.subparsers.event_detail API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.event_detail
-
Substructure parser for the EVENT_DETAIL embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a EVENT_DETAIL embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,11 +49,13 @@
Module gedcom.subparsers.event_detail
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the EVENT_DETAIL embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `EVENT_DETAIL` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.place_structure import place_structure
from gedcom.subparsers.address_structure import address_structure
from gedcom.subparsers.note_structure import note_structure
@@ -71,9 +72,10 @@
Module gedcom.subparsers.event_detail
}
-def event_detail(element):
- """Parses and extracts the EVENT_DETAIL
- :rtype: dict
+def event_detail(element: Element) -> dict:
+ """Parses and extracts a `EVENT_DETAIL` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'type': '',
@@ -123,18 +125,19 @@
Parses and extracts the EVENT_DETAIL
-:rtype: dict
+
Parses and extracts a EVENT_DETAIL structure.
+
The element should be the parent that contains it.
Expand source code
-
def event_detail(element):
- """Parses and extracts the EVENT_DETAIL
- :rtype: dict
+
def event_detail(element: Element) -> dict:
+ """Parses and extracts a `EVENT_DETAIL` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'type': '',
diff --git a/docs/gedcom/subparsers/family_event_detail.html b/docs/gedcom/subparsers/family_event_detail.html
index 08b7fd4..51972b5 100644
--- a/docs/gedcom/subparsers/family_event_detail.html
+++ b/docs/gedcom/subparsers/family_event_detail.html
@@ -5,8 +5,7 @@
gedcom.subparsers.family_event_detail API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.family_event_detail
-
Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a FAMILY_EVENT_DETAIL emdedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,17 +49,20 @@
Module gedcom.subparsers.family_event_detail
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `FAMILY_EVENT_DETAIL` emdedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.event_detail import event_detail
-def family_event_detail(element):
- """Parses and extracts the FAMILY_EVENT_DETAIL
- :rtype: dict
+def family_event_detail(element: Element) -> dict:
+ """Parses and extracts a `FAMILY_EVENT_DETAIL` structure.
+
+ The `element` shouldbe the parent that contains it.
"""
record = event_detail(element)
record['husband_age'] = ''
@@ -88,18 +90,19 @@
Parses and extracts the FAMILY_EVENT_DETAIL
-:rtype: dict
+
Parses and extracts a FAMILY_EVENT_DETAIL structure.
+
The element shouldbe the parent that contains it.
Expand source code
-
def family_event_detail(element):
- """Parses and extracts the FAMILY_EVENT_DETAIL
- :rtype: dict
+
def family_event_detail(element: Element) -> dict:
+ """Parses and extracts a `FAMILY_EVENT_DETAIL` structure.
+
+ The `element` shouldbe the parent that contains it.
"""
record = event_detail(element)
record['husband_age'] = ''
diff --git a/docs/gedcom/subparsers/family_event_structure.html b/docs/gedcom/subparsers/family_event_structure.html
index 39f4ab5..972cff6 100644
--- a/docs/gedcom/subparsers/family_event_structure.html
+++ b/docs/gedcom/subparsers/family_event_structure.html
@@ -5,8 +5,7 @@
gedcom.subparsers.family_event_structure API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.family_event_structure
-
Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a FAMILY_EVENT_STRUCTURE embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,11 +49,15 @@
Module gedcom.subparsers.family_event_structure
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `FAMILY_EVENT_STRUCTURE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.family_event_detail import family_event_detail
EVENT_TAGS = {
@@ -73,9 +76,10 @@
Module gedcom.subparsers.family_event_structure
}
-def family_event_structure(element):
- """Parses and extracts the FAMILY_EVENT_STRUCTURE
- :rtype: dict
+def family_event_structure(element: Element) -> List[dict]:
+ """Parses and extracts a `FAMILY_EVENT_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
@@ -97,18 +101,19 @@
Parses and extracts the FAMILY_EVENT_STRUCTURE
-:rtype: dict
+
Parses and extracts a FAMILY_EVENT_STRUCTURE structure.
+
The element should be the parent that contains it.
Expand source code
-
def family_event_structure(element):
- """Parses and extracts the FAMILY_EVENT_STRUCTURE
- :rtype: dict
+
def family_event_structure(element: Element) -> List[dict]:
+ """Parses and extracts a `FAMILY_EVENT_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/docs/gedcom/subparsers/index.html b/docs/gedcom/subparsers/index.html
index 2299960..6add805 100644
--- a/docs/gedcom/subparsers/index.html
+++ b/docs/gedcom/subparsers/index.html
@@ -5,7 +5,8 @@
gedcom.subparsers API documentation
-
+
@@ -20,6 +21,8 @@
Module gedcom.subparsers
+
Module containing parsers for extracting various substructures from the
+different record types as defined in the GEDCOM standard.
Expand source code
@@ -46,6 +49,9 @@
Module gedcom.subparsers
#
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
+"""Module containing parsers for extracting various substructures from the
+different record types as defined in the GEDCOM standard."""
+
__all__ = [
"address_structure",
"association_structure",
@@ -76,107 +82,87 @@
Substructure parser for the FAMILY_EVENT_DETAIL emdedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a FAMILY_EVENT_DETAIL emdedded record …
Substructure parser for the FAMILY_EVENT_STRUCTURE embedded record. As this is
-referenced in place as part of another structure there is no identifier …
+
Substructure parser for a FAMILY_EVENT_STRUCTURE embedded record …
Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a LDS_SPOUSE_SEALING embedded record …
Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
-referenced in place in part of another structure there is no identifier tag.
+
Substructure parser for a PERSONAL_NAME_PIECES embedded record …
Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record. As
-this is referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,11 +49,15 @@
Module gedcom.subparsers.individual_attribute_structure<
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record. As
-this is referenced in place as part of another structure there is no identifier tag.
+Substructure parser for the `INDIVIDUAL_ATTRIBUTE_STRUCTURE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.individual_event_detail import individual_event_detail
ATTRIBUTE_TAGS = {
@@ -76,9 +79,10 @@
Module gedcom.subparsers.individual_attribute_structure<
}
-def individual_attribute_structure(element):
- """Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
- :rtype: dict
+def individual_attribute_structure(element: Element) -> List[dict]:
+ """Parses and extracts the `INDIVIDUAL_ATTRIBUTE_STRUCTURE` structures.
+
+ The `element` should be the parent that contains them.
"""
records = []
for child in element.get_child_elements():
@@ -101,18 +105,19 @@
Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
-:rtype: dict
+
Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE structures.
+
The element should be the parent that contains them.
Expand source code
-
def individual_attribute_structure(element):
- """Parses and extracts the INDIVIDUAL_ATTRIBUTE_STRUCTURE
- :rtype: dict
+
def individual_attribute_structure(element: Element) -> List[dict]:
+ """Parses and extracts the `INDIVIDUAL_ATTRIBUTE_STRUCTURE` structures.
+
+ The `element` should be the parent that contains them.
"""
records = []
for child in element.get_child_elements():
diff --git a/docs/gedcom/subparsers/individual_event_detail.html b/docs/gedcom/subparsers/individual_event_detail.html
index bdd4118..0706915 100644
--- a/docs/gedcom/subparsers/individual_event_detail.html
+++ b/docs/gedcom/subparsers/individual_event_detail.html
@@ -5,8 +5,7 @@
gedcom.subparsers.individual_event_detail API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.individual_event_detail
-
Substructure parser for the INDIVIDUAL_EVENT_DETAIL emdedded record. As this
-is referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a INDIVIDUAL_EVENT_DETAIL emdedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,17 +49,20 @@
Module gedcom.subparsers.individual_event_detail<
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the INDIVIDUAL_EVENT_DETAIL emdedded record. As this
-is referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `INDIVIDUAL_EVENT_DETAIL` emdedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.event_detail import event_detail
-def individual_event_detail(element):
- """Parses and extracts INDIVIDUAL_EVENT_DETAIL
- :rtype: dict
+def individual_event_detail(element: Element) -> dict:
+ """Parses and extracts a `INDIVIDUAL_EVENT_DETAIL` structure.
+
+ The `element` should be the parent that contains it.
"""
record = event_detail(element)
record['age'] = ''
@@ -79,18 +81,19 @@
def individual_event_detail(element: Element) -> dict:
+ """Parses and extracts a `INDIVIDUAL_EVENT_DETAIL` structure.
+
+ The `element` should be the parent that contains it.
"""
record = event_detail(element)
record['age'] = ''
diff --git a/docs/gedcom/subparsers/individual_event_structure.html b/docs/gedcom/subparsers/individual_event_structure.html
index 660175d..dd8eef8 100644
--- a/docs/gedcom/subparsers/individual_event_structure.html
+++ b/docs/gedcom/subparsers/individual_event_structure.html
@@ -5,8 +5,7 @@
gedcom.subparsers.individual_event_structure API documentation
-
+
@@ -21,8 +20,8 @@
Substructure parser for the INDIVIDUAL_EVENT_STRUCTURE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a INDIVIDUAL_EVENT_STRUCTURE embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
-:rtype: dict
+
Parses and extracts a INDIVIDUAL_EVENT_STRUCTURE structure.
+
The element should be the parent that contains it.
Expand source code
-
def individual_event_structure(element):
- """Parses and extracts the INDIVIDUAL_EVENT_STRUCTURE
- :rtype: dict
+
def individual_event_structure(element: Element) -> List[dict]:
+ """Parses and extracts a `INDIVIDUAL_EVENT_STRUCTURE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/docs/gedcom/subparsers/lds_individual_ordinance.html b/docs/gedcom/subparsers/lds_individual_ordinance.html
index 0b928dd..cdc657d 100644
--- a/docs/gedcom/subparsers/lds_individual_ordinance.html
+++ b/docs/gedcom/subparsers/lds_individual_ordinance.html
@@ -5,8 +5,7 @@
gedcom.subparsers.lds_individual_ordinance API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.lds_individual_ordinance
-
Substructure parser for the LDS_INDIVIDUAL_ORDINANCE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a LDS_INDIVIDUAL_ORDINANCE embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,11 +49,15 @@
Module gedcom.subparsers.lds_individual_ordinance
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the LDS_INDIVIDUAL_ORDINANCE embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `LDS_INDIVIDUAL_ORDINANCE` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
@@ -73,9 +76,10 @@
Module gedcom.subparsers.lds_individual_ordinance
}
-def lds_individual_ordinance(element):
- """Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
- :rtype: dict
+def lds_individual_ordinance(element: Element) -> List[dict]:
+ """Parses and extracts a `LDS_INDIVIDUAL_ORDINANCE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
@@ -127,18 +131,19 @@
Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
-:rtype: dict
+
Parses and extracts a LDS_INDIVIDUAL_ORDINANCE structure.
+
The element should be the parent that contains it.
Expand source code
-
def lds_individual_ordinance(element):
- """Parses and extracts the LDS_INDIVIDUAL_ORDINANCE
- :rtype: dict
+
def lds_individual_ordinance(element: Element) -> List[dict]:
+ """Parses and extracts a `LDS_INDIVIDUAL_ORDINANCE` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/docs/gedcom/subparsers/lds_spouse_sealing.html b/docs/gedcom/subparsers/lds_spouse_sealing.html
index 18b05a3..8d5d0a1 100644
--- a/docs/gedcom/subparsers/lds_spouse_sealing.html
+++ b/docs/gedcom/subparsers/lds_spouse_sealing.html
@@ -5,8 +5,7 @@
gedcom.subparsers.lds_spouse_sealing API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.lds_spouse_sealing
-
Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+
Substructure parser for a LDS_SPOUSE_SEALING embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
Expand source code
@@ -50,11 +49,15 @@
Module gedcom.subparsers.lds_spouse_sealing
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the LDS_SPOUSE_SEALING embedded record. As this is
-referenced in place as part of another structure there is no identifier tag.
+Substructure parser for a `LDS_SPOUSE_SEALING` embedded record.
+
+This is referenced as part of a larger structure so there is no anchor tag.
"""
+from typing import List
+
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
from gedcom.subparsers.source_citation import source_citation
@@ -66,9 +69,10 @@
Module gedcom.subparsers.lds_spouse_sealing
}
-def lds_spouse_sealing(element):
- """Parses and extracts the LDS_SPOUSE_SEALING
- :rtype: dict
+def lds_spouse_sealing(element: Element) -> List[dict]:
+ """Parses and extracts a `LDS_SPOUSE_SEALING` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
@@ -118,18 +122,19 @@
Parses and extracts the LDS_SPOUSE_SEALING
-:rtype: dict
+
Parses and extracts a LDS_SPOUSE_SEALING structure.
+
The element should be the parent that contains it.
Expand source code
-
def lds_spouse_sealing(element):
- """Parses and extracts the LDS_SPOUSE_SEALING
- :rtype: dict
+
def lds_spouse_sealing(element: Element) -> List[dict]:
+ """Parses and extracts a `LDS_SPOUSE_SEALING` structure.
+
+ The `element` should be the parent that contains it.
"""
records = []
for child in element.get_child_elements():
diff --git a/docs/gedcom/subparsers/multimedia_link.html b/docs/gedcom/subparsers/multimedia_link.html
index 4ff3962..fe4d7ab 100644
--- a/docs/gedcom/subparsers/multimedia_link.html
+++ b/docs/gedcom/subparsers/multimedia_link.html
@@ -5,8 +5,7 @@
gedcom.subparsers.multimedia_link API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.multimedia_link
-
Substructure parser for the MULTIMEDIA_LINK record identified by the
-GEDCOM_TAG_OBJECT tag.
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the MULTIMEDIA_LINK record identified by the
-`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
+Substructure parser for a `MULTIMEDIA_LINK` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_OBJECT` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
MEDIA_TAGS = {
tags.GEDCOM_TAG_FILE: 'file',
@@ -66,9 +67,10 @@
Module gedcom.subparsers.multimedia_link
}
-def multimedia_link(element):
- """Parse and extract a MULTIMEDIA_LINK
- :rtype: dict
+def multimedia_link(element: Element) -> dict:
+ """Parse and extract a `MULTIMEDIA_LINK` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_OBJECT` tag.
"""
record = {
'key_to_object': element.get_value(),
@@ -109,18 +111,19 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the NOTE_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_NOTE` tag.
+Substructure parser for a `NOTE_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_NOTE` tag.
"""
+from gedcom.element.element import Element
+
-def note_structure(element):
- """Parse and extract a NOTE_STRUCTURE
- :rtype: dict
+def note_structure(element: Element) -> dict:
+ """Parse and extract a `NOTE_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_NOTE` tag.
"""
record = {
'key_to_note': element.get_value(),
@@ -80,18 +83,19 @@
def note_structure(element):
- """Parse and extract a NOTE_STRUCTURE
- :rtype: dict
+
def note_structure(element: Element) -> dict:
+ """Parse and extract a `NOTE_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_NOTE` tag.
"""
record = {
'key_to_note': element.get_value(),
diff --git a/docs/gedcom/subparsers/personal_name_pieces.html b/docs/gedcom/subparsers/personal_name_pieces.html
index 41fe7f6..69e94a5 100644
--- a/docs/gedcom/subparsers/personal_name_pieces.html
+++ b/docs/gedcom/subparsers/personal_name_pieces.html
@@ -5,8 +5,7 @@
gedcom.subparsers.personal_name_pieces API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.personal_name_pieces
-
Substructure parser for the PERSONAL_NAME_PIECES embedded record. As this is
-referenced in place in part of another structure there is no identifier tag.
+
Substructure parser for a PERSONAL_NAME_PIECES embedded record.
+
This is referenced as part of a larger structure so there is no anchor tag.
def personal_name_pieces(element: Element) -> dict:
+ """Parse and extract a `PERSONAL_NAME_PIECES` structure.
+
+ The `element` should be the parent that contains it.
"""
record = {
'prefix': '',
diff --git a/docs/gedcom/subparsers/personal_name_structure.html b/docs/gedcom/subparsers/personal_name_structure.html
index e2f8ab0..ebc7a80 100644
--- a/docs/gedcom/subparsers/personal_name_structure.html
+++ b/docs/gedcom/subparsers/personal_name_structure.html
@@ -5,8 +5,7 @@
gedcom.subparsers.personal_name_structure API documentation
-
+
@@ -21,8 +20,8 @@
Module gedcom.subparsers.personal_name_structure
-
Substructure parser for the PERSONAL_NAME_STRUCTURE record identified by the
-GEDCOM_TAG_NAME tag.
+
Substructure parser for a PERSONAL_NAME_STRUCTURE record.
Module gedcom.subparsers.personal_name_structure<
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the PERSONAL_NAME_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_NAME` tag.
+Substructure parser for a `PERSONAL_NAME_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_NAME` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.personal_name_pieces import personal_name_pieces
-def extract_name(element):
- """Parse and extract name record in a PERSONAL_NAME_STRUCTURE
- :rtype: dict
+def extract_name(element: Element) -> dict:
+ """Parse and extract a `NAME` for a `PERSONAL_NAME_STRUCTURE` structure.
+
+ The `element` should contain one of the name tags:
+
+ `gedcom.tags.GEDCOM_TAG_NAME`
+
+ `gedcom.tags.GEDCOM_TAG_PHONETIC`
+
+ `gedcom.tags.GEDCOM_TAG_ROMANIZED`
"""
record = {
'name': '',
@@ -75,9 +83,10 @@
Module gedcom.subparsers.personal_name_structure<
return record
-def personal_name_structure(element):
- """Parse and extract a PERSONAL_NAME_STRUCTURE
- :rtype: dict
+def personal_name_structure(element: Element) -> dict:
+ """Parse and extract a `PERSONAL_NAME_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_NAME` tag.
"""
record = extract_name(element)
record['phonetic'] = []
@@ -102,18 +111,28 @@
def extract_name(element):
- """Parse and extract name record in a PERSONAL_NAME_STRUCTURE
- :rtype: dict
+
def extract_name(element: Element) -> dict:
+ """Parse and extract a `NAME` for a `PERSONAL_NAME_STRUCTURE` structure.
+
+ The `element` should contain one of the name tags:
+
+ `gedcom.tags.GEDCOM_TAG_NAME`
+
+ `gedcom.tags.GEDCOM_TAG_PHONETIC`
+
+ `gedcom.tags.GEDCOM_TAG_ROMANIZED`
"""
record = {
'name': '',
@@ -129,18 +148,19 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the PLACE_STRUCTURE record identified by the
-`gedcom.tags.GEDCOM_TAG_PLACE` tag.
+Substructure parser for a `PLACE_STRUCTURE` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_PLACE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.note_structure import note_structure
-def place_structure(element):
- """Parse and extract a PLACE_STRUCTURE
- :rtype: dict
+def place_structure(element: Element) -> dict:
+ """Parse and extract a `PLACE_STRUCTURE` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_PLACE` tag.
"""
record = {
'name': element.get_value(),
@@ -122,18 +124,19 @@
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Substructure parser for the SOURCE_CITATION record identified by the
-`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
+Substructure parser for a `SOURCE_CITATION` record.
+
+This is anchored by the `gedcom.tags.GEDCOM_TAG_SOURCE` tag.
"""
import gedcom.tags as tags
+from gedcom.element.element import Element
from gedcom.subparsers.multimedia_link import multimedia_link
from gedcom.subparsers.note_structure import note_structure
@@ -66,9 +67,10 @@
Module gedcom.subparsers.source_citation
}
-def source_citation(element):
- """Parse and extract a SOURCE_CITATION
- :rtype: dict
+def source_citation(element: Element) -> dict:
+ """Parse and extract a `SOURCE_CITATION` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_SOURCE` tag.
"""
record = {
'key_to_source': element.get_value(),
@@ -131,18 +133,19 @@
def user_reference_number(element: Element) -> dict:
+ """Parse and extract a `USER_REFERENCE_NUMBER` structure.
+
+ The `element` should contain the `gedcom.tags.GEDCOM_TAG_REFERENCE` tag.
"""
record = {
'reference': element.get_value(),
diff --git a/docs/gedcom/tags.html b/docs/gedcom/tags.html
index dd9f85e..ae9d7c5 100644
--- a/docs/gedcom/tags.html
+++ b/docs/gedcom/tags.html
@@ -5,7 +5,7 @@
gedcom.tags API documentation
-
+
@@ -20,7 +20,7 @@
Module gedcom.tags
-
Standard GEDCOM tags and some common program defined extensions
+
Module containing the standard GEDCOM tags and some of the most common program defined extensions.
Expand source code
@@ -54,7 +54,7 @@
Module gedcom.tags
# Further information about the license: http://www.gnu.org/licenses/gpl-2.0.html
"""
-Standard GEDCOM tags and some common program defined extensions
+Module containing the standard GEDCOM tags and some of the most common program defined extensions.
"""
GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE = "_NAME"
diff --git a/gedcom/element/element.py b/gedcom/element/element.py
index a1e9065..c62b1af 100644
--- a/gedcom/element/element.py
+++ b/gedcom/element/element.py
@@ -181,13 +181,13 @@ def set_multi_line_value(self, value: str):
n = self.__add_bounded_child(gedcom.tags.GEDCOM_TAG_CONTINUED, line)
self.__add_concatenation(line[n:])
- def get_child_elements(self) -> List[Element]:
+ def get_child_elements(self) -> List['Element']:
"""Returns the direct child elements of this element.
"""
return self.__children
def new_child_element(self, tag: str, pointer: str = "",
- value: str = "") -> Element:
+ value: str = "") -> 'Element':
"""Creates and returns a new child element of this element.
"""
from gedcom.element.family import FamilyElement
@@ -236,7 +236,7 @@ def new_child_element(self, tag: str, pointer: str = "",
return child_element
- def add_child_element(self, element: Element):
+ def add_child_element(self, element: 'Element'):
"""Adds a child element to this element.
"""
self.get_child_elements().append(element)
@@ -244,12 +244,12 @@ def add_child_element(self, element: Element):
return element
- def get_parent_element(self) -> Element:
+ def get_parent_element(self) -> 'Element':
"""Returns the parent element of this element.
"""
return self.__parent
- def set_parent_element(self, element: Element):
+ def set_parent_element(self, element: 'Element'):
"""Adds a parent element to this element.
There's usually no need to call this method manually,
diff --git a/gedcom/subparsers/spouse_to_family_link.py b/gedcom/subparsers/spouse_to_family_link.py
index 3891c5f..3d2895e 100644
--- a/gedcom/subparsers/spouse_to_family_link.py
+++ b/gedcom/subparsers/spouse_to_family_link.py
@@ -33,7 +33,7 @@
def spouse_to_family_link(element: Element) -> dict:
"""Parse and extract a `SPOUSE_TO_FAMILY_LINK` structure.
-
+
The `element` should contain the `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` tag.
"""
record = {
diff --git a/gedcom/subparsers/user_reference_number.py b/gedcom/subparsers/user_reference_number.py
index f87428e..a1e4d7c 100644
--- a/gedcom/subparsers/user_reference_number.py
+++ b/gedcom/subparsers/user_reference_number.py
@@ -32,6 +32,7 @@
import gedcom.tags as tags
from gedcom.element.element import Element
+
def user_reference_number(element: Element) -> dict:
"""Parse and extract a `USER_REFERENCE_NUMBER` structure.