diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e32b928..d729248 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,6 +51,7 @@ jobs: - name: Generate docs run: >- + rm -rf docs/ & \ pipenv run pdoc3 --html -o docs/ gedcom --force - name: Publish docs diff --git a/Pipfile b/Pipfile index 70a511c..ff5cedb 100644 --- a/Pipfile +++ b/Pipfile @@ -12,6 +12,8 @@ pdoc3 = "*" bump2version = "*" [packages] +chardet = "*" +ansel = "*" [requires] python_version = "3.5" diff --git a/Pipfile.lock b/Pipfile.lock index 24243b8..acd7d59 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "edb2b647f8925bfcd2241475ee31fd5e5ef5c45920e81ccf92bd1f621216b8f1" + "sha256": "2120e027fb9aa8553ac73e14c63ced1ba2cba8fdd76d02abad3d8b6313fdb0cf" }, "pipfile-spec": 6, "requires": { @@ -15,7 +15,31 @@ } ] }, - "default": {}, + "default": { + "ansel": { + "hashes": [ + "sha256:27c1a849b1a683a2b3befd50e9156bda3527e8026f6bc6f04c3d0a2b9cadeed9", + "sha256:3cb2c6a726dcf674bcd1cbd1fc4f35b80167b1c090ea94f6bc60c70f4e615eab" + ], + "index": "pypi", + "version": "==0.1.1" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "index": "pypi", + "version": "==3.0.4" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "version": "==1.15.0" + } + }, "develop": { "appdirs": { "hashes": [ @@ -51,8 +75,16 @@ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" ], + "index": "pypi", "version": "==3.0.4" }, + "colorama": { + "hashes": [ + "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", + "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" + ], + "version": "==0.4.3" + }, "distlib": { "hashes": [ "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb", @@ -81,21 +113,12 @@ ], "version": "==2.10" }, - "importlib-metadata": { + "keyring": { "hashes": [ - "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", - "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070" + "sha256:22df6abfed49912fc560806030051067fba9f0069cffa79da72899aeea4ccbd5", + "sha256:e7a17caf40c40b6bb8c4772224a487e4a63013560ed0c521065aeba7ecd42182" ], - "markers": "python_version < '3.8'", - "version": "==1.7.0" - }, - "importlib-resources": { - "hashes": [ - "sha256:19f745a6eca188b490b1428c8d1d4a0d2368759f32370ea8fb89cad2ab1106c3", - "sha256:d028f66b66c0d5732dae86ba4276999855e162a749c92620a38c1d779ed138a7" - ], - "markers": "python_version < '3.7'", - "version": "==3.0.0" + "version": "==21.3.0" }, "mako": { "hashes": [ @@ -219,6 +242,13 @@ ], "version": "==0.9.1" }, + "rfc3986": { + "hashes": [ + "sha256:112398da31a3344dc25dbf477d8df6cb34f9278a94fee2625d89e4514be8bb9d", + "sha256:af9147e9aceda37c91a05f4deb128d4b4b49d6b199775fd2d2927768abdc8f50" + ], + "version": "==1.4.0" + }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", @@ -250,11 +280,11 @@ }, "twine": { "hashes": [ - "sha256:630fadd6e342e725930be6c696537e3f9ccc54331742b16245dab292a17d0460", - "sha256:a3d22aab467b4682a22de4a422632e79d07eebd07ff2a7079effb13f8a693787" + "sha256:34352fd52ec3b9d29837e6072d5a2a7c6fe4290e97bba46bb8d478b5c598f7ab", + "sha256:ba9ff477b8d6de0c89dd450e70b2185da190514e91c42cc62f96850025c10472" ], "index": "pypi", - "version": "==1.15.0" + "version": "==3.2.0" }, "urllib3": { "hashes": [ @@ -279,19 +309,11 @@ }, "wheel": { "hashes": [ - "sha256:8788e9155fe14f54164c1b9eb0a319d98ef02c160725587ad60f14ddc57b6f96", - "sha256:df277cb51e61359aba502208d680f90c0493adec6f0e848af94948778aed386e" + "sha256:625e645aae0706ad09690bded523196a065fbcf9afcdb2d713b59e01ef8699c0", + "sha256:64a0d73747636637479b8b8741f9304bee7a568c80e4029eeb9529ef134b471d" ], "index": "pypi", - "version": "==0.34.2" - }, - "zipp": { - "hashes": [ - "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1", - "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921" - ], - "markers": "python_version < '3.8'", - "version": "==1.2.0" + "version": "==0.35.0" } } } diff --git a/README.md b/README.md index 896bcf0..5129a68 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Local development is done using [pyenv](https://github.com/pyenv/pyenv) and ### Generating docs 1. Run `pipenv install -d` to install normal and dev dependencies +1. Run `rm -rf docs/` to be able to completely overwrite existing docs 1. Run `pipenv run pdoc3 --html -o docs/ gedcom --force` to generate docs into the `docs/` directory > To develop docs run `pipenv run pdoc3 --http localhost:8000 gedcom` @@ -68,6 +69,27 @@ the `repository-url` is `https://upload.pypi.org/legacy/`. > > `pipenv run twine upload --repository-url https://upload.pypi.org/legacy/ dist/*` +## Contribution + +1. Clone the repo +1. Make your changes +1. (Write appropriate tests within `tests/`) +1. Commit using [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) +1. [Open a pull request](https://github.com/madprime/python-gedcom/compare) +1. When checks for the PR fail consider making changes so that the checks pass + +### Git: Conventional Commits + +Git committing is done using [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) with NPM. + +Consider installing node packages with [NVM](https://github.com/nvm-sh/nvm) and start committing with `npm run commit`. +Git hooks installed via [Husky](https://github.com/typicode/husky) will do the rest. + +How to install: + +1. Use Node version `12.16.1` (or use [NVM](https://github.com/nvm-sh/nvm) and run `nvm use`) +1. Run `npm install` and then `npm run commit` to commit your changes + ## Version bumping (releasing) All of the following will generate a `..-dev` version: @@ -105,13 +127,17 @@ 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) 2018 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) diff --git a/docs/gedcom/detect.html b/docs/gedcom/detect.html new file mode 100644 index 0000000..8c7dc42 --- /dev/null +++ b/docs/gedcom/detect.html @@ -0,0 +1,283 @@ + + + + + + +gedcom.detect API documentation + + + + + + + + + +
+
+
+

Module gedcom.detect

+
+
+

Module containing functions for detecting GEDCOM file encoding and version.

+
+ +Expand source code + +
# -*- coding: utf-8 -*-
+
+#  Copyright (C) 2020
+#
+#  This file is part of the Python GEDCOM Parser.
+#
+#  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.
+#
+#  For more, have a look at the GitHub repository at:
+#  https://github.com/nickreynke/python-gedcom
+
+"""
+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
+
+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.
+    """
+    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: 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)
+
+    # 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: 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
+    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)
+
+    probed_version = gedcom_version
+
+    # UTF was added in the 5.5.1 specification
+    if gedcom_version == '5.5' and 'utf' in codec:
+        probed_version = gedcom_version
+
+    return probed_version, gedcom_version, gedcom_format
+
+
+
+
+
+
+
+

Functions

+
+
+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_TAG_CHARACTER tag.

+

Returns: codec

+
+ +Expand source code + +
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)
+
+    # 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: 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

+
+ +Expand source code + +
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
+    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)
+
+    probed_version = gedcom_version
+
+    # UTF was added in the 5.5.1 specification
+    if gedcom_version == '5.5' and 'utf' in codec:
+        probed_version = gedcom_version
+
+    return probed_version, gedcom_version, gedcom_format
+
+
+
+
+
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/docs/gedcom/element/family.html b/docs/gedcom/element/family.html deleted file mode 100644 index 0c2b782..0000000 --- a/docs/gedcom/element/family.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - -gedcom.element.family API documentation - - - - - - - - - - - -
-
-
-

Module gedcom.element.family

-
-
-

GEDCOM element consisting of tag GEDCOM_TAG_FAMILY

-
- -Expand source code - -
# -*- coding: utf-8 -*-
-
-# Python GEDCOM Parser
-#
-# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_FAMILY`"""
-
-from gedcom.element.element import Element
-import gedcom.tags
-
-
-class NotAnActualFamilyError(Exception):
-    pass
-
-
-class FamilyElement(Element):
-
-    def get_tag(self):
-        return gedcom.tags.GEDCOM_TAG_FAMILY
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class FamilyElement -(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

-
- -Expand source code - -
class FamilyElement(Element):
-
-    def get_tag(self):
-        return gedcom.tags.GEDCOM_TAG_FAMILY
-
-

Ancestors

- -

Inherited members

- -
-
-class NotAnActualFamilyError -(...) -
-
-

Common base class for all non-exit exceptions.

-
- -Expand source code - -
class NotAnActualFamilyError(Exception):
-    pass
-
-

Ancestors

-
    -
  • builtins.Exception
  • -
  • builtins.BaseException
  • -
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/gedcom/element/file.html b/docs/gedcom/element/file.html deleted file mode 100644 index 53c99ff..0000000 --- a/docs/gedcom/element/file.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - -gedcom.element.file API documentation - - - - - - - - - - - -
-
-
-

Module gedcom.element.file

-
-
-

GEDCOM element consisting of tag GEDCOM_TAG_FILE

-
- -Expand source code - -
# -*- coding: utf-8 -*-
-
-# Python GEDCOM Parser
-#
-# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_FILE`"""
-
-from gedcom.element.element import Element
-import gedcom.tags
-
-
-class NotAnActualFileError(Exception):
-    pass
-
-
-class FileElement(Element):
-
-    def get_tag(self):
-        return gedcom.tags.GEDCOM_TAG_FILE
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class FileElement -(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

-
- -Expand source code - -
class FileElement(Element):
-
-    def get_tag(self):
-        return gedcom.tags.GEDCOM_TAG_FILE
-
-

Ancestors

- -

Inherited members

- -
-
-class NotAnActualFileError -(...) -
-
-

Common base class for all non-exit exceptions.

-
- -Expand source code - -
class NotAnActualFileError(Exception):
-    pass
-
-

Ancestors

-
    -
  • builtins.Exception
  • -
  • builtins.BaseException
  • -
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/gedcom/element/individual.html b/docs/gedcom/element/individual.html deleted file mode 100644 index e4db236..0000000 --- a/docs/gedcom/element/individual.html +++ /dev/null @@ -1,1741 +0,0 @@ - - - - - - -gedcom.element.individual API documentation - - - - - - - - - - - -
-
-
-

Module gedcom.element.individual

-
-
-

GEDCOM element consisting of tag GEDCOM_TAG_INDIVIDUAL

-
- -Expand source code - -
# -*- coding: utf-8 -*-
-
-# Python GEDCOM Parser
-#
-# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_INDIVIDUAL`"""
-
-import re as regex
-from gedcom.element.element import Element
-from gedcom.helpers import deprecated
-import gedcom.tags
-
-
-class NotAnActualIndividualError(Exception):
-    pass
-
-
-class IndividualElement(Element):
-
-    def get_tag(self):
-        return gedcom.tags.GEDCOM_TAG_INDIVIDUAL
-
-    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:
-                return True
-
-        return False
-
-    def is_child(self):
-        """Checks if this element is a child of a family
-        :rtype: bool
-        """
-        found_child = False
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
-                found_child = True
-
-        return found_child
-
-    def is_private(self):
-        """Checks if this individual is marked private
-        :rtype: bool
-        """
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
-                private = child.get_value()
-                if private == 'Y':
-                    return True
-
-        return False
-
-    def get_name(self):
-        """Returns an individual's names as a tuple: (`str` given_name, `str` surname)
-        :rtype: tuple
-        """
-        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.
-        found_given_name = False
-        found_surname_name = False
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.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() != "":
-                    name = child.get_value().split('/')
-
-                    if len(name) > 0:
-                        given_name = name[0].strip()
-                        if len(name) > 1:
-                            surname = name[1].strip()
-
-                    return given_name, surname
-
-                for childOfChild in child.get_child_elements():
-
-                    if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
-                        given_name = childOfChild.get_value()
-                        found_given_name = True
-
-                    if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
-                        surname = childOfChild.get_value()
-                        found_surname_name = True
-
-                if found_given_name and found_surname_name:
-                    return given_name, surname
-
-        # If we reach here we are probably returning empty strings
-        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]
-
-    def surname_match(self, surname_to_match):
-        """Matches a string with the surname of an individual
-        :type surname_to_match: str
-        :rtype: bool
-        """
-        (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
-        ::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
-        """
-        (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
-        """
-        gender = ""
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.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)
-        :rtype: tuple
-        """
-        date = ""
-        place = ""
-        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 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())
-
-        return date, place, sources
-
-    def get_birth_year(self):
-        """Returns the birth year of a person in integer format
-        :rtype: int
-        """
-        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()
-                        date = date_split[len(date_split) - 1]
-
-        if date == "":
-            return -1
-        try:
-            return int(date)
-        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
-        """
-        date = ""
-        place = ""
-        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())
-
-        return date, place, sources
-
-    def get_death_year(self):
-        """Returns the death year of a person in integer format
-        :rtype: int
-        """
-        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()
-                        date = date_split[len(date_split) - 1]
-
-        if date == "":
-            return -1
-        try:
-            return int(date)
-        except ValueError:
-            return -1
-
-    @deprecated
-    def get_burial(self):
-        """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
-        """
-        date = ""
-        place = ""
-        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 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())
-
-        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)
-        ::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
-        """
-        census = []
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
-
-                date = ''
-                place = ''
-                sources = []
-
-                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())
-
-                census.append((date, place, sources))
-
-        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
-        """
-        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()
-
-        return date
-
-    def get_occupation(self):
-        """Returns the occupation of a person
-        :rtype: str
-        """
-        occupation = ""
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
-                occupation = child.get_value()
-
-        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
-        """
-        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
-        """
-        birth_year = self.get_birth_year()
-
-        if from_year <= birth_year <= to_year:
-            return True
-
-        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
-        """
-        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
-        """
-        death_year = self.get_death_year()
-
-        if from_year <= death_year <= to_year:
-            return True
-
-        return False
-
-    def criteria_match(self, 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]
-             Match a person with [name] in any part of the `surname`.
-        given_name=[given_name]
-             Match a person with [given_name] in any part of the given `given_name`.
-        birth=[year]
-             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
-        """
-
-        # Check if criteria is a valid criteria and can be split by `:` and `=` characters
-        try:
-            for criterion in criteria.split(':'):
-                criterion.split('=')
-        except ValueError:
-            return False
-
-        match = True
-
-        for criterion in criteria.split(':'):
-            key, value = criterion.split('=')
-
-            if key == "surname" and not self.surname_match(value):
-                match = False
-            elif key == "name" and not self.given_name_match(value):
-                match = False
-            elif key == "birth":
-
-                try:
-                    year = int(value)
-                    if not self.birth_year_match(year):
-                        match = False
-                except ValueError:
-                    match = False
-
-            elif key == "birth_range":
-
-                try:
-                    from_year, to_year = value.split('-')
-                    from_year = int(from_year)
-                    to_year = int(to_year)
-                    if not self.birth_range_match(from_year, to_year):
-                        match = False
-                except ValueError:
-                    match = False
-
-            elif key == "death":
-
-                try:
-                    year = int(value)
-                    if not self.death_year_match(year):
-                        match = False
-                except ValueError:
-                    match = False
-
-            elif key == "death_range":
-
-                try:
-                    from_year, to_year = value.split('-')
-                    from_year = int(from_year)
-                    to_year = int(to_year)
-                    if not self.death_range_match(from_year, to_year):
-                        match = False
-                except ValueError:
-                    match = False
-
-        return match
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class IndividualElement -(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

-
- -Expand source code - -
class IndividualElement(Element):
-
-    def get_tag(self):
-        return gedcom.tags.GEDCOM_TAG_INDIVIDUAL
-
-    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:
-                return True
-
-        return False
-
-    def is_child(self):
-        """Checks if this element is a child of a family
-        :rtype: bool
-        """
-        found_child = False
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
-                found_child = True
-
-        return found_child
-
-    def is_private(self):
-        """Checks if this individual is marked private
-        :rtype: bool
-        """
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
-                private = child.get_value()
-                if private == 'Y':
-                    return True
-
-        return False
-
-    def get_name(self):
-        """Returns an individual's names as a tuple: (`str` given_name, `str` surname)
-        :rtype: tuple
-        """
-        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.
-        found_given_name = False
-        found_surname_name = False
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.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() != "":
-                    name = child.get_value().split('/')
-
-                    if len(name) > 0:
-                        given_name = name[0].strip()
-                        if len(name) > 1:
-                            surname = name[1].strip()
-
-                    return given_name, surname
-
-                for childOfChild in child.get_child_elements():
-
-                    if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
-                        given_name = childOfChild.get_value()
-                        found_given_name = True
-
-                    if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
-                        surname = childOfChild.get_value()
-                        found_surname_name = True
-
-                if found_given_name and found_surname_name:
-                    return given_name, surname
-
-        # If we reach here we are probably returning empty strings
-        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]
-
-    def surname_match(self, surname_to_match):
-        """Matches a string with the surname of an individual
-        :type surname_to_match: str
-        :rtype: bool
-        """
-        (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
-        ::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
-        """
-        (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
-        """
-        gender = ""
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.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)
-        :rtype: tuple
-        """
-        date = ""
-        place = ""
-        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 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())
-
-        return date, place, sources
-
-    def get_birth_year(self):
-        """Returns the birth year of a person in integer format
-        :rtype: int
-        """
-        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()
-                        date = date_split[len(date_split) - 1]
-
-        if date == "":
-            return -1
-        try:
-            return int(date)
-        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
-        """
-        date = ""
-        place = ""
-        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())
-
-        return date, place, sources
-
-    def get_death_year(self):
-        """Returns the death year of a person in integer format
-        :rtype: int
-        """
-        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()
-                        date = date_split[len(date_split) - 1]
-
-        if date == "":
-            return -1
-        try:
-            return int(date)
-        except ValueError:
-            return -1
-
-    @deprecated
-    def get_burial(self):
-        """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
-        """
-        date = ""
-        place = ""
-        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 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())
-
-        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)
-        ::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
-        """
-        census = []
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
-
-                date = ''
-                place = ''
-                sources = []
-
-                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())
-
-                census.append((date, place, sources))
-
-        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
-        """
-        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()
-
-        return date
-
-    def get_occupation(self):
-        """Returns the occupation of a person
-        :rtype: str
-        """
-        occupation = ""
-
-        for child in self.get_child_elements():
-            if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
-                occupation = child.get_value()
-
-        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
-        """
-        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
-        """
-        birth_year = self.get_birth_year()
-
-        if from_year <= birth_year <= to_year:
-            return True
-
-        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
-        """
-        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
-        """
-        death_year = self.get_death_year()
-
-        if from_year <= death_year <= to_year:
-            return True
-
-        return False
-
-    def criteria_match(self, 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]
-             Match a person with [name] in any part of the `surname`.
-        given_name=[given_name]
-             Match a person with [given_name] in any part of the given `given_name`.
-        birth=[year]
-             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
-        """
-
-        # Check if criteria is a valid criteria and can be split by `:` and `=` characters
-        try:
-            for criterion in criteria.split(':'):
-                criterion.split('=')
-        except ValueError:
-            return False
-
-        match = True
-
-        for criterion in criteria.split(':'):
-            key, value = criterion.split('=')
-
-            if key == "surname" and not self.surname_match(value):
-                match = False
-            elif key == "name" and not self.given_name_match(value):
-                match = False
-            elif key == "birth":
-
-                try:
-                    year = int(value)
-                    if not self.birth_year_match(year):
-                        match = False
-                except ValueError:
-                    match = False
-
-            elif key == "birth_range":
-
-                try:
-                    from_year, to_year = value.split('-')
-                    from_year = int(from_year)
-                    to_year = int(to_year)
-                    if not self.birth_range_match(from_year, to_year):
-                        match = False
-                except ValueError:
-                    match = False
-
-            elif key == "death":
-
-                try:
-                    year = int(value)
-                    if not self.death_year_match(year):
-                        match = False
-                except ValueError:
-                    match = False
-
-            elif key == "death_range":
-
-                try:
-                    from_year, to_year = value.split('-')
-                    from_year = int(from_year)
-                    to_year = int(to_year)
-                    if not self.death_range_match(from_year, to_year):
-                        match = False
-                except ValueError:
-                    match = False
-
-        return match
-
-

Ancestors

- -

Methods

-
-
-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

-
- -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
-    """
-    birth_year = self.get_birth_year()
-
-    if from_year <= birth_year <= to_year:
-        return True
-
-    return False
-
-
-
-def birth_year_match(self, year) -
-
-

Returns True if the given year matches the birth year of this person -:type year: int -:rtype: bool

-
- -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
-    """
-    return self.get_birth_year() == year
-
-
-
-def criteria_match(self, 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] -Match a person with [name] in any part of the surname. -given_name=[given_name] -Match a person with [given_name] in any part of the given given_name. -birth=[year] -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

-
- -Expand source code - -
def criteria_match(self, 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]
-         Match a person with [name] in any part of the `surname`.
-    given_name=[given_name]
-         Match a person with [given_name] in any part of the given `given_name`.
-    birth=[year]
-         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
-    """
-
-    # Check if criteria is a valid criteria and can be split by `:` and `=` characters
-    try:
-        for criterion in criteria.split(':'):
-            criterion.split('=')
-    except ValueError:
-        return False
-
-    match = True
-
-    for criterion in criteria.split(':'):
-        key, value = criterion.split('=')
-
-        if key == "surname" and not self.surname_match(value):
-            match = False
-        elif key == "name" and not self.given_name_match(value):
-            match = False
-        elif key == "birth":
-
-            try:
-                year = int(value)
-                if not self.birth_year_match(year):
-                    match = False
-            except ValueError:
-                match = False
-
-        elif key == "birth_range":
-
-            try:
-                from_year, to_year = value.split('-')
-                from_year = int(from_year)
-                to_year = int(to_year)
-                if not self.birth_range_match(from_year, to_year):
-                    match = False
-            except ValueError:
-                match = False
-
-        elif key == "death":
-
-            try:
-                year = int(value)
-                if not self.death_year_match(year):
-                    match = False
-            except ValueError:
-                match = False
-
-        elif key == "death_range":
-
-            try:
-                from_year, to_year = value.split('-')
-                from_year = int(from_year)
-                to_year = int(to_year)
-                if not self.death_range_match(from_year, to_year):
-                    match = False
-            except ValueError:
-                match = False
-
-    return match
-
-
-
-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

-
- -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
-    """
-    death_year = self.get_death_year()
-
-    if from_year <= death_year <= to_year:
-        return True
-
-    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

-
- -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
-    """
-    return self.get_death_year() == year
-
-
-
-def get_all_names(self) -
-
-
-
- -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]
-
-
-
-def get_birth_data(self) -
-
-

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)
-    :rtype: tuple
-    """
-    date = ""
-    place = ""
-    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 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())
-
-    return date, place, sources
-
-
-
-def get_birth_year(self) -
-
-

Returns the birth year of a person in integer format -:rtype: int

-
- -Expand source code - -
def get_birth_year(self):
-    """Returns the birth year of a person in integer format
-    :rtype: int
-    """
-    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()
-                    date = date_split[len(date_split) - 1]
-
-    if date == "":
-        return -1
-    try:
-        return int(date)
-    except ValueError:
-        return -1
-
-
-
-def get_burial(self) -
-
-

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 - -
@deprecated
-def get_burial(self):
-    """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

-
- -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
-    """
-    date = ""
-    place = ""
-    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 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())
-
-    return date, place, sources
-
-
-
-def get_census(self) -
-
-

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 - -
@deprecated
-def get_census(self):
-    """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

-
- -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
-    """
-    census = []
-
-    for child in self.get_child_elements():
-        if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS:
-
-            date = ''
-            place = ''
-            sources = []
-
-            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())
-
-            census.append((date, place, sources))
-
-    return census
-
-
-
-def get_death_data(self) -
-
-

Returns the death data of a person formatted as a tuple: (str date, str place, list sources) -:rtype: tuple

-
- -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
-    """
-    date = ""
-    place = ""
-    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())
-
-    return date, place, sources
-
-
-
-def get_death_year(self) -
-
-

Returns the death year of a person in integer format -:rtype: int

-
- -Expand source code - -
def get_death_year(self):
-    """Returns the death year of a person in integer format
-    :rtype: int
-    """
-    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()
-                    date = date_split[len(date_split) - 1]
-
-    if date == "":
-        return -1
-    try:
-        return int(date)
-    except ValueError:
-        return -1
-
-
-
-def get_gender(self) -
-
-

Returns the gender of a person in string format -:rtype: str

-
- -Expand source code - -
def get_gender(self):
-    """Returns the gender of a person in string format
-    :rtype: str
-    """
-    gender = ""
-
-    for child in self.get_child_elements():
-        if child.get_tag() == gedcom.tags.GEDCOM_TAG_SEX:
-            gender = child.get_value()
-
-    return gender
-
-
-
-def get_last_change_date(self) -
-
-

Returns the date of when the person data was last changed formatted as a string -:rtype: str

-
- -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
-    """
-    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()
-
-    return date
-
-
-
-def get_name(self) -
-
-

Returns an individual's names as a tuple: (str given_name, str surname) -:rtype: tuple

-
- -Expand source code - -
def get_name(self):
-    """Returns an individual's names as a tuple: (`str` given_name, `str` surname)
-    :rtype: tuple
-    """
-    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.
-    found_given_name = False
-    found_surname_name = False
-
-    for child in self.get_child_elements():
-        if child.get_tag() == gedcom.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() != "":
-                name = child.get_value().split('/')
-
-                if len(name) > 0:
-                    given_name = name[0].strip()
-                    if len(name) > 1:
-                        surname = name[1].strip()
-
-                return given_name, surname
-
-            for childOfChild in child.get_child_elements():
-
-                if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME:
-                    given_name = childOfChild.get_value()
-                    found_given_name = True
-
-                if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME:
-                    surname = childOfChild.get_value()
-                    found_surname_name = True
-
-            if found_given_name and found_surname_name:
-                return given_name, surname
-
-    # If we reach here we are probably returning empty strings
-    return given_name, surname
-
-
-
-def get_occupation(self) -
-
-

Returns the occupation of a person -:rtype: str

-
- -Expand source code - -
def get_occupation(self):
-    """Returns the occupation of a person
-    :rtype: str
-    """
-    occupation = ""
-
-    for child in self.get_child_elements():
-        if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION:
-            occupation = child.get_value()
-
-    return occupation
-
-
-
-def given_match(self, name) -
-
-

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

-
- -Expand source code - -
@deprecated
-def given_match(self, name):
-    """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

-
- -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
-    """
-    (given_name, surname) = self.get_name()
-    return regex.search(given_name_to_match, given_name, regex.IGNORECASE)
-
-
-
-def is_child(self) -
-
-

Checks if this element is a child of a family -:rtype: bool

-
- -Expand source code - -
def is_child(self):
-    """Checks if this element is a child of a family
-    :rtype: bool
-    """
-    found_child = False
-
-    for child in self.get_child_elements():
-        if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD:
-            found_child = True
-
-    return found_child
-
-
-
-def is_deceased(self) -
-
-

Checks if this individual is deceased -:rtype: bool

-
- -Expand source code - -
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:
-            return True
-
-    return False
-
-
-
-def is_private(self) -
-
-

Checks if this individual is marked private -:rtype: bool

-
- -Expand source code - -
def is_private(self):
-    """Checks if this individual is marked private
-    :rtype: bool
-    """
-    for child in self.get_child_elements():
-        if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE:
-            private = child.get_value()
-            if private == 'Y':
-                return True
-
-    return False
-
-
-
-def surname_match(self, surname_to_match) -
-
-

Matches a string with the surname of an individual -:type surname_to_match: str -:rtype: bool

-
- -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
-    """
-    (given_name, surname) = self.get_name()
-    return regex.search(surname_to_match, surname, regex.IGNORECASE)
-
-
-
-

Inherited members

- -
-
-class NotAnActualIndividualError -(...) -
-
-

Common base class for all non-exit exceptions.

-
- -Expand source code - -
class NotAnActualIndividualError(Exception):
-    pass
-
-

Ancestors

-
    -
  • builtins.Exception
  • -
  • builtins.BaseException
  • -
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/gedcom/element/object.html b/docs/gedcom/element/object.html deleted file mode 100644 index adc6c3f..0000000 --- a/docs/gedcom/element/object.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - -gedcom.element.object API documentation - - - - - - - - - - - -
-
-
-

Module gedcom.element.object

-
-
-

GEDCOM element consisting of tag GEDCOM_TAG_OBJECT

-
- -Expand source code - -
# -*- coding: utf-8 -*-
-
-# Python GEDCOM Parser
-#
-# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_OBJECT`"""
-
-from gedcom.element.element import Element
-import gedcom.tags
-
-
-class NotAnActualObjectError(Exception):
-    pass
-
-
-class ObjectElement(Element):
-
-    def is_object(self):
-        """Checks if this element is an actual object
-        :rtype: bool
-        """
-        return self.get_tag() == gedcom.tags.GEDCOM_TAG_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

-
- -Expand source code - -
class ObjectElement(Element):
-
-    def is_object(self):
-        """Checks if this element is an actual object
-        :rtype: bool
-        """
-        return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT
-
-

Ancestors

- -

Methods

-
-
-def is_object(self) -
-
-

Checks if this element is an actual object -:rtype: bool

-
- -Expand source code - -
def is_object(self):
-    """Checks if this element is an actual object
-    :rtype: bool
-    """
-    return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/gedcom/element/element.html b/docs/gedcom/elements/element.html similarity index 59% rename from docs/gedcom/element/element.html rename to docs/gedcom/elements/element.html index df41322..be0a511 100644 --- a/docs/gedcom/element/element.html +++ b/docs/gedcom/elements/element.html @@ -4,8 +4,8 @@ -gedcom.element.element API documentation - +gedcom.elements.element API documentation + @@ -19,54 +19,42 @@
-

Module gedcom.element.element

+

Module gedcom.elements.element

-

Base GEDCOM element

+

Base GEDCOM element.

Expand source code
# -*- coding: utf-8 -*-
 
-# Python GEDCOM Parser
+#  Copyright (C) 2020
 #
-# 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 file is part of the Python GEDCOM Parser.
 #
-# 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.
+#  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.
 #
-# 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
+#  For more, have a look at the GitHub repository at:
+#  https://github.com/nickreynke/python-gedcom
 
 """
-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]`
 
@@ -91,7 +79,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 @@ -106,39 +95,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 @@ -152,17 +135,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() @@ -175,40 +155,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: @@ -220,79 +196,91 @@

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.file import FileElement - from gedcom.element.individual import IndividualElement - from gedcom.element.object import ObjectElement + from gedcom.elements.family import FamilyElement + from gedcom.elements.individual import IndividualElement + from gedcom.elements.note import NoteElement + from gedcom.elements.object import ObjectElement + from gedcom.elements.repository import RepositoryElement + from gedcom.elements.source import SourceElement + from gedcom.elements.submitter import SubmitterElement + from gedcom.elements.submission import SubmissionElement + from gedcom.elements.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) + 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) 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) + 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) + 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()) @@ -316,7 +304,7 @@

Module gedcom.element.element

return result - def __str__(self): + def __str__(self) -> str: """:rtype: str""" if version_info[0] >= 3: return self.to_gedcom_string() @@ -333,13 +321,13 @@

Module gedcom.element.element

Classes

-
+
class Element -(level, pointer, tag, value, crlf='\n', multi_line=True) +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True)
-

GEDCOM element

-

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. @@ -364,9 +352,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]`
 
@@ -391,7 +379,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 @@ -406,39 +395,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 @@ -452,17 +435,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() @@ -475,40 +455,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: @@ -520,79 +496,91 @@

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.file import FileElement - from gedcom.element.individual import IndividualElement - from gedcom.element.object import ObjectElement + from gedcom.elements.family import FamilyElement + from gedcom.elements.individual import IndividualElement + from gedcom.elements.note import NoteElement + from gedcom.elements.object import ObjectElement + from gedcom.elements.repository import RepositoryElement + from gedcom.elements.source import SourceElement + from gedcom.elements.submitter import SubmitterElement + from gedcom.elements.submission import SubmissionElement + from gedcom.elements.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) + 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) 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) + 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) + 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()) @@ -616,7 +604,7 @@

Classes

return result - def __str__(self): + def __str__(self) -> str: """:rtype: str""" if version_info[0] >= 3: return self.to_gedcom_string() @@ -625,28 +613,30 @@

Classes

Subclasses

Methods

-
-def add_child_element(self, element) +
+def add_child_element(self, element: Element)
-

Adds a child element to this element

-

:type element: Element

+

Adds a child element to this element.

Expand source code -
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)
@@ -654,73 +644,65 @@ 

Methods

return element
-
-def get_child_elements(self) +
+def get_child_elements(self) ‑> List[Element]
-

Returns the direct child elements of this element -:rtype: list of Element

+

Returns the direct child elements of this element.

Expand source code -
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 get_individual(self) +
+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

+

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
-
-def get_multi_line_value(self) +
+def get_multi_line_value(self) ‑> str
-

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
@@ -735,134 +717,145 @@ 

Methods

return result
-
-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
-
-def get_pointer(self) +
+def get_pointer(self) ‑> str
-

Returns the pointer of this element from within the GEDCOM file -:rtype: str

+

Returns the pointer of this element from within the GEDCOM file.

Expand source code -
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) +
+def get_tag(self) ‑> str
-

Returns the tag of this element from within the GEDCOM file -:rtype: str

+

Returns the tag of this element from within the GEDCOM file.

Expand source code -
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) +
+def get_value(self) ‑> str
-

Return the value of this element from within the GEDCOM file -:rtype: str

+

Return the value of this element from within the GEDCOM file.

Expand source code -
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 new_child_element(self, tag, pointer='', value='') +
+def new_child_element(self, tag: str, pointer: str = '', value: str = '') ‑> Element
-

Creates and returns a new child element of this element

-

:type tag: str -:type pointer: str -:type value: str -:rtype: Element

+

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.file import FileElement
-    from gedcom.element.individual import IndividualElement
-    from gedcom.element.object import ObjectElement
+    from gedcom.elements.family import FamilyElement
+    from gedcom.elements.individual import IndividualElement
+    from gedcom.elements.note import NoteElement
+    from gedcom.elements.object import ObjectElement
+    from gedcom.elements.repository import RepositoryElement
+    from gedcom.elements.source import SourceElement
+    from gedcom.elements.submitter import SubmitterElement
+    from gedcom.elements.submission import SubmissionElement
+    from gedcom.elements.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)
+        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)
     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)
+    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)
+        child_element = Element(self.get_level() + 1, pointer, tag,
+                                value, self.__crlf)
 
     self.add_child_element(child_element)
 
     return child_element
-
-def set_multi_line_value(self, value) +
+def set_multi_line_value(self, value: str)
-

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:
@@ -875,61 +868,52 @@ 

Methods

self.__add_concatenation(line[n:])
-
-def set_parent_element(self, element) +
+def set_parent_element(self, element: Element)
-

Adds a parent element to this 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

+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
-
-def set_value(self, value) +
+def set_value(self, value: str)
-

Sets the value of this element -:type value: str

+

Sets the value of this element.

Expand source code -
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 to_gedcom_string(self, recursive=False) +
+def to_gedcom_string(self, recursive: bool = False) ‑> str
-

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())
@@ -967,28 +951,28 @@ 

Index

  • Super-module

  • Classes

    diff --git a/docs/gedcom/elements/family.html b/docs/gedcom/elements/family.html new file mode 100644 index 0000000..02492e6 --- /dev/null +++ b/docs/gedcom/elements/family.html @@ -0,0 +1,387 @@ + + + + + + +gedcom.elements.family API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.family

    +
    +
    +

    GEDCOM element for a FAM_RECORD family record identified by the +GEDCOM_TAG_FAMILY tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `FAM_RECORD` family record identified by the
    +`gedcom.tags.GEDCOM_TAG_FAMILY` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.element import Element
    +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) -> str:
    +        return tags.GEDCOM_TAG_FAMILY
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class FamilyElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a FAM_RECORD

    +
    + +Expand source code + +
    class FamilyElement(Element):
    +    """Element associated with a `FAM_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_FAMILY
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/header.html b/docs/gedcom/elements/header.html new file mode 100644 index 0000000..720c74a --- /dev/null +++ b/docs/gedcom/elements/header.html @@ -0,0 +1,483 @@ + + + + + + +gedcom.elements.header API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.header

    +
    +
    +

    GEDCOM element for a HEADER header record identified by the +GEDCOM_TAG_HEADER tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `HEADER` header record identified by the
    +`gedcom.tags.GEDCOM_TAG_HEADER` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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) -> str:
    +        return tags.GEDCOM_TAG_HEADER
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class HeaderElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a HEADER

    +
    + +Expand source code + +
    class HeaderElement(Element):
    +    """Element associated with a `HEADER`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_HEADER
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/index.html b/docs/gedcom/elements/index.html new file mode 100644 index 0000000..cd25238 --- /dev/null +++ b/docs/gedcom/elements/index.html @@ -0,0 +1,163 @@ + + + + + + +gedcom.elements API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements

    +
    +
    +

    Module containing all relevant elements generated by a Parser. +An element represents a line within GEDCOM data.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +Module containing all relevant elements generated by a `gedcom.parser.Parser`.
    +An element represents a line within GEDCOM data.
    +"""
    +
    +__all__ = [
    +    "element",
    +    "family",
    +    "header",
    +    "individual",
    +    "note",
    +    "object",
    +    "repository",
    +    "root",
    +    "source",
    +    "submission",
    +    "submitter"
    +]
    +
    +
    +
    +

    Sub-modules

    +
    +
    gedcom.elements.element
    +
    +

    Base GEDCOM element.

    +
    +
    gedcom.elements.family
    +
    +

    GEDCOM element for a FAM_RECORD family record identified by the +GEDCOM_TAG_FAMILY tag.

    +
    +
    gedcom.elements.header
    +
    +

    GEDCOM element for a HEADER header record identified by the +GEDCOM_TAG_HEADER tag.

    +
    +
    gedcom.elements.individual
    +
    +

    GEDCOM element for a INDIVIDUAL_RECORD individual record identified by the +GEDCOM_TAG_INDIVIDUAL tag.

    +
    +
    gedcom.elements.note
    +
    +

    GEDCOM element for a NOTE_RECORD note record identified by the +GEDCOM_TAG_NOTE tag.

    +
    +
    gedcom.elements.object
    +
    +

    GEDCOM element for a MULTIMEDIA_RECORD media record identified by the +GEDCOM_TAG_OBJECT tag.

    +
    +
    gedcom.elements.repository
    +
    +

    GEDCOM element for a REPOSITORY_RECORD repository record identified by the +GEDCOM_TAG_REPOSITORY tag.

    +
    +
    gedcom.elements.root
    +
    +

    Virtual GEDCOM root element containing all logical records as children

    +
    +
    gedcom.elements.source
    +
    +

    GEDCOM element for a SOURCE_RECORD source record identified by the +GEDCOM_TAG_SOURCE tag.

    +
    +
    gedcom.elements.submission
    +
    +

    GEDCOM element for a SUBMISSION_RECORD submission record identified by the +GEDCOM_TAG_SUBMISSION tag.

    +
    +
    gedcom.elements.submitter
    +
    +

    GEDCOM element for a SUBMITTER_RECORD submitter record identified by the +GEDCOM_TAG_SUBMITTER tag.

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/individual.html b/docs/gedcom/elements/individual.html new file mode 100644 index 0000000..2155a5f --- /dev/null +++ b/docs/gedcom/elements/individual.html @@ -0,0 +1,1886 @@ + + + + + + +gedcom.elements.individual API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.individual

    +
    +
    +

    GEDCOM element for a INDIVIDUAL_RECORD individual record identified by the +GEDCOM_TAG_INDIVIDUAL tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `INDIVIDUAL_RECORD` individual record identified by the
    +`gedcom.tags.GEDCOM_TAG_INDIVIDUAL` tag.
    +"""
    +
    +from typing import Tuple, List
    +import re as regex
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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
    +
    +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) -> str:
    +        return tags.GEDCOM_TAG_INDIVIDUAL
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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) -> bool:
    +        """Checks if this individual is deceased.
    +        """
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_DEATH:
    +                return True
    +
    +        return False
    +
    +    def is_child(self) -> bool:
    +        """Checks if this element is a child of a family.
    +        """
    +        found_child = False
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
    +                found_child = True
    +
    +        return found_child
    +
    +    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:
    +                private = child.get_value()
    +                if private == 'Y':
    +                    return True
    +
    +        return False
    +
    +    def get_name(self) -> Tuple[str, str]:
    +        """Returns an individual's names as a tuple: (`str` given_name, `str` surname)
    +        """
    +        given_name = ""
    +        surname = ""
    +
    +        # 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() == 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() != "":
    +                    name = child.get_value().split('/')
    +
    +                    if len(name) > 0:
    +                        given_name = name[0].strip()
    +                        if len(name) > 1:
    +                            surname = name[1].strip()
    +
    +                    return given_name, surname
    +
    +                for gchild in child.get_child_elements():
    +
    +                    if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
    +                        given_name = gchild.get_value()
    +                        found_given_name = True
    +
    +                    if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
    +                        surname = gchild.get_value()
    +                        found_surname_name = True
    +
    +                if found_given_name and found_surname_name:
    +                    return given_name, surname
    +
    +        # If we reach here we are probably returning empty strings
    +        return given_name, surname
    +
    +    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: 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: 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
    +        """
    +        return self.given_name_match(name)
    +
    +    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) -> str:
    +        """Returns the gender of a person in string format.
    +        """
    +        gender = ""
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_SEX:
    +                gender = child.get_value()
    +
    +        return gender
    +
    +    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)
    +        """
    +        date = ""
    +        place = ""
    +        sources = []
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
    +                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
    +
    +    def get_birth_year(self) -> int:
    +        """Returns the birth year of a person in integer format.
    +        """
    +        date = ""
    +
    +        for child in self.get_child_elements():
    +            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 == "":
    +            return -1
    +        try:
    +            return int(date)
    +        except ValueError:
    +            return -1
    +
    +    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 = ""
    +        sources = []
    +
    +        for child in self.get_child_elements():
    +            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
    +
    +    def get_death_year(self) -> int:
    +        """Returns the death year of a person in integer format.
    +        """
    +        date = ""
    +
    +        for child in self.get_child_elements():
    +            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 == "":
    +            return -1
    +        try:
    +            return int(date)
    +        except ValueError:
    +            return -1
    +
    +    @deprecated
    +    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
    +        """
    +        self.get_burial_data()
    +
    +    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 = ""
    +        sources = []
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
    +                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
    +
    +    @deprecated
    +    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
    +        """
    +        self.get_census_data()
    +
    +    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 = []
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
    +
    +                date = ''
    +                place = ''
    +                sources = []
    +
    +                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())
    +
    +                census.append((date, place, sources))
    +
    +        return census
    +
    +    def get_last_change_date(self) -> str:
    +        """Returns the date of when the person data was last changed formatted as a string.
    +        """
    +        date = ""
    +
    +        for child in self.get_child_elements():
    +            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
    +
    +    def get_occupation(self) -> str:
    +        """Returns the occupation of a person.
    +        """
    +        occupation = ""
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
    +                occupation = child.get_value()
    +
    +        return occupation
    +
    +    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: int, to_year: int) -> bool:
    +        """Checks if the birth year of a person lies within the given range.
    +        """
    +        birth_year = self.get_birth_year()
    +
    +        if from_year <= birth_year <= to_year:
    +            return True
    +
    +        return False
    +
    +    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: int, to_year: int) -> bool:
    +        """Checks if the death year of a person lies within the given range.
    +        """
    +        death_year = self.get_death_year()
    +
    +        if from_year <= death_year <= to_year:
    +            return True
    +
    +        return False
    +
    +    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:
    +
    +        surname=[name]
    +             Match a person with [name] in any part of the `surname`.
    +        given_name=[given_name]
    +             Match a person with [given_name] in any part of the given `given_name`.
    +        birth=[year]
    +             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].
    +        """
    +
    +        # Check if criteria is a valid criteria and can be split by `:` and `=` characters
    +        try:
    +            for criterion in criteria.split(':'):
    +                criterion.split('=')
    +        except ValueError:
    +            return False
    +
    +        match = True
    +
    +        for criterion in criteria.split(':'):
    +            key, value = criterion.split('=')
    +
    +            if key == "surname" and not self.surname_match(value):
    +                match = False
    +            elif key == "name" and not self.given_name_match(value):
    +                match = False
    +            elif key == "birth":
    +
    +                try:
    +                    year = int(value)
    +                    if not self.birth_year_match(year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +            elif key == "birth_range":
    +
    +                try:
    +                    from_year, to_year = value.split('-')
    +                    from_year = int(from_year)
    +                    to_year = int(to_year)
    +                    if not self.birth_range_match(from_year, to_year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +            elif key == "death":
    +
    +                try:
    +                    year = int(value)
    +                    if not self.death_year_match(year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +            elif key == "death_range":
    +
    +                try:
    +                    from_year, to_year = value.split('-')
    +                    from_year = int(from_year)
    +                    to_year = int(to_year)
    +                    if not self.death_range_match(from_year, to_year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +        return match
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class IndividualElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with an INDIVIDUAL_RECORD

    +
    + +Expand source code + +
    class IndividualElement(Element):
    +    """Element associated with an `INDIVIDUAL_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_INDIVIDUAL
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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) -> bool:
    +        """Checks if this individual is deceased.
    +        """
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_DEATH:
    +                return True
    +
    +        return False
    +
    +    def is_child(self) -> bool:
    +        """Checks if this element is a child of a family.
    +        """
    +        found_child = False
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
    +                found_child = True
    +
    +        return found_child
    +
    +    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:
    +                private = child.get_value()
    +                if private == 'Y':
    +                    return True
    +
    +        return False
    +
    +    def get_name(self) -> Tuple[str, str]:
    +        """Returns an individual's names as a tuple: (`str` given_name, `str` surname)
    +        """
    +        given_name = ""
    +        surname = ""
    +
    +        # 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() == 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() != "":
    +                    name = child.get_value().split('/')
    +
    +                    if len(name) > 0:
    +                        given_name = name[0].strip()
    +                        if len(name) > 1:
    +                            surname = name[1].strip()
    +
    +                    return given_name, surname
    +
    +                for gchild in child.get_child_elements():
    +
    +                    if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
    +                        given_name = gchild.get_value()
    +                        found_given_name = True
    +
    +                    if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
    +                        surname = gchild.get_value()
    +                        found_surname_name = True
    +
    +                if found_given_name and found_surname_name:
    +                    return given_name, surname
    +
    +        # If we reach here we are probably returning empty strings
    +        return given_name, surname
    +
    +    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: 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: 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
    +        """
    +        return self.given_name_match(name)
    +
    +    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) -> str:
    +        """Returns the gender of a person in string format.
    +        """
    +        gender = ""
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_SEX:
    +                gender = child.get_value()
    +
    +        return gender
    +
    +    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)
    +        """
    +        date = ""
    +        place = ""
    +        sources = []
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
    +                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
    +
    +    def get_birth_year(self) -> int:
    +        """Returns the birth year of a person in integer format.
    +        """
    +        date = ""
    +
    +        for child in self.get_child_elements():
    +            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 == "":
    +            return -1
    +        try:
    +            return int(date)
    +        except ValueError:
    +            return -1
    +
    +    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 = ""
    +        sources = []
    +
    +        for child in self.get_child_elements():
    +            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
    +
    +    def get_death_year(self) -> int:
    +        """Returns the death year of a person in integer format.
    +        """
    +        date = ""
    +
    +        for child in self.get_child_elements():
    +            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 == "":
    +            return -1
    +        try:
    +            return int(date)
    +        except ValueError:
    +            return -1
    +
    +    @deprecated
    +    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
    +        """
    +        self.get_burial_data()
    +
    +    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 = ""
    +        sources = []
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
    +                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
    +
    +    @deprecated
    +    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
    +        """
    +        self.get_census_data()
    +
    +    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 = []
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
    +
    +                date = ''
    +                place = ''
    +                sources = []
    +
    +                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())
    +
    +                census.append((date, place, sources))
    +
    +        return census
    +
    +    def get_last_change_date(self) -> str:
    +        """Returns the date of when the person data was last changed formatted as a string.
    +        """
    +        date = ""
    +
    +        for child in self.get_child_elements():
    +            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
    +
    +    def get_occupation(self) -> str:
    +        """Returns the occupation of a person.
    +        """
    +        occupation = ""
    +
    +        for child in self.get_child_elements():
    +            if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
    +                occupation = child.get_value()
    +
    +        return occupation
    +
    +    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: int, to_year: int) -> bool:
    +        """Checks if the birth year of a person lies within the given range.
    +        """
    +        birth_year = self.get_birth_year()
    +
    +        if from_year <= birth_year <= to_year:
    +            return True
    +
    +        return False
    +
    +    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: int, to_year: int) -> bool:
    +        """Checks if the death year of a person lies within the given range.
    +        """
    +        death_year = self.get_death_year()
    +
    +        if from_year <= death_year <= to_year:
    +            return True
    +
    +        return False
    +
    +    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:
    +
    +        surname=[name]
    +             Match a person with [name] in any part of the `surname`.
    +        given_name=[given_name]
    +             Match a person with [given_name] in any part of the given `given_name`.
    +        birth=[year]
    +             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].
    +        """
    +
    +        # Check if criteria is a valid criteria and can be split by `:` and `=` characters
    +        try:
    +            for criterion in criteria.split(':'):
    +                criterion.split('=')
    +        except ValueError:
    +            return False
    +
    +        match = True
    +
    +        for criterion in criteria.split(':'):
    +            key, value = criterion.split('=')
    +
    +            if key == "surname" and not self.surname_match(value):
    +                match = False
    +            elif key == "name" and not self.given_name_match(value):
    +                match = False
    +            elif key == "birth":
    +
    +                try:
    +                    year = int(value)
    +                    if not self.birth_year_match(year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +            elif key == "birth_range":
    +
    +                try:
    +                    from_year, to_year = value.split('-')
    +                    from_year = int(from_year)
    +                    to_year = int(to_year)
    +                    if not self.birth_range_match(from_year, to_year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +            elif key == "death":
    +
    +                try:
    +                    year = int(value)
    +                    if not self.death_year_match(year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +            elif key == "death_range":
    +
    +                try:
    +                    from_year, to_year = value.split('-')
    +                    from_year = int(from_year)
    +                    to_year = int(to_year)
    +                    if not self.death_range_match(from_year, to_year):
    +                        match = False
    +                except ValueError:
    +                    match = False
    +
    +        return match
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +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.

    +
    + +Expand source code + +
    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()
    +
    +    if from_year <= birth_year <= to_year:
    +        return True
    +
    +    return False
    +
    +
    +
    +def birth_year_match(self, year: int) ‑> bool +
    +
    +

    Returns True if the given year matches the birth year of this person.

    +
    + +Expand source code + +
    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 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:

    +

    surname=[name] +Match a person with [name] in any part of the surname. +given_name=[given_name] +Match a person with [given_name] in any part of the given given_name. +birth=[year] +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].

    +
    + +Expand source code + +
    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:
    +
    +    surname=[name]
    +         Match a person with [name] in any part of the `surname`.
    +    given_name=[given_name]
    +         Match a person with [given_name] in any part of the given `given_name`.
    +    birth=[year]
    +         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].
    +    """
    +
    +    # Check if criteria is a valid criteria and can be split by `:` and `=` characters
    +    try:
    +        for criterion in criteria.split(':'):
    +            criterion.split('=')
    +    except ValueError:
    +        return False
    +
    +    match = True
    +
    +    for criterion in criteria.split(':'):
    +        key, value = criterion.split('=')
    +
    +        if key == "surname" and not self.surname_match(value):
    +            match = False
    +        elif key == "name" and not self.given_name_match(value):
    +            match = False
    +        elif key == "birth":
    +
    +            try:
    +                year = int(value)
    +                if not self.birth_year_match(year):
    +                    match = False
    +            except ValueError:
    +                match = False
    +
    +        elif key == "birth_range":
    +
    +            try:
    +                from_year, to_year = value.split('-')
    +                from_year = int(from_year)
    +                to_year = int(to_year)
    +                if not self.birth_range_match(from_year, to_year):
    +                    match = False
    +            except ValueError:
    +                match = False
    +
    +        elif key == "death":
    +
    +            try:
    +                year = int(value)
    +                if not self.death_year_match(year):
    +                    match = False
    +            except ValueError:
    +                match = False
    +
    +        elif key == "death_range":
    +
    +            try:
    +                from_year, to_year = value.split('-')
    +                from_year = int(from_year)
    +                to_year = int(to_year)
    +                if not self.death_range_match(from_year, to_year):
    +                    match = False
    +            except ValueError:
    +                match = False
    +
    +    return match
    +
    +
    +
    +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.

    +
    + +Expand source code + +
    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()
    +
    +    if from_year <= death_year <= to_year:
    +        return True
    +
    +    return False
    +
    +
    +
    +def death_year_match(self, year: int) ‑> bool +
    +
    +

    Returns True if the given year matches the death year of this person.

    +
    + +Expand source code + +
    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) ‑> List[str] +
    +
    +

    Return all names.

    +
    + +Expand source code + +
    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 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)

    +
    + +Expand source code + +
    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)
    +    """
    +    date = ""
    +    place = ""
    +    sources = []
    +
    +    for child in self.get_child_elements():
    +        if child.get_tag() == tags.GEDCOM_TAG_BIRTH:
    +            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
    +
    +
    +
    +def get_birth_year(self) ‑> int +
    +
    +

    Returns the birth year of a person in integer format.

    +
    + +Expand source code + +
    def get_birth_year(self) -> int:
    +    """Returns the birth year of a person in integer format.
    +    """
    +    date = ""
    +
    +    for child in self.get_child_elements():
    +        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 == "":
    +        return -1
    +    try:
    +        return int(date)
    +    except ValueError:
    +        return -1
    +
    +
    +
    +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

    +
    + +Expand source code + +
    @deprecated
    +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
    +    """
    +    self.get_burial_data()
    +
    +
    +
    +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)

    +
    + +Expand source code + +
    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 = ""
    +    sources = []
    +
    +    for child in self.get_child_elements():
    +        if child.get_tag() == tags.GEDCOM_TAG_BURIAL:
    +            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
    +
    +
    +
    +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

    +
    + +Expand source code + +
    @deprecated
    +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
    +    """
    +    self.get_census_data()
    +
    +
    +
    +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)

    +
    + +Expand source code + +
    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 = []
    +
    +    for child in self.get_child_elements():
    +        if child.get_tag() == tags.GEDCOM_TAG_CENSUS:
    +
    +            date = ''
    +            place = ''
    +            sources = []
    +
    +            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())
    +
    +            census.append((date, place, sources))
    +
    +    return census
    +
    +
    +
    +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)

    +
    + +Expand source code + +
    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 = ""
    +    sources = []
    +
    +    for child in self.get_child_elements():
    +        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
    +
    +
    +
    +def get_death_year(self) ‑> int +
    +
    +

    Returns the death year of a person in integer format.

    +
    + +Expand source code + +
    def get_death_year(self) -> int:
    +    """Returns the death year of a person in integer format.
    +    """
    +    date = ""
    +
    +    for child in self.get_child_elements():
    +        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 == "":
    +        return -1
    +    try:
    +        return int(date)
    +    except ValueError:
    +        return -1
    +
    +
    +
    +def get_gender(self) ‑> str +
    +
    +

    Returns the gender of a person in string format.

    +
    + +Expand source code + +
    def get_gender(self) -> str:
    +    """Returns the gender of a person in string format.
    +    """
    +    gender = ""
    +
    +    for child in self.get_child_elements():
    +        if child.get_tag() == tags.GEDCOM_TAG_SEX:
    +            gender = child.get_value()
    +
    +    return gender
    +
    +
    +
    +def get_last_change_date(self) ‑> 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) -> str:
    +    """Returns the date of when the person data was last changed formatted as a string.
    +    """
    +    date = ""
    +
    +    for child in self.get_child_elements():
    +        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
    +
    +
    +
    +def get_name(self) ‑> Tuple[str, str] +
    +
    +

    Returns an individual's names as a tuple: (str given_name, str surname)

    +
    + +Expand source code + +
    def get_name(self) -> Tuple[str, str]:
    +    """Returns an individual's names as a tuple: (`str` given_name, `str` surname)
    +    """
    +    given_name = ""
    +    surname = ""
    +
    +    # 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() == 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() != "":
    +                name = child.get_value().split('/')
    +
    +                if len(name) > 0:
    +                    given_name = name[0].strip()
    +                    if len(name) > 1:
    +                        surname = name[1].strip()
    +
    +                return given_name, surname
    +
    +            for gchild in child.get_child_elements():
    +
    +                if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME:
    +                    given_name = gchild.get_value()
    +                    found_given_name = True
    +
    +                if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME:
    +                    surname = gchild.get_value()
    +                    found_surname_name = True
    +
    +            if found_given_name and found_surname_name:
    +                return given_name, surname
    +
    +    # If we reach here we are probably returning empty strings
    +    return given_name, surname
    +
    +
    +
    +def get_occupation(self) ‑> str +
    +
    +

    Returns the occupation of a person.

    +
    + +Expand source code + +
    def get_occupation(self) -> str:
    +    """Returns the occupation of a person.
    +    """
    +    occupation = ""
    +
    +    for child in self.get_child_elements():
    +        if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION:
    +            occupation = child.get_value()
    +
    +    return occupation
    +
    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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: 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

    +
    + +Expand source code + +
    @deprecated
    +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
    +    """
    +    return self.given_name_match(name)
    +
    +
    +
    +def given_name_match(self, given_name_to_match: str) ‑> bool +
    +
    +

    Matches a string with the given name of an individual.

    +
    + +Expand source code + +
    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) ‑> bool +
    +
    +

    Checks if this element is a child of a family.

    +
    + +Expand source code + +
    def is_child(self) -> bool:
    +    """Checks if this element is a child of a family.
    +    """
    +    found_child = False
    +
    +    for child in self.get_child_elements():
    +        if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD:
    +            found_child = True
    +
    +    return found_child
    +
    +
    +
    +def is_deceased(self) ‑> bool +
    +
    +

    Checks if this individual is deceased.

    +
    + +Expand source code + +
    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:
    +            return True
    +
    +    return False
    +
    +
    +
    +def is_private(self) ‑> bool +
    +
    +

    Checks if this individual is marked private.

    +
    + +Expand source code + +
    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:
    +            private = child.get_value()
    +            if private == 'Y':
    +                return True
    +
    +    return False
    +
    +
    +
    +def surname_match(self, surname_to_match: str) ‑> bool +
    +
    +

    Matches a string with the surname of an individual.

    +
    + +Expand source code + +
    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)
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/note.html b/docs/gedcom/elements/note.html new file mode 100644 index 0000000..ad45f5c --- /dev/null +++ b/docs/gedcom/elements/note.html @@ -0,0 +1,246 @@ + + + + + + +gedcom.elements.note API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.note

    +
    +
    +

    GEDCOM element for a NOTE_RECORD note record identified by the +GEDCOM_TAG_NOTE tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `NOTE_RECORD` note record identified by the
    +`gedcom.tags.GEDCOM_TAG_NOTE` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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) -> str:
    +        return tags.GEDCOM_TAG_NOTE
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class NoteElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a NOTE_RECORD

    +
    + +Expand source code + +
    class NoteElement(Element):
    +    """Element associated with a `NOTE_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_NOTE
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/object.html b/docs/gedcom/elements/object.html new file mode 100644 index 0000000..666b875 --- /dev/null +++ b/docs/gedcom/elements/object.html @@ -0,0 +1,346 @@ + + + + + + +gedcom.elements.object API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.object

    +
    +
    +

    GEDCOM element for a MULTIMEDIA_RECORD media record identified by the +GEDCOM_TAG_OBJECT tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `MULTIMEDIA_RECORD` media record identified by the
    +`gedcom.tags.GEDCOM_TAG_OBJECT` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.element import Element
    +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 get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_OBJECT
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class ObjectElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a MULTIMEDIA_RECORD

    +
    + +Expand source code + +
    class ObjectElement(Element):
    +    """Element associated with a `MULTIMEDIA_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_OBJECT
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/repository.html b/docs/gedcom/elements/repository.html new file mode 100644 index 0000000..23edc17 --- /dev/null +++ b/docs/gedcom/elements/repository.html @@ -0,0 +1,274 @@ + + + + + + +gedcom.elements.repository API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.repository

    +
    +
    +

    GEDCOM element for a REPOSITORY_RECORD repository record identified by the +GEDCOM_TAG_REPOSITORY tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `REPOSITORY_RECORD` repository record identified by the
    +`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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) -> str:
    +        return tags.GEDCOM_TAG_REPOSITORY
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class RepositoryElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a REPOSITORY_RECORD

    +
    + +Expand source code + +
    class RepositoryElement(Element):
    +    """Element associated with a `REPOSITORY_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_REPOSITORY
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/element/root.html b/docs/gedcom/elements/root.html similarity index 61% rename from docs/gedcom/element/root.html rename to docs/gedcom/elements/root.html index 8eabb78..084bfba 100644 --- a/docs/gedcom/element/root.html +++ b/docs/gedcom/elements/root.html @@ -4,7 +4,7 @@ -gedcom.element.root API documentation +gedcom.elements.root API documentation @@ -19,7 +19,7 @@
    -

    Module gedcom.element.root

    +

    Module gedcom.elements.root

    Virtual GEDCOM root element containing all logical records as children

    @@ -29,40 +29,27 @@

    Module gedcom.element.root

    # -*- coding: utf-8 -*-
     
    -# Python GEDCOM Parser
    +#  Copyright (C) 2020
     #
    -# 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 file is part of the Python GEDCOM Parser.
     #
    -# 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.
    +#  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.
     #
    -# 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
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
     
     """Virtual GEDCOM root element containing all logical records as children"""
     
    -from gedcom.element.element import Element
    +from gedcom.elements.element import Element
     
     
     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)
@@ -75,44 +62,45 @@

Module gedcom.element.root

Classes

-
+
class RootElement -(level=-1, pointer='', tag='ROOT', value='', crlf='\n', multi_line=True) +(level: int = -1, pointer: str = '', tag: str = 'ROOT', value: str = '', crlf: str = '\n', multi_line: bool = True)
-

Virtual GEDCOM root element containing all logical records as children

+

Virtual GEDCOM root element containing all logical records as children.

Expand source code
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)

Ancestors

Inherited members

@@ -128,13 +116,13 @@

Index

  • Super-module

  • Classes

  • diff --git a/docs/gedcom/elements/source.html b/docs/gedcom/elements/source.html new file mode 100644 index 0000000..407d1e6 --- /dev/null +++ b/docs/gedcom/elements/source.html @@ -0,0 +1,405 @@ + + + + + + +gedcom.elements.source API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.source

    +
    +
    +

    GEDCOM element for a SOURCE_RECORD source record identified by the +GEDCOM_TAG_SOURCE tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `SOURCE_RECORD` source record identified by the
    +`gedcom.tags.GEDCOM_TAG_SOURCE` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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) -> str:
    +        return tags.GEDCOM_TAG_SOURCE
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class SourceElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a SOURCE_RECORD

    +
    + +Expand source code + +
    class SourceElement(Element):
    +    """Element associated with a SOURCE_RECORD"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_SOURCE
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the full record in dictionary format.
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the full record in dictionary format.

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the full record in dictionary format.
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/submission.html b/docs/gedcom/elements/submission.html new file mode 100644 index 0000000..07e9105 --- /dev/null +++ b/docs/gedcom/elements/submission.html @@ -0,0 +1,255 @@ + + + + + + +gedcom.elements.submission API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.submission

    +
    +
    +

    GEDCOM element for a SUBMISSION_RECORD submission record identified by the +GEDCOM_TAG_SUBMISSION tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `SUBMISSION_RECORD` submission record identified by the
    +`gedcom.tags.GEDCOM_TAG_SUBMISSION` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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) -> str:
    +        return tags.GEDCOM_TAG_SUBMISSION
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the record in dictionary format
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class SubmissionElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a SUBMISSION_RECORD

    +
    + +Expand source code + +
    class SubmissionElement(Element):
    +    """Element associated with a `SUBMISSION_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_SUBMISSION
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the record in dictionary format
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the record in dictionary format

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the record in dictionary format
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/elements/submitter.html b/docs/gedcom/elements/submitter.html new file mode 100644 index 0000000..70c0b5f --- /dev/null +++ b/docs/gedcom/elements/submitter.html @@ -0,0 +1,304 @@ + + + + + + +gedcom.elements.submitter API documentation + + + + + + + + + + + +
    +
    +
    +

    Module gedcom.elements.submitter

    +
    +
    +

    GEDCOM element for a SUBMITTER_RECORD submitter record identified by the +GEDCOM_TAG_SUBMITTER tag.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +GEDCOM element for a `SUBMITTER_RECORD` submitter record identified by the
    +`gedcom.tags.GEDCOM_TAG_SUBMITTER` tag.
    +"""
    +
    +import gedcom.tags as tags
    +from gedcom.elements.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) -> str:
    +        return tags.GEDCOM_TAG_SUBMITTER
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the record in dictionary format
    +        """
    +        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
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class SubmitterElement +(level: int, pointer: str, tag: str, value: str, crlf: str = '\n', multi_line: bool = True) +
    +
    +

    Element associated with a SUBMITTER_RECORD

    +
    + +Expand source code + +
    class SubmitterElement(Element):
    +    """Element associated with a `SUBMITTER_RECORD`"""
    +
    +    def get_tag(self) -> str:
    +        return tags.GEDCOM_TAG_SUBMITTER
    +
    +    def get_record(self) -> dict:
    +        """Parse and return the record in dictionary format
    +        """
    +        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
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def get_record(self) ‑> dict +
    +
    +

    Parse and return the record in dictionary format

    +
    + +Expand source code + +
    def get_record(self) -> dict:
    +    """Parse and return the record in dictionary format
    +    """
    +    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
    +
    +
    +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/gedcom/errors.html b/docs/gedcom/errors.html new file mode 100644 index 0000000..5d7cfd0 --- /dev/null +++ b/docs/gedcom/errors.html @@ -0,0 +1,480 @@ + + + + + + +gedcom.errors API documentation + + + + + + + + + +
    +
    +
    +

    Module gedcom.errors

    +
    +
    +

    Module containing the exception handling classes.

    +
    + +Expand source code + +
    # -*- coding: utf-8 -*-
    +
    +#  Copyright (C) 2020
    +#
    +#  This file is part of the Python GEDCOM Parser.
    +#
    +#  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.
    +#
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
    +
    +"""
    +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 that version requires the
    +    parser to reject it.
    +    """
    +
    +
    +class GedcomFormatUnsupportedError(Exception):
    +    """Raised if the GEDCOM format is not recognized by the
    +    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.
    +    """
    +
    +
    +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`"""
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class GedcomCharacterSetUnsupportedError +(...) +
    +
    +

    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 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 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

    +
      +
    • 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 that 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 that 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 d633974..07cd374 100644 --- a/docs/gedcom/helpers.html +++ b/docs/gedcom/helpers.html @@ -3,17 +3,15 @@ - + gedcom.helpers API documentation - - - - + + + + - -
    @@ -29,30 +27,16 @@

    Module gedcom.helpers

    # -*- coding: utf-8 -*-
     
    -# Python GEDCOM Parser
    +#  Copyright (C) 2020
     #
    -# 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 file is part of the Python GEDCOM Parser.
     #
    -# 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.
    +#  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.
     #
    -# 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
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
     
     """
     Helper methods.
    @@ -143,7 +127,9 @@ 

    Index

    + + \ No newline at end of file diff --git a/docs/gedcom/index.html b/docs/gedcom/index.html index f947549..a27e8df 100644 --- a/docs/gedcom/index.html +++ b/docs/gedcom/index.html @@ -3,17 +3,15 @@ - + gedcom API documentation - - - - + + + + - -
    @@ -38,11 +36,12 @@

    Important classes and modules

    Example usage

    When successfully installed you may import the gedcom package and use it like so:

    -
    from gedcom.element.individual import IndividualElement
    +
    from gedcom.elements.individual import IndividualElement
     from gedcom.parser import Parser
     
     # Path to your ".ged" file
    @@ -81,7 +80,7 @@ 

    Strict parsing

    If you encounter errors in parsing, you might consider disabling strict parsing which is enabled by default:

    from gedcom.parser import Parser
     
    -file_path = '' # Path to your `.ged` file
    +file_path = '' # Path to your <code>.ged</code> file
     
     gedcom_parser = Parser()
     gedcom_parser.parse_file(file_path, False) # Disable strict parsing
    @@ -94,6 +93,7 @@ 

    Strict parsing

    License

    Licensed under the GNU General Public License v2

    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 @@ -118,30 +118,16 @@

    License

    # -*- coding: utf-8 -*-
     
    -# Python GEDCOM Parser
    +#  Copyright (C) 2020
     #
    -# 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 file is part of the Python GEDCOM Parser.
     #
    -# 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.
    +#  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.
     #
    -# 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
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
     
     """
     A Python module for parsing, analyzing, and manipulating GEDCOM files.
    @@ -151,10 +137,16 @@ 

    License

    __all__ = [ # Subpackages - "element", + "elements", + "subparsers", # Modules + "errors", "helpers", + "detect", "parser", + "reader", + "records", + "standards", "tags" ]
    @@ -162,23 +154,50 @@

    License

    Sub-modules

    -
    gedcom.element
    +
    gedcom.detect
    +
    +

    Module containing functions for detecting GEDCOM file encoding and version.

    +
    +
    gedcom.elements

    Module containing all relevant elements generated by a Parser. An element represents a line within GEDCOM data.

    +
    gedcom.errors
    +
    +

    Module containing the exception handling classes.

    +
    gedcom.helpers

    Helper methods.

    gedcom.parser
    -

    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.

    +
    +
    gedcom.reader
    +
    +

    Module containing a Reader with higher order methods than the +base Parser for extracting records as structured data.

    +
    +
    gedcom.records
    +
    +

    Module containing the standard GEDCOM record types recognized by the +GEDCOM Reader.

    +
    +
    gedcom.standards
    +
    +

    Module containing links to the documentation for the various GEDCOM standards.

    +
    +
    gedcom.subparsers
    +
    +

    Module containing parsers for extracting various substructures from the +different record types as defined in the GEDCOM standard.

    gedcom.tags
    -

    GEDCOM tags.

    +

    Module containing the standard GEDCOM tags and some of the most common program defined extensions.

    @@ -206,9 +225,15 @@

    Index

    + + \ No newline at end of file diff --git a/docs/gedcom/parser.html b/docs/gedcom/parser.html index 8694989..48ad9a6 100644 --- a/docs/gedcom/parser.html +++ b/docs/gedcom/parser.html @@ -5,8 +5,8 @@ gedcom.parser API documentation - + @@ -23,69 +23,83 @@

    Module gedcom.parser

    -

    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
    # -*- coding: utf-8 -*-
     
    -# Python GEDCOM Parser
    +#  Copyright (C) 2020
     #
    -# 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 file is part of the Python GEDCOM Parser.
     #
    -# 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.
    +#  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.
     #
    -# 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
    +#  For more, have a look at the GitHub repository at:
    +#  https://github.com/nickreynke/python-gedcom
     
     """
    -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 stdout
     from sys import version_info
    -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.object import ObjectElement
    -from gedcom.element.root import RootElement
    -import gedcom.tags
    +from typing import Tuple, List, IO
    +
    +import gedcom.tags as tags
    +import gedcom.standards as standards
    +
    +from gedcom.detect import get_encoding, get_version
    +from gedcom.elements.element import Element
    +from gedcom.elements.header import HeaderElement
    +from gedcom.elements.family import FamilyElement
    +from gedcom.elements.individual import IndividualElement
    +from gedcom.elements.note import NoteElement
    +from gedcom.elements.object import ObjectElement
    +from gedcom.elements.source import SourceElement
    +from gedcom.elements.submission import SubmissionElement
    +from gedcom.elements.submitter import SubmitterElement
    +from gedcom.elements.repository import RepositoryElement
    +from gedcom.elements.root import RootElement
    +
    +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():
    +    """Parses and manipulates GEDCOM formatted data.
     
    -class Parser(object):
    -    """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 different GEDCOM standards see the
    +    links defined in `gedcom.standards`
     
         This parser reads and parses a GEDCOM file.
     
    @@ -101,35 +115,36 @@ 

    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. """ 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. 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 """ 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): - """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file + def get_element_dictionary(self) -> dict: + """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. @@ -137,46 +152,51 @@

    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 = { - 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 - 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. """ - 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): - """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() @@ -185,24 +205,18 @@

    Module gedcom.parser

    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 @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. @@ -221,43 +235,43 @@

    Module gedcom.parser

    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() @@ -269,20 +283,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) @@ -297,10 +305,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(): @@ -308,81 +314,74 @@

    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): 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 - 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 = [] 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: - for childOfChild in child.get_child_elements(): - if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE: - date = childOfChild.get_value().split()[-1] + if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE: + 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( - "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) 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( - "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) @@ -391,20 +390,19 @@

    Module gedcom.parser

    return True return False - def get_families(self, individual, family_type=gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE): - """Return family elements listed for an individual + 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: - 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. + `tags.GEDCOM_TAG_FAMILY_SPOUSE`: Default, families where the individual is a spouse. - :type individual: IndividualElement - :type family_type: str - :rtype: list of FamilyElement + `tags.GEDCOM_TAG_FAMILY_CHILD`: Families where the individual is a child. """ 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,19 +417,19 @@

    Module gedcom.parser

    return families - def get_ancestors(self, individual, ancestor_type="ALL"): - """Return elements corresponding to ancestors of an individual + def get_ancestors(self, individual: IndividualElement, + ancestor_type: str = "ALL") -> List[Element]: + """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. + Optional argument `ancestor_type` can be used to return specific subsets: - :type individual: IndividualElement - :type ancestor_type: str - :rtype: list of Element + "ALL": Default, returns all ancestors. + + "NAT": Return only natural (genetic) 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 ) parents = self.get_parents(individual, ancestor_type) @@ -443,49 +441,53 @@

    Module gedcom.parser

    return ancestors - def get_parents(self, individual, parent_type="ALL"): - """Return elements corresponding to parents of an individual + 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: - Optional parent_type. Default "ALL" returns all parents. "NAT" can be - used to specify only natural (genetic) parents. + "ALL": Default, returns all parents. - :type individual: IndividualElement - :type parent_type: str - :rtype: list of IndividualElement + "NAT": Return only natural (genetic) parents. """ 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") 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." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL + "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL ) if not path: @@ -493,33 +495,34 @@

    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 + "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children) """ 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 = [] @@ -527,19 +530,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()]) @@ -548,9 +551,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'' @@ -564,14 +567,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))
    @@ -585,31 +585,13 @@

    Module gedcom.parser

    Classes

    -
    -class GedcomFormatViolationError -(...) -
    -
    -

    Common base class for all non-exit exceptions.

    -
    - -Expand source code - -
    class GedcomFormatViolationError(Exception):
    -    pass
    -
    -

    Ancestors

    -
      -
    • builtins.Exception
    • -
    • builtins.BaseException
    • -
    -
    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

    +

    Parses and manipulates GEDCOM formatted data.

    +

    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:

      @@ -620,10 +602,11 @@

      Ancestors

      Expand source code -
      class Parser(object):
      -    """Parses and manipulates GEDCOM 5.5 format data
      +
      class Parser():
      +    """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.
       
      @@ -639,35 +622,36 @@ 

      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. """ 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. 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 """ 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): - """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file + def get_element_dictionary(self) -> dict: + """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. @@ -675,46 +659,51 @@

      Ancestors

      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 = { - 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 - 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. """ - 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): - """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() @@ -723,24 +712,18 @@

      Ancestors

      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 @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. @@ -759,43 +742,43 @@

      Ancestors

      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() @@ -807,20 +790,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) @@ -835,10 +812,8 @@

      Ancestors

      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(): @@ -846,81 +821,74 @@

      Ancestors

      # 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): 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 - 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 = [] 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: - for childOfChild in child.get_child_elements(): - if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE: - date = childOfChild.get_value().split()[-1] + if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE: + 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( - "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) 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( - "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) @@ -929,20 +897,19 @@

      Ancestors

      return True return False - def get_families(self, individual, family_type=gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE): - """Return family elements listed for an individual + def get_families(self, individual: IndividualElement, + family_type: str = tags.GEDCOM_TAG_FAMILY_SPOUSE) -> List[FamilyElement]: + """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. + Optional argument `family_type` can be used to return specific subsets: - :type individual: IndividualElement - :type family_type: str - :rtype: list of FamilyElement + `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( - "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,19 +924,19 @@

      Ancestors

      return families - def get_ancestors(self, individual, ancestor_type="ALL"): - """Return elements corresponding to ancestors of an individual + 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: - Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be - used to specify only natural (genetic) ancestors. + "ALL": Default, returns all ancestors. - :type individual: IndividualElement - :type ancestor_type: str - :rtype: list of Element + "NAT": Return only natural (genetic) 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 ) parents = self.get_parents(individual, ancestor_type) @@ -981,49 +948,53 @@

      Ancestors

      return ancestors - def get_parents(self, individual, parent_type="ALL"): - """Return elements corresponding to parents of an individual + 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: - Optional parent_type. Default "ALL" returns all parents. "NAT" can be - used to specify only natural (genetic) parents. + "ALL": Default, returns all parents. - :type individual: IndividualElement - :type parent_type: str - :rtype: list of IndividualElement + "NAT": Return only natural (genetic) parents. """ 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") 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." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL + "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL ) if not path: @@ -1031,33 +1002,34 @@

      Ancestors

      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 + "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children) """ 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 = [] @@ -1065,19 +1037,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()]) @@ -1086,9 +1058,9 @@

      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 + 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'' @@ -1102,36 +1074,39 @@

      Ancestors

      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))
      +

      Subclasses

      +

      Methods

      -def find_path_to_ancestor(self, descendant, ancestor, path=None) +def find_path_to_ancestor(self, descendant: IndividualElement, ancestor: IndividualElement, path: str = None)
      -

      Return path from descendant to ancestor +

      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." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL
      +            "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL
               )
       
           if not path:
      @@ -1139,43 +1114,41 @@ 

      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
      -def get_ancestors(self, individual, ancestor_type='ALL') +def get_ancestors(self, individual: IndividualElement, ancestor_type: str = 'ALL') ‑> List[Element]
      -

      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
      +
      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:
       
      -    Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
      -    used to specify only natural (genetic) ancestors.
      +    "ALL": Default, returns all ancestors.
       
      -    :type individual: IndividualElement
      -    :type ancestor_type: str
      -    :rtype: list of Element
      +    "NAT": Return only natural (genetic) 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
               )
       
           parents = self.get_parents(individual, ancestor_type)
      @@ -1189,22 +1162,23 @@ 

      Methods

      -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

      +

      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

      +this method return updated data.

      Expand source code -
      def get_element_dictionary(self):
      -    """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file
      +
      def get_element_dictionary(self) -> dict:
      +    """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.
      @@ -1212,46 +1186,44 @@ 

      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 = { - 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
      -def get_element_list(self) +def get_element_list(self) ‑> List[Element]
      -

      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.

      -

      Consider using Parser.get_root_element() or Parser.get_root_child_elements() to access -the hierarchical GEDCOM tree, unless you rarely modify the database.

      -

      :rtype: list of Element

      +was modified, you should call Parser.invalidate_cache() once +to let this method return updated data.

      +

      Consider using Parser.get_root_element() or +Parser.get_root_child_elements() to access +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.
       
           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
           """
           if not self.__element_list:
               for element in self.get_root_child_elements():
      @@ -1260,34 +1232,30 @@ 

      Methods

      -def get_families(self, individual, family_type='FAMS') +def get_families(self, individual: IndividualElement, family_type: str = 'FAMS') ‑> List[FamilyElement]
      -

      Return family elements listed for an individual

      -

      family_type can be GEDCOM_TAG_FAMILY_SPOUSE (families where the individual is a spouse) or -GEDCOM_TAG_FAMILY_CHILD (families where the individual is a child). If a value is not -provided, 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=gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE):
      -    """Return family elements listed for an individual
      +
      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:
       
      -    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.
      +    `tags.GEDCOM_TAG_FAMILY_SPOUSE`: Default, families where the individual is a spouse.
       
      -    :type individual: IndividualElement
      -    :type family_type: str
      -    :rtype: list of FamilyElement
      +    `tags.GEDCOM_TAG_FAMILY_CHILD`: Families where the individual is a child.
           """
           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 = []
      @@ -1304,41 +1272,39 @@ 

      Methods

      -def get_family_members(self, family, members_type='ALL') +def get_family_members(self, family: FamilyElement, members_type: str = 'ALL') ‑> List[IndividualElement]
      -

      Return array of family members: individual, spouse, and children

      +

      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

      +

      "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
      +    "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)
           """
           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 = []
      @@ -1346,19 +1312,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()]) @@ -1367,36 +1333,32 @@

      Methods

      -def get_marriage_years(self, individual) +def get_marriage_years(self, individual: IndividualElement) ‑> List[int]
      -

      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 = []
       
           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:
      -                for childOfChild in child.get_child_elements():
      -                    if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE:
      -                        date = childOfChild.get_value().split()[-1]
      +            if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE:
      +                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:
      @@ -1405,87 +1367,85 @@ 

      Methods

      -def get_marriages(self, individual) +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) -: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):
               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
      -def get_parents(self, individual, parent_type='ALL') +def get_parents(self, individual: IndividualElement, parent_type: str = 'ALL') ‑> List[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

      +

      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
      +
      def get_parents(self, individual: IndividualElement,
      +                parent_type: str = "ALL") -> List[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.
      +    Optional argument `parent_type` can be used to return specific subsets:
       
      -    :type individual: IndividualElement
      -    :type parent_type: str
      -    :rtype: list of IndividualElement
      +    "ALL": Default, returns all parents.
      +
      +    "NAT": Return only natural (genetic) parents.
           """
           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")
       
      @@ -1493,43 +1453,37 @@ 

      Methods

      -def get_root_child_elements(self) +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

      +

      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()
      -def get_root_element(self) +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

      +

      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
      @@ -1538,16 +1492,18 @@

      Methods

      def invalidate_cache(self)
      -

      Empties the element list and dictionary to cause Parser.get_element_list() -and Parser.get_element_dictionary() to return updated data.

      +

      Empties the element list and dictionary to cause +Parser.get_element_list() and +Parser.get_element_dictionary() to return updated data.

      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.
           """
      @@ -1556,28 +1512,23 @@ 

      Methods

      -def marriage_range_match(self, individual, from_year, to_year) +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. -: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(
      -            "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)
      @@ -1588,26 +1539,22 @@ 

      Methods

      -def marriage_year_match(self, individual, year) +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. -: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(
      -            "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)
      @@ -1615,20 +1562,16 @@ 

      Methods

      -def parse(self, gedcom_stream, strict=True) +def parse(self, gedcom_stream: IO, strict: bool = 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

      +

      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()
      @@ -1637,27 +1580,37 @@ 

      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
      -def parse_file(self, file_path, strict=True) +def parse_file(self, file_path: str, strict: bool = True)
      -

      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.
           """
      -    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)
      @@ -1665,49 +1618,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)
      -def save_gedcom(self, open_file, recursive=True) +def save_gedcom(self, open_file: IO, recursive: bool = True)
      -

      Save GEDCOM data to a file -:type open_file: file -:type recursive: bool

      +

      Save GEDCOM data to a file.

      Expand source code -
      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))
      -def to_gedcom_string(self, recursive=False) +def to_gedcom_string(self, recursive: bool = False) ‑> str
      -

      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''
      @@ -1740,9 +1688,6 @@ 

      Index

    • Classes

      • -

        GedcomFormatViolationError

        -
      • -
      • Parser

        • find_path_to_ancestor
        • diff --git a/docs/gedcom/reader.html b/docs/gedcom/reader.html new file mode 100644 index 0000000..4a15e38 --- /dev/null +++ b/docs/gedcom/reader.html @@ -0,0 +1,353 @@ + + + + + + +gedcom.reader API documentation + + + + + + + + + +
          +
          +
          +

          Module gedcom.reader

          +
          +
          +

          Module containing a Reader with higher order methods than the +base Parser for extracting records as structured data.

          +
          + +Expand source code + +
          # -*- coding: utf-8 -*-
          +
          +#  Copyright (C) 2020
          +#
          +#  This file is part of the Python GEDCOM Parser.
          +#
          +#  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.
          +#
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
          +
          +"""
          +Module containing a `gedcom.reader.Reader` with higher order methods than the
          +base `gedcom.parser.Parser` for extracting records as structured data.
          +"""
          +
          +from typing import Union
          +
          +from gedcom.parser import Parser
          +from gedcom.elements.header import HeaderElement
          +from gedcom.elements.individual import IndividualElement
          +from gedcom.elements.family import FamilyElement
          +from gedcom.elements.note import NoteElement
          +from gedcom.elements.object import ObjectElement
          +from gedcom.elements.source import SourceElement
          +from gedcom.elements.submission import SubmissionElement
          +from gedcom.elements.submitter import SubmitterElement
          +from gedcom.elements.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 around the core `gedcom.parser.Parser` with methods for
          +    extracting parsed records as structured data.
          +    """
          +
          +    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 = {}
          +
          +        for element in self.get_root_child_elements():
          +            if isinstance(element, ELEMENT_TYPES[record_type]):
          +                record = element.get_record()
          +                if return_output_as_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 return_output_as_list:
          +            return record_list
          +
          +        return record_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 return_entries_as_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 return_entries_as_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 around the core Parser with methods for +extracting parsed records as structured data.

          +
          + +Expand source code + +
          class Reader(Parser):
          +    """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: 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 = {}
          +
          +        for element in self.get_root_child_elements():
          +            if isinstance(element, ELEMENT_TYPES[record_type]):
          +                record = element.get_record()
          +                if return_output_as_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 return_output_as_list:
          +            return record_list
          +
          +        return record_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 return_entries_as_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 return_entries_as_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
          +
          +

          Ancestors

          + +

          Methods

          +
          +
          +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.

          +
          + +Expand source code + +
          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 return_entries_as_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 return_entries_as_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
          +
          +
          +
          +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.

          +
          + +Expand source code + +
          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 = {}
          +
          +    for element in self.get_root_child_elements():
          +        if isinstance(element, ELEMENT_TYPES[record_type]):
          +            record = element.get_record()
          +            if return_output_as_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 return_output_as_list:
          +        return record_list
          +
          +    return record_dict
          +
          +
          +
          +

          Inherited members

          + +
          +
          +
          +
          + +
          + + + + + \ No newline at end of file diff --git a/docs/gedcom/records.html b/docs/gedcom/records.html new file mode 100644 index 0000000..cba70d3 --- /dev/null +++ b/docs/gedcom/records.html @@ -0,0 +1,172 @@ + + + + + + +gedcom.records API documentation + + + + + + + + + +
          +
          +
          +

          Module gedcom.records

          +
          +
          +

          Module containing the standard GEDCOM record types recognized by the +GEDCOM Reader.

          +
          + +Expand source code + +
          # -*- coding: utf-8 -*-
          +
          +#  Copyright (C) 2020
          +#
          +#  This file is part of the Python GEDCOM Parser.
          +#
          +#  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.
          +#
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
          +
          +"""Module containing the standard GEDCOM record types recognized by the
          +GEDCOM `gedcom.reader.Reader`."""
          +
          +
          +GEDCOM_RECORD_FAMILY = "family"
          +"""Value: `family`
          +
          +Identifies the `FAM_RECORD` record type."""
          +
          +GEDCOM_RECORD_HEADER = "header"
          +"""Value: `header`
          +
          +Identifies the `HEADER` record type."""
          +
          +GEDCOM_RECORD_INDIVIDUAL = "individual"
          +"""Value: `individual`
          +
          +Identifies the `INDIVIDUAL_RECORD` record type."""
          +
          +GEDCOM_RECORD_NOTE = "note"
          +"""Value: `note`
          +
          +Identifies the `NOTE_RECORD` record type."""
          +
          +GEDCOM_RECORD_SOURCE = "source"
          +"""Value: `source`
          +
          +Identifies the `SOURCE_RECORD` record type."""
          +
          +GEDCOM_RECORD_REPOSITORY = "repository"
          +"""Value: `repository`
          +
          +Identifies the `REPOSITORY_RECORD` record type."""
          +
          +GEDCOM_RECORD_SUBMISSION = "submission"
          +"""Value: `submission`
          +
          +Identifies the `SUBMISSION_RECORD` record type."""
          +
          +GEDCOM_RECORD_SUBMITTER = "submitter"
          +"""Value: `submitter`
          +
          +Identifies the `SUBMITTER_RECORD` record type."""
          +
          +
          +
          +
          +
          +

          Global variables

          +
          +
          var GEDCOM_RECORD_FAMILY
          +
          +

          Value: family

          +

          Identifies the FAM_RECORD record type.

          +
          +
          var GEDCOM_RECORD_HEADER
          +
          +

          Value: header

          +

          Identifies the HEADER record type.

          +
          +
          var GEDCOM_RECORD_INDIVIDUAL
          +
          +

          Value: individual

          +

          Identifies the INDIVIDUAL_RECORD record type.

          +
          +
          var GEDCOM_RECORD_NOTE
          +
          +

          Value: note

          +

          Identifies the NOTE_RECORD record type.

          +
          +
          var GEDCOM_RECORD_REPOSITORY
          +
          +

          Value: repository

          +

          Identifies the REPOSITORY_RECORD record type.

          +
          +
          var GEDCOM_RECORD_SOURCE
          +
          +

          Value: source

          +

          Identifies the SOURCE_RECORD record type.

          +
          +
          var GEDCOM_RECORD_SUBMISSION
          +
          +

          Value: submission

          +

          Identifies the SUBMISSION_RECORD record type.

          +
          +
          var GEDCOM_RECORD_SUBMITTER
          +
          +

          Value: 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 new file mode 100644 index 0000000..2998288 --- /dev/null +++ b/docs/gedcom/standards.html @@ -0,0 +1,115 @@ + + + + + + +gedcom.standards API documentation + + + + + + + + + +
          +
          +
          +

          Module gedcom.standards

          +
          +
          +

          Module containing links to the documentation for the various GEDCOM standards.

          +
          + +Expand source code + +
          # -*- coding: utf-8 -*-
          +
          +#  Copyright (C) 2020
          +#
          +#  This file is part of the Python GEDCOM Parser.
          +#
          +#  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.
          +#
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
          +
          +"""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."""
          +
          +GEDCOM_5_5_1 = "https://edge.fscdn.org/assets/img/documents/" + \
          +    "ged551-5bac5e57fe88dd37df0e153d9c515335.pdf"
          +"""The official FamilySearch GEDCOM 5.5.1 Standard."""
          +
          +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."""
          +
          +GEDCOM_5_5_5 = "https://www.gedcom.org/specs/GEDCOM555.zip"
          +"""The gedcom.org GEDCOM 5.5.5 Specification With Annotations."""
          +
          +
          +
          +
          +
          +

          Global variables

          +
          +
          var GEDCOM_5_5
          +
          +

          The official FamilySearch GEDCOM 5.5 Standard.

          +
          +
          var GEDCOM_5_5_1
          +
          +

          The official FamilySearch GEDCOM 5.5.1 Standard.

          +
          +
          var GEDCOM_5_5_1_GEDCOM_L_ADDENDUM
          +
          +

          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.

          +
          +
          +
          +
          +
          +
          +
          +
          + +
          + + + + + \ 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..23ec5a6 --- /dev/null +++ b/docs/gedcom/subparsers/address_structure.html @@ -0,0 +1,198 @@ + + + + + + +gedcom.subparsers.address_structure API documentation + + + + + + + + + + + +
          +
          +
          +

          Module gedcom.subparsers.address_structure

          +
          +
          +

          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.

          +
          + +Expand source code + +
          # -*- coding: utf-8 -*-
          +
          +#  Copyright (C) 2020
          +#
          +#  This file is part of the Python GEDCOM Parser.
          +#
          +#  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.
          +#
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
          +#
          +#  This file is part of the Python GEDCOM Parser.
          +#
          +#  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.
          +#
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
          +
          +"""
          +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.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.elements.element import Element
          +
          +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: Element) -> dict:
          +    """Parses and extracts a `ADDRESS_STRUCTURE` structure.
          +
          +    The `element` should be the parent that contains it.
          +    """
          +    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: Element) ‑> dict +
          +
          +

          Parses and extracts a ADDRESS_STRUCTURE structure.

          +

          The element should be the parent that contains it.

          +
          + +Expand source code + +
          def address_structure(element: Element) -> dict:
          +    """Parses and extracts a `ADDRESS_STRUCTURE` structure.
          +
          +    The `element` should be the parent that contains it.
          +    """
          +    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..78425fb --- /dev/null +++ b/docs/gedcom/subparsers/association_structure.html @@ -0,0 +1,153 @@ + + + + + + +gedcom.subparsers.association_structure API documentation + + + + + + + + + + + +
          +
          +
          +

          Module gedcom.subparsers.association_structure

          +
          +
          +

          Substructure parser for the ASSOCIATION_STRUCTURE record.

          +

          This is anchored by the GEDCOM_TAG_ASSOCIATES tag.

          +
          + +Expand source code + +
          # -*- coding: utf-8 -*-
          +
          +#  Copyright (C) 2020
          +#
          +#  This file is part of the Python GEDCOM Parser.
          +#
          +#  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.
          +#
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
          +
          +"""
          +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.elements.element import Element
          +from gedcom.subparsers.note_structure import note_structure
          +from gedcom.subparsers.source_citation import source_citation
          +
          +
          +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(),
          +        '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: Element) ‑> dict +
          +
          +

          Parses and extracts the ASSOCIATION_STRUCTURE structure.

          +

          The element should contain the GEDCOM_TAG_ASSOCIATES tag.

          +
          + +Expand source code + +
          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(),
          +        '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/element/index.html b/docs/gedcom/subparsers/change_date.html similarity index 58% rename from docs/gedcom/element/index.html rename to docs/gedcom/subparsers/change_date.html index 2875adf..d8c2159 100644 --- a/docs/gedcom/element/index.html +++ b/docs/gedcom/subparsers/change_date.html @@ -4,9 +4,8 @@ -gedcom.element API documentation - +gedcom.subparsers.change_date API documentation + @@ -20,89 +19,107 @@
          -

          Module gedcom.element

          +

          Module gedcom.subparsers.change_date

          -

          Module containing all relevant elements generated by a Parser. -An element represents a line within GEDCOM data.

          +

          Substructure parser for a CHANGE_DATE record.

          +

          This is anchored by the GEDCOM_TAG_CHANGE tag.

          Expand source code
          # -*- coding: utf-8 -*-
           
          -# Python GEDCOM Parser
          +#  Copyright (C) 2020
           #
          -# 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 file is part of the Python GEDCOM Parser.
           #
          -# 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.
          +#  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.
           #
          -# 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
          +#  For more, have a look at the GitHub repository at:
          +#  https://github.com/nickreynke/python-gedcom
           
           """
          -Module containing all relevant elements generated by a `gedcom.parser.Parser`.
          -An element represents a line within GEDCOM data.
          +Substructure parser for a `CHANGE_DATE` record.
          +
          +This is anchored by the `gedcom.tags.GEDCOM_TAG_CHANGE` tag.
           """
           
          -__all__ = [
          -    "element",
          -    "family",
          -    "file",
          -    "individual",
          -    "object",
          -    "root"
          -]
          +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.note_structure import note_structure + + +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': '', + '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
    -

    Sub-modules

    -
    -
    gedcom.element.element
    -
    -

    Base GEDCOM element

    -
    -
    gedcom.element.family
    -
    -

    GEDCOM element consisting of tag GEDCOM_TAG_FAMILY

    -
    -
    gedcom.element.file
    -
    -

    GEDCOM element consisting of tag GEDCOM_TAG_FILE

    -
    -
    gedcom.element.individual
    -
    -

    GEDCOM element consisting of tag GEDCOM_TAG_INDIVIDUAL

    -
    -
    gedcom.element.object
    -
    -

    GEDCOM element consisting of tag GEDCOM_TAG_OBJECT

    -
    -
    gedcom.element.root
    -
    -

    Virtual GEDCOM root element containing all logical records as children

    -
    -
    +

    Functions

    +
    +
    +def change_date(element: Element) ‑> dict +
    +
    +

    Parses and extracts a CHANGE_DATE structure.

    +

    The element should contain the GEDCOM_TAG_CHANGE tag.

    +
    + +Expand source code + +
    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': '',
    +        '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
    +
    +
    +
    @@ -115,17 +132,12 @@

    Index

    • Super-module

    • -
    • Sub-modules

      - 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..cc3d3c7 --- /dev/null +++ b/docs/gedcom/subparsers/child_to_family_link.html @@ -0,0 +1,152 @@ + + + + + + +gedcom.subparsers.child_to_family_link API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.child_to_family_link

      +
      +
      +

      Substructure parser for a CHILD_TO_FAMILY_LINK record.

      +

      This is anchored by the GEDCOM_TAG_FAMILY_CHILD tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.note_structure import note_structure
      +
      +
      +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(),
      +        '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

      +
      + +
      +

      Parses and extracts a CHILD_TO_FAMILY_LINK structure.

      +

      The element should contain the GEDCOM_TAG_FAMILY_CHILD tag.

      +
      + +Expand source code + +
      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(),
      +        '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..0079990 --- /dev/null +++ b/docs/gedcom/subparsers/event_detail.html @@ -0,0 +1,203 @@ + + + + + + +gedcom.subparsers.event_detail API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.event_detail

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.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
      +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: Element) -> dict:
      +    """Parses and extracts a `EVENT_DETAIL` structure.
      +
      +    The `element` should be the parent that contains it.
      +    """
      +    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: Element) ‑> dict +
      +
      +

      Parses and extracts a EVENT_DETAIL structure.

      +

      The element should be the parent that contains it.

      +
      + +Expand source code + +
      def event_detail(element: Element) -> dict:
      +    """Parses and extracts a `EVENT_DETAIL` structure.
      +
      +    The `element` should be the parent that contains it.
      +    """
      +    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..4c044f8 --- /dev/null +++ b/docs/gedcom/subparsers/family_event_detail.html @@ -0,0 +1,146 @@ + + + + + + +gedcom.subparsers.family_event_detail API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.family_event_detail

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.event_detail import event_detail
      +
      +
      +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'] = ''
      +    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: Element) ‑> 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: 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'] = ''
      +    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..ac4f7fe --- /dev/null +++ b/docs/gedcom/subparsers/family_event_structure.html @@ -0,0 +1,151 @@ + + + + + + +gedcom.subparsers.family_event_structure API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.family_event_structure

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: 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():
      +        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: Element) ‑> List[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: 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():
      +        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..8ef9680 --- /dev/null +++ b/docs/gedcom/subparsers/index.html @@ -0,0 +1,212 @@ + + + + + + +gedcom.subparsers API documentation + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers

      +
      +
      +

      Module containing parsers for extracting various substructures from the +different record types as defined in the GEDCOM standard.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""Module containing parsers for extracting various substructures from the
      +different record types as defined in the GEDCOM standard."""
      +
      +__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"
      +]
      +
      +
      +
      +

      Sub-modules

      +
      +
      gedcom.subparsers.address_structure
      +
      +

      Substructure parser for a ADDRESS_STRUCTURE embedded record …

      +
      +
      gedcom.subparsers.association_structure
      +
      +

      Substructure parser for the ASSOCIATION_STRUCTURE record …

      +
      +
      gedcom.subparsers.change_date
      +
      +

      Substructure parser for a CHANGE_DATE record …

      +
      +
      gedcom.subparsers.child_to_family_link
      +
      +

      Substructure parser for a CHILD_TO_FAMILY_LINK record …

      +
      +
      gedcom.subparsers.event_detail
      +
      +

      Substructure parser for a EVENT_DETAIL embedded record …

      +
      +
      gedcom.subparsers.family_event_detail
      +
      +

      Substructure parser for a FAMILY_EVENT_DETAIL emdedded record …

      +
      +
      gedcom.subparsers.family_event_structure
      +
      +

      Substructure parser for a FAMILY_EVENT_STRUCTURE embedded record …

      +
      +
      gedcom.subparsers.individual_attribute_structure
      +
      +

      Substructure parser for the INDIVIDUAL_ATTRIBUTE_STRUCTURE embedded record …

      +
      +
      gedcom.subparsers.individual_event_detail
      +
      +

      Substructure parser for a INDIVIDUAL_EVENT_DETAIL emdedded record …

      +
      +
      gedcom.subparsers.individual_event_structure
      +
      +

      Substructure parser for a INDIVIDUAL_EVENT_STRUCTURE embedded record …

      +
      +
      gedcom.subparsers.lds_individual_ordinance
      +
      +

      Substructure parser for a LDS_INDIVIDUAL_ORDINANCE embedded record …

      +
      +
      gedcom.subparsers.lds_spouse_sealing
      +
      +

      Substructure parser for a LDS_SPOUSE_SEALING embedded record …

      +
      +
      gedcom.subparsers.multimedia_link
      +
      +

      Substructure parser for a MULTIMEDIA_LINK record …

      +
      +
      gedcom.subparsers.note_structure
      +
      +

      Substructure parser for a NOTE_STRUCTURE record …

      +
      +
      gedcom.subparsers.personal_name_pieces
      +
      +

      Substructure parser for a PERSONAL_NAME_PIECES embedded record …

      +
      +
      gedcom.subparsers.personal_name_structure
      +
      +

      Substructure parser for a PERSONAL_NAME_STRUCTURE record …

      +
      +
      gedcom.subparsers.place_structure
      +
      +

      Substructure parser for a PLACE_STRUCTURE record …

      +
      +
      gedcom.subparsers.source_citation
      +
      +

      Substructure parser for a SOURCE_CITATION record …

      +
      +
      gedcom.subparsers.source_repository_citation
      +
      +

      Substructure parser for a SOURCE_REPOSITORY_CITATION record …

      +
      +
      gedcom.subparsers.spouse_to_family_link
      +
      +

      Substructure parser for a SPOUSE_TO_FAMILY_LINK record …

      +
      +
      gedcom.subparsers.user_reference_number
      +
      +

      Parser for a USER_REFERENCE_NUMBER structure …

      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/docs/gedcom/subparsers/individual_attribute_structure.html b/docs/gedcom/subparsers/individual_attribute_structure.html new file mode 100644 index 0000000..873b426 --- /dev/null +++ b/docs/gedcom/subparsers/individual_attribute_structure.html @@ -0,0 +1,156 @@ + + + + + + +gedcom.subparsers.individual_attribute_structure API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.individual_attribute_structure

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: 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():
      +        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: Element) ‑> List[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: 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():
      +        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..0a0ef19 --- /dev/null +++ b/docs/gedcom/subparsers/individual_event_detail.html @@ -0,0 +1,128 @@ + + + + + + +gedcom.subparsers.individual_event_detail API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.individual_event_detail

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.event_detail import event_detail
      +
      +
      +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'] = ''
      +    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: Element) ‑> dict +
      +
      +

      Parses and extracts a INDIVIDUAL_EVENT_DETAIL structure.

      +

      The element should be the parent that contains it.

      +
      + +Expand source code + +
      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'] = ''
      +    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..3c4e792 --- /dev/null +++ b/docs/gedcom/subparsers/individual_event_structure.html @@ -0,0 +1,224 @@ + + + + + + +gedcom.subparsers.individual_event_structure API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.individual_event_structure

      +
      +
      +

      Substructure parser for a INDIVIDUAL_EVENT_STRUCTURE embedded record.

      +

      This is referenced as part of a larger structure so there is no anchor tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: 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():
      +        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: Element) ‑> List[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: 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():
      +        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..5e21630 --- /dev/null +++ b/docs/gedcom/subparsers/lds_individual_ordinance.html @@ -0,0 +1,211 @@ + + + + + + +gedcom.subparsers.lds_individual_ordinance API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.lds_individual_ordinance

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: 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():
      +        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: Element) ‑> List[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: 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():
      +        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..364f884 --- /dev/null +++ b/docs/gedcom/subparsers/lds_spouse_sealing.html @@ -0,0 +1,200 @@ + + + + + + +gedcom.subparsers.lds_spouse_sealing API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.lds_spouse_sealing

      +
      +
      +

      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 + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: 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():
      +        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: Element) ‑> List[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: 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():
      +        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..261821c --- /dev/null +++ b/docs/gedcom/subparsers/multimedia_link.html @@ -0,0 +1,180 @@ + + + + + + +gedcom.subparsers.multimedia_link API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.multimedia_link

      +
      +
      +

      Substructure parser for a MULTIMEDIA_LINK record.

      +

      This is anchored by the GEDCOM_TAG_OBJECT tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +
      +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: 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(),
      +        '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

      +
      + +
      +

      Parse and extract a MULTIMEDIA_LINK structure.

      +

      The element should contain the GEDCOM_TAG_OBJECT tag.

      +
      + +Expand source code + +
      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(),
      +        '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..d136c7f --- /dev/null +++ b/docs/gedcom/subparsers/note_structure.html @@ -0,0 +1,134 @@ + + + + + + +gedcom.subparsers.note_structure API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.note_structure

      +
      +
      +

      Substructure parser for a NOTE_STRUCTURE record.

      +

      This is anchored by the GEDCOM_TAG_NOTE tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +Substructure parser for a `NOTE_STRUCTURE` record.
      +
      +This is anchored by the `gedcom.tags.GEDCOM_TAG_NOTE` tag.
      +"""
      +
      +from gedcom.elements.element import Element
      +
      +
      +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(),
      +        '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: Element) ‑> dict +
      +
      +

      Parse and extract a NOTE_STRUCTURE structure.

      +

      The element should contain the GEDCOM_TAG_NOTE tag.

      +
      + +Expand source code + +
      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(),
      +        '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..6250992 --- /dev/null +++ b/docs/gedcom/subparsers/personal_name_pieces.html @@ -0,0 +1,175 @@ + + + + + + +gedcom.subparsers.personal_name_pieces API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.personal_name_pieces

      +
      +
      +

      Substructure parser for a PERSONAL_NAME_PIECES embedded record.

      +

      This is referenced as part of a larger structure so there is no anchor tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: Element) -> dict:
      +    """Parse and extract a `PERSONAL_NAME_PIECES` structure.
      +
      +    The `element` should be the parent that contains it.
      +    """
      +    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: Element) ‑> dict +
      +
      +

      Parse and extract a PERSONAL_NAME_PIECES structure.

      +

      The element should be the parent that contains it.

      +
      + +Expand source code + +
      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': '',
      +        '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..50e4fba --- /dev/null +++ b/docs/gedcom/subparsers/personal_name_structure.html @@ -0,0 +1,202 @@ + + + + + + +gedcom.subparsers.personal_name_structure API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.personal_name_structure

      +
      +
      +

      Substructure parser for a PERSONAL_NAME_STRUCTURE record.

      +

      This is anchored by the GEDCOM_TAG_NAME tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.personal_name_pieces import personal_name_pieces
      +
      +
      +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': '',
      +        '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: 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'] = []
      +    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: Element) ‑> dict +
      +
      +

      Parse and extract a NAME for a PERSONAL_NAME_STRUCTURE structure.

      +

      The element should contain one of the name tags:

      +

      GEDCOM_TAG_NAME

      +

      GEDCOM_TAG_PHONETIC

      +

      GEDCOM_TAG_ROMANIZED

      +
      + +Expand source code + +
      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': '',
      +        '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: Element) ‑> dict +
      +
      +

      Parse and extract a PERSONAL_NAME_STRUCTURE structure.

      +

      The element should contain the GEDCOM_TAG_NAME tag.

      +
      + +Expand source code + +
      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'] = []
      +    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..67339a7 --- /dev/null +++ b/docs/gedcom/subparsers/place_structure.html @@ -0,0 +1,214 @@ + + + + + + +gedcom.subparsers.place_structure API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.place_structure

      +
      +
      +

      Substructure parser for a PLACE_STRUCTURE record.

      +

      This is anchored by the GEDCOM_TAG_PLACE tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.note_structure import note_structure
      +
      +
      +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(),
      +        '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: Element) ‑> dict +
      +
      +

      Parse and extract a PLACE_STRUCTURE structure.

      +

      The element should contain the GEDCOM_TAG_PLACE tag.

      +
      + +Expand source code + +
      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(),
      +        '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..becd11a --- /dev/null +++ b/docs/gedcom/subparsers/source_citation.html @@ -0,0 +1,224 @@ + + + + + + +gedcom.subparsers.source_citation API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.source_citation

      +
      +
      +

      Substructure parser for a SOURCE_CITATION record.

      +

      This is anchored by the GEDCOM_TAG_SOURCE tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +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: 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(),
      +        '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: Element) ‑> dict +
      +
      +

      Parse and extract a SOURCE_CITATION structure.

      +

      The element should contain the GEDCOM_TAG_SOURCE tag.

      +
      + +Expand source code + +
      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(),
      +        '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..c75cd3e --- /dev/null +++ b/docs/gedcom/subparsers/source_repository_citation.html @@ -0,0 +1,158 @@ + + + + + + +gedcom.subparsers.source_repository_citation API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.source_repository_citation

      +
      +
      +

      Substructure parser for a SOURCE_REPOSITORY_CITATION record.

      +

      This is anchored by the GEDCOM_TAG_REPOSITORY tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.note_structure import note_structure
      +
      +
      +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(),
      +        '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: Element) ‑> dict +
      +
      +

      Parse and extract a SOURCE_REPOSITORY_CITATION structure.

      +

      The element should contain the GEDCOM_TAG_REPOSITORY tag.

      +
      + +Expand source code + +
      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(),
      +        '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..b474ef7 --- /dev/null +++ b/docs/gedcom/subparsers/spouse_to_family_link.html @@ -0,0 +1,132 @@ + + + + + + +gedcom.subparsers.spouse_to_family_link API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.spouse_to_family_link

      +
      +
      +

      Substructure parser for a SPOUSE_TO_FAMILY_LINK record.

      +

      This is anchored by the GEDCOM_TAG_FAMILY_SPOUSE tag.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +from gedcom.subparsers.note_structure import note_structure
      +
      +
      +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(),
      +        '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

      +
      + +
      +

      Parse and extract a SPOUSE_TO_FAMILY_LINK structure.

      +

      The element should contain the GEDCOM_TAG_FAMILY_SPOUSE tag.

      +
      + +Expand source code + +
      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(),
      +        '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..e932ac5 --- /dev/null +++ b/docs/gedcom/subparsers/user_reference_number.html @@ -0,0 +1,136 @@ + + + + + + +gedcom.subparsers.user_reference_number API documentation + + + + + + + + + + + +
      +
      +
      +

      Module gedcom.subparsers.user_reference_number

      +
      +
      +

      Parser for a USER_REFERENCE_NUMBER structure.

      +

      This is anchored by the 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.

      +
      + +Expand source code + +
      # -*- coding: utf-8 -*-
      +
      +#  Copyright (C) 2020
      +#
      +#  This file is part of the Python GEDCOM Parser.
      +#
      +#  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.
      +#
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
      +
      +"""
      +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.elements.element import Element
      +
      +
      +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(),
      +        '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: Element) ‑> dict +
      +
      +

      Parse and extract a USER_REFERENCE_NUMBER structure.

      +

      The element should contain the GEDCOM_TAG_REFERENCE tag.

      +
      + +Expand source code + +
      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(),
      +        '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 9adbfd8..55e8315 100644 --- a/docs/gedcom/tags.html +++ b/docs/gedcom/tags.html @@ -3,17 +3,15 @@ - + gedcom.tags API documentation - - - - - + + + + + - -
      @@ -22,96 +20,411 @@

      Module gedcom.tags

      -

      GEDCOM tags.

      +

      Module containing the standard GEDCOM tags and some of the most common program defined extensions.

      Expand source code
      # -*- coding: utf-8 -*-
       
      -# Python GEDCOM Parser
      +#  Copyright (C) 2020
       #
      -# 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 file is part of the Python GEDCOM Parser.
       #
      -# 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.
      +#  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.
       #
      -# 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
      +#  For more, have a look at the GitHub repository at:
      +#  https://github.com/nickreynke/python-gedcom
       
       """
      -GEDCOM tags.
      +Module containing the standard GEDCOM tags and some of the most 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`
       
      -Relationship to a mother."""
      +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.
      +
      +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`
      @@ -123,93 +436,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_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`)"""
      @@ -217,60 +979,384 @@

      Module gedcom.tags

      Global variables

      +
      var GEDCOM_PROGRAM_DEFINED_TAG_ADDRESSE
      +
      +

      Value: _NAME

      +

      Name of addresse in a GEDCOM_TAG_ADDRESS structure.

      +

      5.5.1 GEDCOM-L Addendum.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_ADMINISTRATIVE_ID
      +
      +

      Value: _AIDN

      +

      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.

      +

      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.

      +

      5.5.1 GEDCOM-L Addendum.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_GOVERNMENT_TYPE
      +
      +

      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.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_HOME_PERSON
      +
      +

      Value: _HME

      +

      Home person in the tree.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_LOCATION
      +
      +

      Value: _LOC

      +

      Location data record.

      +

      5.5.1 GEDCOM-L Addendum.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_MAIDENHEAD
      +
      +

      Value: _MAIDENHEAD

      +

      The maidenhead code.

      +

      5.5.1 GEDCOM-L Addendum.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_MEDICAL
      +
      +

      Value: _MDCL

      +

      Medical information about an individual.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_MILITARY
      +
      +

      Value: _MILT

      +

      A military related event in the individuals life.

      var GEDCOM_PROGRAM_DEFINED_TAG_MREL

      Value: _MREL

      -

      Relationship to a mother.

      +

      Type of relationship between child and the mother in a family.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_PHOTO
      +
      +

      Value: _PHOTO

      +

      Used by some programs to identify the primary multimedia object for an +individual, the same as GEDCOM_PROGRAM_DEFINED_TAG_PRIMARY.

      +
      +
      var GEDCOM_PROGRAM_DEFINED_TAG_POSTAL_CODE
      +
      +

      Value: _POST

      +

      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.

      +
      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.

      +
      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.

      +

      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

      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.

      +
      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.

      +

      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.

      +

      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: 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
      @@ -282,94 +1368,536 @@

      Global variables

      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.

      +

      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.

      +
      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.

      +
      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.

      +

      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.

      +
      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.

      +
      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.

      +
      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.

      +

      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.

      +

      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.

      +

      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.

      +
      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.

      +
      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.

      +
      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.

      +
      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.

      +
      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.

      +
      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.

      +
      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)

      +
      +
      var GEDCOM_TAG_WWW
      +
      +

      Value: WWW

      +

      World Wide Web home page.

      +
      @@ -390,41 +1918,177 @@

      Index

    • Global variables

+ + \ No newline at end of file diff --git a/gedcom/__init__.py b/gedcom/__init__.py index 386a74b..f9327e0 100644 --- a/gedcom/__init__.py +++ b/gedcom/__init__.py @@ -1,29 +1,15 @@ # -*- coding: utf-8 -*- -# Python GEDCOM Parser +# Copyright (C) 2020 # -# 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 file is part of the Python GEDCOM Parser. # -# 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. +# 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. # -# 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 +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom """ A Python module for parsing, analyzing, and manipulating GEDCOM files. @@ -33,9 +19,15 @@ __all__ = [ # Subpackages - "element", + "elements", + "subparsers", # Modules + "errors", "helpers", + "detect", "parser", + "reader", + "records", + "standards", "tags" ] diff --git a/gedcom/detect.py b/gedcom/detect.py new file mode 100644 index 0000000..ab506a1 --- /dev/null +++ b/gedcom/detect.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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 + +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. + """ + 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: 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) + + # 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: 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 + 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) + + probed_version = gedcom_version + + # UTF was added in the 5.5.1 specification + if gedcom_version == '5.5' and 'utf' in codec: + probed_version = gedcom_version + + return probed_version, gedcom_version, gedcom_format diff --git a/gedcom/element/__init__.py b/gedcom/element/__init__.py deleted file mode 100644 index 34eaac5..0000000 --- a/gedcom/element/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- - -# Python GEDCOM Parser -# -# 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 all relevant elements generated by a `gedcom.parser.Parser`. -An element represents a line within GEDCOM data. -""" - -__all__ = [ - "element", - "family", - "file", - "individual", - "object", - "root" -] diff --git a/gedcom/element/family.py b/gedcom/element/family.py deleted file mode 100644 index c91b5a9..0000000 --- a/gedcom/element/family.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- - -# Python GEDCOM Parser -# -# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_FAMILY`""" - -from gedcom.element.element import Element -import gedcom.tags - - -class NotAnActualFamilyError(Exception): - pass - - -class FamilyElement(Element): - - def get_tag(self): - return gedcom.tags.GEDCOM_TAG_FAMILY diff --git a/gedcom/element/file.py b/gedcom/element/file.py deleted file mode 100644 index d02e8eb..0000000 --- a/gedcom/element/file.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- - -# Python GEDCOM Parser -# -# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_FILE`""" - -from gedcom.element.element import Element -import gedcom.tags - - -class NotAnActualFileError(Exception): - pass - - -class FileElement(Element): - - def get_tag(self): - return gedcom.tags.GEDCOM_TAG_FILE diff --git a/gedcom/element/individual.py b/gedcom/element/individual.py deleted file mode 100644 index da61d08..0000000 --- a/gedcom/element/individual.py +++ /dev/null @@ -1,453 +0,0 @@ -# -*- coding: utf-8 -*- - -# Python GEDCOM Parser -# -# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_INDIVIDUAL`""" - -import re as regex -from gedcom.element.element import Element -from gedcom.helpers import deprecated -import gedcom.tags - - -class NotAnActualIndividualError(Exception): - pass - - -class IndividualElement(Element): - - def get_tag(self): - return gedcom.tags.GEDCOM_TAG_INDIVIDUAL - - 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: - return True - - return False - - def is_child(self): - """Checks if this element is a child of a family - :rtype: bool - """ - found_child = False - - for child in self.get_child_elements(): - if child.get_tag() == gedcom.tags.GEDCOM_TAG_FAMILY_CHILD: - found_child = True - - return found_child - - def is_private(self): - """Checks if this individual is marked private - :rtype: bool - """ - for child in self.get_child_elements(): - if child.get_tag() == gedcom.tags.GEDCOM_TAG_PRIVATE: - private = child.get_value() - if private == 'Y': - return True - - return False - - def get_name(self): - """Returns an individual's names as a tuple: (`str` given_name, `str` surname) - :rtype: tuple - """ - 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. - found_given_name = False - found_surname_name = False - - for child in self.get_child_elements(): - if child.get_tag() == gedcom.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() != "": - name = child.get_value().split('/') - - if len(name) > 0: - given_name = name[0].strip() - if len(name) > 1: - surname = name[1].strip() - - return given_name, surname - - for childOfChild in child.get_child_elements(): - - if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_GIVEN_NAME: - given_name = childOfChild.get_value() - found_given_name = True - - if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_SURNAME: - surname = childOfChild.get_value() - found_surname_name = True - - if found_given_name and found_surname_name: - return given_name, surname - - # If we reach here we are probably returning empty strings - 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] - - def surname_match(self, surname_to_match): - """Matches a string with the surname of an individual - :type surname_to_match: str - :rtype: bool - """ - (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 - ::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 - """ - (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 - """ - gender = "" - - for child in self.get_child_elements(): - if child.get_tag() == gedcom.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) - :rtype: tuple - """ - date = "" - place = "" - 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 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()) - - return date, place, sources - - def get_birth_year(self): - """Returns the birth year of a person in integer format - :rtype: int - """ - 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() - date = date_split[len(date_split) - 1] - - if date == "": - return -1 - try: - return int(date) - 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 - """ - date = "" - place = "" - 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()) - - return date, place, sources - - def get_death_year(self): - """Returns the death year of a person in integer format - :rtype: int - """ - 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() - date = date_split[len(date_split) - 1] - - if date == "": - return -1 - try: - return int(date) - except ValueError: - return -1 - - @deprecated - def get_burial(self): - """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 - """ - date = "" - place = "" - 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 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()) - - 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) - ::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 - """ - census = [] - - for child in self.get_child_elements(): - if child.get_tag() == gedcom.tags.GEDCOM_TAG_CENSUS: - - date = '' - place = '' - sources = [] - - 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()) - - census.append((date, place, sources)) - - 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 - """ - 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() - - return date - - def get_occupation(self): - """Returns the occupation of a person - :rtype: str - """ - occupation = "" - - for child in self.get_child_elements(): - if child.get_tag() == gedcom.tags.GEDCOM_TAG_OCCUPATION: - occupation = child.get_value() - - 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 - """ - 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 - """ - birth_year = self.get_birth_year() - - if from_year <= birth_year <= to_year: - return True - - 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 - """ - 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 - """ - death_year = self.get_death_year() - - if from_year <= death_year <= to_year: - return True - - return False - - def criteria_match(self, 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] - Match a person with [name] in any part of the `surname`. - given_name=[given_name] - Match a person with [given_name] in any part of the given `given_name`. - birth=[year] - 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 - """ - - # Check if criteria is a valid criteria and can be split by `:` and `=` characters - try: - for criterion in criteria.split(':'): - criterion.split('=') - except ValueError: - return False - - match = True - - for criterion in criteria.split(':'): - key, value = criterion.split('=') - - if key == "surname" and not self.surname_match(value): - match = False - elif key == "name" and not self.given_name_match(value): - match = False - elif key == "birth": - - try: - year = int(value) - if not self.birth_year_match(year): - match = False - except ValueError: - match = False - - elif key == "birth_range": - - try: - from_year, to_year = value.split('-') - from_year = int(from_year) - to_year = int(to_year) - if not self.birth_range_match(from_year, to_year): - match = False - except ValueError: - match = False - - elif key == "death": - - try: - year = int(value) - if not self.death_year_match(year): - match = False - except ValueError: - match = False - - elif key == "death_range": - - try: - from_year, to_year = value.split('-') - from_year = int(from_year) - to_year = int(to_year) - if not self.death_range_match(from_year, to_year): - match = False - except ValueError: - match = False - - return match diff --git a/gedcom/element/object.py b/gedcom/element/object.py deleted file mode 100644 index 0090e2f..0000000 --- a/gedcom/element/object.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- - -# Python GEDCOM Parser -# -# 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 consisting of tag `gedcom.tags.GEDCOM_TAG_OBJECT`""" - -from gedcom.element.element import Element -import gedcom.tags - - -class NotAnActualObjectError(Exception): - pass - - -class ObjectElement(Element): - - def is_object(self): - """Checks if this element is an actual object - :rtype: bool - """ - return self.get_tag() == gedcom.tags.GEDCOM_TAG_OBJECT diff --git a/gedcom/element/root.py b/gedcom/element/root.py deleted file mode 100644 index 826c378..0000000 --- a/gedcom/element/root.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- - -# Python GEDCOM Parser -# -# 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 - -"""Virtual GEDCOM root element containing all logical records as children""" - -from gedcom.element.element import Element - - -class RootElement(Element): - """Virtual GEDCOM root element containing all logical records as children""" - - def __init__(self, level=-1, pointer="", tag="ROOT", value="", crlf="\n", multi_line=True): - super(RootElement, self).__init__(level, pointer, tag, value, crlf, multi_line) diff --git a/gedcom/elements/__init__.py b/gedcom/elements/__init__.py new file mode 100644 index 0000000..cf8ca78 --- /dev/null +++ b/gedcom/elements/__init__.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +Module containing all relevant elements generated by a `gedcom.parser.Parser`. +An element represents a line within GEDCOM data. +""" + +__all__ = [ + # Modules + "element", + "family", + "header", + "individual", + "note", + "object", + "repository", + "root", + "source", + "submission", + "submitter", + # Constants + "ELEMENT_TYPES" +] + +from gedcom import tags +from gedcom.elements.family import FamilyElement +from gedcom.elements.header import HeaderElement +from gedcom.elements.individual import IndividualElement +from gedcom.elements.note import NoteElement +from gedcom.elements.object import ObjectElement +from gedcom.elements.repository import RepositoryElement +from gedcom.elements.source import SourceElement +from gedcom.elements.submission import SubmissionElement +from gedcom.elements.submitter import SubmitterElement + +ELEMENT_TYPES = { + 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 +} diff --git a/gedcom/element/element.py b/gedcom/elements/element.py similarity index 59% rename from gedcom/element/element.py rename to gedcom/elements/element.py index 3428e3c..74d853a 100644 --- a/gedcom/element/element.py +++ b/gedcom/elements/element.py @@ -1,43 +1,31 @@ # -*- coding: utf-8 -*- -# Python GEDCOM Parser +# Copyright (C) 2020 # -# 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 file is part of the Python GEDCOM Parser. # -# 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. +# 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. # -# 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 +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom """ -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 +50,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 +66,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 +106,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 +126,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,79 +167,91 @@ 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.file import FileElement - from gedcom.element.individual import IndividualElement - from gedcom.element.object import ObjectElement + from gedcom.elements.family import FamilyElement + from gedcom.elements.individual import IndividualElement + from gedcom.elements.note import NoteElement + from gedcom.elements.object import ObjectElement + from gedcom.elements.repository import RepositoryElement + from gedcom.elements.source import SourceElement + from gedcom.elements.submitter import SubmitterElement + from gedcom.elements.submission import SubmissionElement + from gedcom.elements.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) + 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) 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) + 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) + 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()) @@ -287,7 +275,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/elements/family.py b/gedcom/elements/family.py new file mode 100644 index 0000000..1b7b951 --- /dev/null +++ b/gedcom/elements/family.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `FAM_RECORD` family record identified by the +`gedcom.tags.GEDCOM_TAG_FAMILY` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.family_event_structure import parse_family_event_structure +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.lds_spouse_sealing import parse_lds_spouse_sealing +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_source_citation +from gedcom.subparsers.multimedia_link import parse_multimedia_link +from gedcom.subparsers.user_reference_number import parse_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) -> str: + return tags.GEDCOM_TAG_FAMILY + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + record = { + 'key_to_family': self.get_pointer(), + 'restriction': '', + 'events': parse_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 = parse_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(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_source_citation(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_OBJECT: + record['media'].append(parse_multimedia_link(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_REFERENCE: + record['references'].append(parse_user_reference_number(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_CHANGE: + record['change_date'] = parse_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/elements/header.py b/gedcom/elements/header.py new file mode 100644 index 0000000..b96f5c1 --- /dev/null +++ b/gedcom/elements/header.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `HEADER` header record identified by the +`gedcom.tags.GEDCOM_TAG_HEADER` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.address_structure import parse_address_structure +from gedcom.subparsers.note_structure import parse_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) -> str: + return tags.GEDCOM_TAG_HEADER + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + 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'] = parse_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(parse_note_structure(child)) + + return record diff --git a/gedcom/elements/individual.py b/gedcom/elements/individual.py new file mode 100644 index 0000000..0881bee --- /dev/null +++ b/gedcom/elements/individual.py @@ -0,0 +1,525 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `INDIVIDUAL_RECORD` individual record identified by the +`gedcom.tags.GEDCOM_TAG_INDIVIDUAL` tag. +""" + +from typing import Tuple, List +import re as regex + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.personal_name_structure import parse_personal_name_structure +from gedcom.subparsers.individual_event_structure import parse_individual_event_structure +from gedcom.subparsers.individual_attribute_structure import parse_individual_attribute_structure +from gedcom.subparsers.lds_individual_ordinance import parse_lds_individual_ordinance +from gedcom.subparsers.child_to_family_link import parse_child_to_family_link +from gedcom.subparsers.spouse_to_family_link import parse_spouse_to_family_link +from gedcom.subparsers.association_structure import parse_association_structure +from gedcom.subparsers.user_reference_number import parse_user_reference_number +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_source_citation +from gedcom.subparsers.multimedia_link import parse_multimedia_link +from gedcom.helpers import deprecated + +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) -> str: + return tags.GEDCOM_TAG_INDIVIDUAL + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + record = { + 'key_to_individual': self.get_pointer(), + 'restriction': '', + 'names': [], + 'sex': 'U', + 'events': parse_individual_event_structure(self), + 'attributes': parse_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 = parse_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(parse_personal_name_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD: + record['child_to_family'].append(parse_child_to_family_link(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_FAMILY_SPOUSE: + record['spouse_to_family'].append(parse_spouse_to_family_link(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_NOTE: + record['notes'].append(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_source_citation(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_MEDIA: + record['media'].append(parse_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(parse_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(parse_user_reference_number(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_CHANGE: + record['changed'] = parse_change_date(child) + + return record + + 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: + return True + + return False + + def is_child(self) -> bool: + """Checks if this element is a child of a family. + """ + found_child = False + + for child in self.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_FAMILY_CHILD: + found_child = True + + return found_child + + 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: + private = child.get_value() + if private == 'Y': + return True + + return False + + def get_name(self) -> Tuple[str, str]: + """Returns an individual's names as a tuple: (`str` given_name, `str` surname) + """ + given_name = "" + surname = "" + + # 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() == 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() != "": + name = child.get_value().split('/') + + if len(name) > 0: + given_name = name[0].strip() + if len(name) > 1: + surname = name[1].strip() + + return given_name, surname + + for gchild in child.get_child_elements(): + + if gchild.get_tag() == tags.GEDCOM_TAG_GIVEN_NAME: + given_name = gchild.get_value() + found_given_name = True + + if gchild.get_tag() == tags.GEDCOM_TAG_SURNAME: + surname = gchild.get_value() + found_surname_name = True + + if found_given_name and found_surname_name: + return given_name, surname + + # If we reach here we are probably returning empty strings + return given_name, surname + + 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: 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: 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 + """ + return self.given_name_match(name) + + 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) -> str: + """Returns the gender of a person in string format. + """ + gender = "" + + for child in self.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_SEX: + gender = child.get_value() + + return gender + + 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) + """ + date = "" + place = "" + sources = [] + + for child in self.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_BIRTH: + 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 + + def get_birth_year(self) -> int: + """Returns the birth year of a person in integer format. + """ + date = "" + + for child in self.get_child_elements(): + 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 == "": + return -1 + try: + return int(date) + except ValueError: + return -1 + + 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 = "" + sources = [] + + for child in self.get_child_elements(): + 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 + + def get_death_year(self) -> int: + """Returns the death year of a person in integer format. + """ + date = "" + + for child in self.get_child_elements(): + 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 == "": + return -1 + try: + return int(date) + except ValueError: + return -1 + + @deprecated + 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 + """ + self.get_burial_data() + + 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 = "" + sources = [] + + for child in self.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_BURIAL: + 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 + + @deprecated + 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 + """ + self.get_census_data() + + 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 = [] + + for child in self.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_CENSUS: + + date = '' + place = '' + sources = [] + + 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()) + + census.append((date, place, sources)) + + return census + + def get_last_change_date(self) -> str: + """Returns the date of when the person data was last changed formatted as a string. + """ + date = "" + + for child in self.get_child_elements(): + 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 + + def get_occupation(self) -> str: + """Returns the occupation of a person. + """ + occupation = "" + + for child in self.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_OCCUPATION: + occupation = child.get_value() + + return occupation + + 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: int, to_year: int) -> bool: + """Checks if the birth year of a person lies within the given range. + """ + birth_year = self.get_birth_year() + + if from_year <= birth_year <= to_year: + return True + + return False + + 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: int, to_year: int) -> bool: + """Checks if the death year of a person lies within the given range. + """ + death_year = self.get_death_year() + + if from_year <= death_year <= to_year: + return True + + return False + + 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: + + surname=[name] + Match a person with [name] in any part of the `surname`. + given_name=[given_name] + Match a person with [given_name] in any part of the given `given_name`. + birth=[year] + 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]. + """ + + # Check if criteria is a valid criteria and can be split by `:` and `=` characters + try: + for criterion in criteria.split(':'): + criterion.split('=') + except ValueError: + return False + + match = True + + for criterion in criteria.split(':'): + key, value = criterion.split('=') + + if key == "surname" and not self.surname_match(value): + match = False + elif key == "name" and not self.given_name_match(value): + match = False + elif key == "birth": + + try: + year = int(value) + if not self.birth_year_match(year): + match = False + except ValueError: + match = False + + elif key == "birth_range": + + try: + from_year, to_year = value.split('-') + from_year = int(from_year) + to_year = int(to_year) + if not self.birth_range_match(from_year, to_year): + match = False + except ValueError: + match = False + + elif key == "death": + + try: + year = int(value) + if not self.death_year_match(year): + match = False + except ValueError: + match = False + + elif key == "death_range": + + try: + from_year, to_year = value.split('-') + from_year = int(from_year) + to_year = int(to_year) + if not self.death_range_match(from_year, to_year): + match = False + except ValueError: + match = False + + return match diff --git a/gedcom/elements/note.py b/gedcom/elements/note.py new file mode 100644 index 0000000..37288f6 --- /dev/null +++ b/gedcom/elements/note.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `NOTE_RECORD` note record identified by the +`gedcom.tags.GEDCOM_TAG_NOTE` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.source_citation import parse_source_citation +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.user_reference_number import parse_user_reference_number + + +class NoteElement(Element): + """Element associated with a `NOTE_RECORD`""" + + def get_tag(self) -> str: + return tags.GEDCOM_TAG_NOTE + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + 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(parse_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(parse_source_citation(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_CHANGE: + record['change_date'] = parse_change_date(child) + + return record diff --git a/gedcom/elements/object.py b/gedcom/elements/object.py new file mode 100644 index 0000000..779c748 --- /dev/null +++ b/gedcom/elements/object.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `MULTIMEDIA_RECORD` media record identified by the +`gedcom.tags.GEDCOM_TAG_OBJECT` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_source_citation +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.user_reference_number import parse_user_reference_number + + +class ObjectElement(Element): + """Element associated with a `MULTIMEDIA_RECORD`""" + + def get_tag(self) -> str: + return tags.GEDCOM_TAG_OBJECT + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + 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(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_source_citation(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_REFERENCE: + record['references'].append(parse_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'] = parse_change_date(child) + + return record diff --git a/gedcom/elements/repository.py b/gedcom/elements/repository.py new file mode 100644 index 0000000..8820ff9 --- /dev/null +++ b/gedcom/elements/repository.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `REPOSITORY_RECORD` repository record identified by the +`gedcom.tags.GEDCOM_TAG_REPOSITORY` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.address_structure import parse_address_structure +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.user_reference_number import parse_user_reference_number + + +class RepositoryElement(Element): + """Element associated with a `REPOSITORY_RECORD`""" + + def get_tag(self) -> str: + return tags.GEDCOM_TAG_REPOSITORY + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + 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'] = parse_address_structure(self) + continue + + if child.get_tag() == tags.GEDCOM_TAG_NOTE: + record['notes'].append(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_REFERENCE: + record['references'].append(parse_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'] = parse_change_date(child) + + return record diff --git a/gedcom/elements/root.py b/gedcom/elements/root.py new file mode 100644 index 0000000..afe33ef --- /dev/null +++ b/gedcom/elements/root.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +"""Virtual GEDCOM root element containing all logical records as children""" + +from gedcom.elements.element import Element + + +class RootElement(Element): + """Virtual GEDCOM root element containing all logical records as children.""" + + 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/elements/source.py b/gedcom/elements/source.py new file mode 100644 index 0000000..11b247e --- /dev/null +++ b/gedcom/elements/source.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `SOURCE_RECORD` source record identified by the +`gedcom.tags.GEDCOM_TAG_SOURCE` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.multimedia_link import parse_multimedia_link +from gedcom.subparsers.user_reference_number import parse_user_reference_number +from gedcom.subparsers.source_repository_citation import parse_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) -> str: + return tags.GEDCOM_TAG_SOURCE + + def get_record(self) -> dict: + """Parse and return the full record in dictionary format. + """ + 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(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_OBJECT: + record['media'].append(parse_multimedia_link(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_REPOSITORY: + record['repository'] = parse_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(parse_note_structure(gchild)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_REFERENCE: + record['references'].append(parse_user_reference_number(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_CHANGE: + record['change_date'] = parse_change_date(child) + continue + + return record diff --git a/gedcom/elements/submission.py b/gedcom/elements/submission.py new file mode 100644 index 0000000..95f8084 --- /dev/null +++ b/gedcom/elements/submission.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `SUBMISSION_RECORD` submission record identified by the +`gedcom.tags.GEDCOM_TAG_SUBMISSION` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.change_date import parse_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) -> str: + return tags.GEDCOM_TAG_SUBMISSION + + def get_record(self) -> dict: + """Parse and return the record in dictionary format + """ + 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(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_CHANGE: + record['change_date'] = parse_change_date(child) + + return record diff --git a/gedcom/elements/submitter.py b/gedcom/elements/submitter.py new file mode 100644 index 0000000..ca07891 --- /dev/null +++ b/gedcom/elements/submitter.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +GEDCOM element for a `SUBMITTER_RECORD` submitter record identified by the +`gedcom.tags.GEDCOM_TAG_SUBMITTER` tag. +""" + +import gedcom.tags as tags +from gedcom.elements.element import Element +from gedcom.subparsers.address_structure import parse_address_structure +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.change_date import parse_change_date +from gedcom.subparsers.multimedia_link import parse_multimedia_link + + +class SubmitterElement(Element): + """Element associated with a `SUBMITTER_RECORD`""" + + def get_tag(self) -> str: + return tags.GEDCOM_TAG_SUBMITTER + + def get_record(self) -> dict: + """Parse and return the record in dictionary format + """ + 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'] = parse_address_structure(self) + continue + + if child.get_tag() == tags.GEDCOM_TAG_NOTE: + record['notes'].append(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_OBJECT: + record['media'].append(parse_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'] = parse_change_date(child) + + return record diff --git a/gedcom/errors.py b/gedcom/errors.py new file mode 100644 index 0000000..ed008f3 --- /dev/null +++ b/gedcom/errors.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +Module containing the exception handling classes. +""" + +ERROR_LINE_VIOLATION_TEMPLATE = "Line <{0}:{1}> of document violates GEDCOM format {2}\nSee: {3}" + + +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 that version requires the + parser to reject it. + """ + + +class GedcomFormatUnsupportedError(Exception): + """Raised if the GEDCOM format is not recognized by the + 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. + """ + + +class NotAnActualIndividualError(Exception): + """Raised if element does not appear to be an `INDIVIDUAL_RECORD`""" + + +class NotAnActualFamilyError(Exception): + """Raised if element does not appear to be a `FAM_RECORD`""" + + +class NotAnActualSourceError(Exception): + """Raised if element does not appear to be a `SOURCE_RECORD`""" + + +class NotAnActualRepositoryError(Exception): + """Raised if element does not appear to be a `REPOSITORY_RECORD`""" + + +class NotAnActualNoteError(Exception): + """Raised if element does not appear to be a `NOTE_RECORD`""" + + +class NotAnActualObjectError(Exception): + """Raised if element does not appear to be a `MULTIMEDIA_RECORD`""" + + +class NotAnActualHeaderError(Exception): + """Raised if element does not appear to be a `HEADER`""" + + +class NotAnActualSubmitterError(Exception): + """Raised if element does not appear to be a `SUBMITTER_RECORD`""" + + +class NotAnActualSubmissionError(Exception): + """Raised if element does not appear to be a `SUBMISSION_RECORD`""" diff --git a/gedcom/gedcom.md b/gedcom/gedcom.md index 56076be..c953acc 100644 --- a/gedcom/gedcom.md +++ b/gedcom/gedcom.md @@ -17,14 +17,15 @@ simply append the `--pre` option to `pip3`: `pip3 install python-gedcom --pre` * `gedcom.parser.Parser`: The actual GEDCOM parser. * `gedcom.tags`: GEDCOM tags like `gedcom.tags.GEDCOM_TAG_INDIVIDUAL` (`INDI`) or `gedcom.tags.GEDCOM_TAG_NAME` (`NAME`) -* `gedcom.element`: Contains all relevant elements generated by a `gedcom.parser.Parser`. +* `gedcom.elements`: Contains all relevant elements generated by a `gedcom.parser.Parser`. +* `gedcom.subparsers`: Module containing parsers for extracting various substructures from the different record types as defined in the GEDCOM standard. ## Example usage When successfully installed you may import the `gedcom` package and use it like so: ```python -from gedcom.element.individual import IndividualElement +from gedcom.elements.individual import IndividualElement from gedcom.parser import Parser # Path to your ".ged" file @@ -82,6 +83,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/helpers.py b/gedcom/helpers.py index 2e2a465..3e0e0d9 100644 --- a/gedcom/helpers.py +++ b/gedcom/helpers.py @@ -1,29 +1,15 @@ # -*- coding: utf-8 -*- -# Python GEDCOM Parser +# Copyright (C) 2020 # -# 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 file is part of the Python GEDCOM Parser. # -# 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. +# 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. # -# 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 +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom """ Helper methods. diff --git a/gedcom/parser.py b/gedcom/parser.py index 473ad9e..207d825 100644 --- a/gedcom/parser.py +++ b/gedcom/parser.py @@ -1,60 +1,55 @@ # -*- coding: utf-8 -*- -# Python GEDCOM Parser +# Copyright (C) 2020 # -# 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 file is part of the Python GEDCOM Parser. # -# 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. +# 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. # -# 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 +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom """ -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 stdout from sys import version_info -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.object import ObjectElement -from gedcom.element.root import RootElement -import gedcom.tags +from typing import Tuple, List, IO -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 +import gedcom.tags as tags +import gedcom.standards as standards +from gedcom.detect import get_encoding, get_version +from gedcom.elements import ELEMENT_TYPES +from gedcom.elements.element import Element +from gedcom.elements.family import FamilyElement +from gedcom.elements.individual import IndividualElement +from gedcom.elements.root import RootElement -class GedcomFormatViolationError(Exception): - pass +from gedcom.errors import ERROR_LINE_VIOLATION_TEMPLATE +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 + +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(object): - """Parses and manipulates GEDCOM 5.5 format data +class Parser: + """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. @@ -70,35 +65,36 @@ 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. """ 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. 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 """ 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): - """Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file + def get_element_dictionary(self) -> dict: + """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. @@ -106,46 +102,51 @@ 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 = { - 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 - 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. """ - 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): - """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() @@ -154,24 +155,18 @@ 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 @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. @@ -190,43 +185,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_LINE_VIOLATION_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 +233,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 ELEMENT_TYPES: + element = ELEMENT_TYPES[tag](level, pointer, tag, value, crlf, multi_line=False) else: element = Element(level, pointer, tag, value, crlf, multi_line=False) @@ -266,10 +255,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(): @@ -277,81 +264,74 @@ 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): 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 - 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 = [] 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: - for childOfChild in child.get_child_elements(): - if childOfChild.get_tag() == gedcom.tags.GEDCOM_TAG_DATE: - date = childOfChild.get_value().split()[-1] + if child.get_tag() == tags.GEDCOM_TAG_MARRIAGE: + 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( - "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) 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( - "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) @@ -360,20 +340,19 @@ def marriage_range_match(self, individual, from_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 + def get_families(self, individual: IndividualElement, + family_type: str = tags.GEDCOM_TAG_FAMILY_SPOUSE) -> List[FamilyElement]: + """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. + Optional argument `family_type` can be used to return specific subsets: - :type individual: IndividualElement - :type family_type: str - :rtype: list of FamilyElement + `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( - "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 = [] @@ -388,19 +367,19 @@ def get_families(self, individual, family_type=gedcom.tags.GEDCOM_TAG_FAMILY_SPO return families - def get_ancestors(self, individual, ancestor_type="ALL"): - """Return elements corresponding to ancestors of an individual + 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: - Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be - used to specify only natural (genetic) ancestors. + "ALL": Default, returns all ancestors. - :type individual: IndividualElement - :type ancestor_type: str - :rtype: list of Element + "NAT": Return only natural (genetic) 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 ) parents = self.get_parents(individual, ancestor_type) @@ -412,49 +391,53 @@ 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 + def get_parents(self, individual: IndividualElement, + parent_type: str = "ALL") -> List[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. + Optional argument `parent_type` can be used to return specific subsets: - :type individual: IndividualElement - :type parent_type: str - :rtype: list of IndividualElement + "ALL": Default, returns all parents. + + "NAT": Return only natural (genetic) parents. """ 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") 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." % gedcom.tags.GEDCOM_TAG_INDIVIDUAL + "Operation only valid for elements with %s tag." % tags.GEDCOM_TAG_INDIVIDUAL ) if not path: @@ -462,33 +445,34 @@ 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 + "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children) """ 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 = [] @@ -496,19 +480,19 @@ def get_family_members(self, family, members_type=FAMILY_MEMBERS_TYPE_ALL): 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()]) @@ -517,9 +501,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'' @@ -533,13 +517,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 new file mode 100644 index 0000000..d6dff4d --- /dev/null +++ b/gedcom/reader.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +Module containing a `gedcom.reader.Reader` with higher order methods than the +base `gedcom.parser.Parser` for extracting records as structured data. +""" + +from typing import Union + +from gedcom.parser import Parser +from gedcom.elements.header import HeaderElement +from gedcom.elements.individual import IndividualElement +from gedcom.elements.family import FamilyElement +from gedcom.elements.note import NoteElement +from gedcom.elements.object import ObjectElement +from gedcom.elements.source import SourceElement +from gedcom.elements.submission import SubmissionElement +from gedcom.elements.submitter import SubmitterElement +from gedcom.elements.repository import RepositoryElement + +RECORD_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 around the core `gedcom.parser.Parser` with methods for + extracting parsed records as structured data. + """ + + 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 = {} + + for element in self.get_root_child_elements(): + if isinstance(element, RECORD_TYPES[record_type]): + record = element.get_record() + if return_output_as_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 return_output_as_list: + return record_list + + return record_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 return_entries_as_list: + record_dict.update({key: []}) + else: + record_dict.update({key: {}}) + + for element in self.get_root_child_elements(): + for key in RECORD_TYPES: + if isinstance(element, RECORD_TYPES[key]): + record = element.get_record() + if return_entries_as_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/records.py b/gedcom/records.py new file mode 100644 index 0000000..e7eaa50 --- /dev/null +++ b/gedcom/records.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +"""Module containing the standard GEDCOM record types recognized by the +GEDCOM `gedcom.reader.Reader`.""" + + +GEDCOM_RECORD_FAMILY = "family" +"""Value: `family` + +Identifies the `FAM_RECORD` record type.""" + +GEDCOM_RECORD_HEADER = "header" +"""Value: `header` + +Identifies the `HEADER` record type.""" + +GEDCOM_RECORD_INDIVIDUAL = "individual" +"""Value: `individual` + +Identifies the `INDIVIDUAL_RECORD` record type.""" + +GEDCOM_RECORD_NOTE = "note" +"""Value: `note` + +Identifies the `NOTE_RECORD` record type.""" + +GEDCOM_RECORD_SOURCE = "source" +"""Value: `source` + +Identifies the `SOURCE_RECORD` record type.""" + +GEDCOM_RECORD_REPOSITORY = "repository" +"""Value: `repository` + +Identifies the `REPOSITORY_RECORD` record type.""" + +GEDCOM_RECORD_SUBMISSION = "submission" +"""Value: `submission` + +Identifies the `SUBMISSION_RECORD` record type.""" + +GEDCOM_RECORD_SUBMITTER = "submitter" +"""Value: `submitter` + +Identifies the `SUBMITTER_RECORD` record type.""" diff --git a/gedcom/standards.py b/gedcom/standards.py new file mode 100644 index 0000000..8138122 --- /dev/null +++ b/gedcom/standards.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +"""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.""" + +GEDCOM_5_5_1 = "https://edge.fscdn.org/assets/img/documents/" + \ + "ged551-5bac5e57fe88dd37df0e153d9c515335.pdf" +"""The official FamilySearch GEDCOM 5.5.1 Standard.""" + +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.""" + +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/__init__.py b/gedcom/subparsers/__init__.py new file mode 100644 index 0000000..edad1d2 --- /dev/null +++ b/gedcom/subparsers/__init__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +"""Module containing parsers for extracting various substructures from the +different record types as defined in the GEDCOM standard.""" + +__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..b487397 --- /dev/null +++ b/gedcom/subparsers/address_structure.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.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.elements.element import Element + +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 parse_address_structure(element: Element) -> dict: + """Parses and extracts a `ADDRESS_STRUCTURE` structure. + + The `element` should be the parent that contains it. + """ + 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..73af9b1 --- /dev/null +++ b/gedcom/subparsers/association_structure.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_source_citation + + +def parse_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(), + '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(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_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..355e64f --- /dev/null +++ b/gedcom/subparsers/change_date.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure + + +def parse_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': '', + '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(parse_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..c777e07 --- /dev/null +++ b/gedcom/subparsers/child_to_family_link.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure + + +def parse_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(), + '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(parse_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..0fd1068 --- /dev/null +++ b/gedcom/subparsers/event_detail.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.place_structure import parse_place_structure +from gedcom.subparsers.address_structure import parse_address_structure +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_source_citation +from gedcom.subparsers.multimedia_link import parse_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 parse_event_detail(element: Element) -> dict: + """Parses and extracts a `EVENT_DETAIL` structure. + + The `element` should be the parent that contains it. + """ + 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'] = parse_place_structure(child) + continue + + if child.get_tag() == tags.GEDCOM_TAG_ADDRESS: + record['address'] = parse_address_structure(element) + continue + + if child.get_tag() == tags.GEDCOM_TAG_NOTE: + record['notes'].append(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_source_citation(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_OBJECT: + record['media'].append(parse_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..c958ceb --- /dev/null +++ b/gedcom/subparsers/family_event_detail.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.event_detail import parse_event_detail + + +def parse_family_event_detail(element: Element) -> dict: + """Parses and extracts a `FAMILY_EVENT_DETAIL` structure. + + The `element` should be the parent that contains it. + """ + record = parse_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..67186ce --- /dev/null +++ b/gedcom/subparsers/family_event_structure.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.family_event_detail import parse_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 parse_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(): + if child.get_tag() in EVENT_TAGS: + record = parse_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..cb98be1 --- /dev/null +++ b/gedcom/subparsers/individual_attribute_structure.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.individual_event_detail import parse_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 parse_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(): + if child.get_tag() in ATTRIBUTE_TAGS: + record = parse_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..673cdf3 --- /dev/null +++ b/gedcom/subparsers/individual_event_detail.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.event_detail import parse_event_detail + + +def parse_individual_event_detail(element: Element) -> dict: + """Parses and extracts a `INDIVIDUAL_EVENT_DETAIL` structure. + + The `element` should be the parent that contains it. + """ + record = parse_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..36a2cd7 --- /dev/null +++ b/gedcom/subparsers/individual_event_structure.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.individual_event_detail import parse_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 parse_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(): + if child.get_tag() in BIRTH_EVENT_TAGS: + record = parse_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 = parse_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 = parse_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..d674db8 --- /dev/null +++ b/gedcom/subparsers/lds_individual_ordinance.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_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 parse_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(): + 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(parse_note_structure(child)) + continue + + if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_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..d88362d --- /dev/null +++ b/gedcom/subparsers/lds_spouse_sealing.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_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 parse_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(): + 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(parse_note_structure(child)) + continue + + if gchild.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_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..74d2118 --- /dev/null +++ b/gedcom/subparsers/multimedia_link.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element + +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 parse_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(), + '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 diff --git a/gedcom/subparsers/note_structure.py b/gedcom/subparsers/note_structure.py new file mode 100644 index 0000000..58ff1a3 --- /dev/null +++ b/gedcom/subparsers/note_structure.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +Substructure parser for a `NOTE_STRUCTURE` record. + +This is anchored by the `gedcom.tags.GEDCOM_TAG_NOTE` tag. +""" + +from gedcom.elements.element import Element + + +def parse_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(), + '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..ff977b8 --- /dev/null +++ b/gedcom/subparsers/personal_name_pieces.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure +from gedcom.subparsers.source_citation import parse_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 parse_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': '', + '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(parse_note_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_SOURCE: + record['citations'].append(parse_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..1903979 --- /dev/null +++ b/gedcom/subparsers/personal_name_structure.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.personal_name_pieces import parse_personal_name_pieces + + +def extract_name_from_personal_name_structure(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': '', + 'type': '', + 'pieces': {} + } + record['name'] = element.get_value() + record['pieces'] = parse_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 parse_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_from_personal_name_structure(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_from_personal_name_structure(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_ROMANIZED: + record['romanized'].append(extract_name_from_personal_name_structure(child)) + continue + + return record diff --git a/gedcom/subparsers/place_structure.py b/gedcom/subparsers/place_structure.py new file mode 100644 index 0000000..b21ec96 --- /dev/null +++ b/gedcom/subparsers/place_structure.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure + + +def parse_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(), + '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(parse_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..36b7b01 --- /dev/null +++ b/gedcom/subparsers/source_citation.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.multimedia_link import parse_multimedia_link +from gedcom.subparsers.note_structure import parse_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 parse_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(), + '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(parse_multimedia_link(child)) + continue + + if child.get_tag() == tags.GEDCOM_TAG_NOTE: + record['notes'].append(parse_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..4a2c0fc --- /dev/null +++ b/gedcom/subparsers/source_repository_citation.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure + + +def parse_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(), + '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(parse_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..ab400a6 --- /dev/null +++ b/gedcom/subparsers/spouse_to_family_link.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element +from gedcom.subparsers.note_structure import parse_note_structure + + +def parse_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(), + 'notes': [] + } + for child in element.get_child_elements(): + if child.get_tag() == tags.GEDCOM_TAG_NOTE: + record['notes'].append(parse_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..8601d1e --- /dev/null +++ b/gedcom/subparsers/user_reference_number.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +""" +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.elements.element import Element + + +def parse_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(), + '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 9efa002..6b33c71 100644 --- a/gedcom/tags.py +++ b/gedcom/tags.py @@ -1,88 +1,403 @@ # -*- coding: utf-8 -*- -# Python GEDCOM Parser +# Copyright (C) 2020 # -# 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 file is part of the Python GEDCOM Parser. # -# 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. +# 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. # -# 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 +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom """ -GEDCOM tags. +Module containing the standard GEDCOM tags and some of the most 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` @@ -94,90 +409,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 `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_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_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`)""" diff --git a/setup.py b/setup.py index 3b6f06b..1d0d26d 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,14 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + from setuptools import setup, find_packages from os import path from io import open diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..29f614c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,10 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom diff --git a/tests/element/__init__.py b/tests/element/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/element/test_element.py b/tests/element/test_element.py deleted file mode 100644 index 710830c..0000000 --- a/tests/element/test_element.py +++ /dev/null @@ -1,6 +0,0 @@ -from gedcom.element.element import Element - - -def test_initialization(): - element = Element(level=-1, pointer="", tag="", value="") - assert isinstance(element, Element) diff --git a/tests/element/test_family.py b/tests/element/test_family.py deleted file mode 100644 index eab452e..0000000 --- a/tests/element/test_family.py +++ /dev/null @@ -1,9 +0,0 @@ -from gedcom.element.element import Element -from gedcom.element.family import FamilyElement -import gedcom.tags - - -def test_initialization(): - family_element = FamilyElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_FAMILY, value="") - assert isinstance(family_element, Element) - assert isinstance(family_element, FamilyElement) 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_object.py b/tests/element/test_object.py deleted file mode 100644 index ede7384..0000000 --- a/tests/element/test_object.py +++ /dev/null @@ -1,9 +0,0 @@ -from gedcom.element.element import Element -from gedcom.element.object import ObjectElement -import gedcom.tags - - -def test_initialization(): - object_element = ObjectElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_OBJECT, value="") - assert isinstance(object_element, Element) - assert isinstance(object_element, ObjectElement) diff --git a/tests/element/test_root.py b/tests/element/test_root.py deleted file mode 100644 index 65adee1..0000000 --- a/tests/element/test_root.py +++ /dev/null @@ -1,8 +0,0 @@ -from gedcom.element.element import Element -from gedcom.element.root import RootElement - - -def test_initialization(): - root_element = RootElement(level=-1, pointer="", tag="ROOT", value="") - assert isinstance(root_element, Element) - assert isinstance(root_element, RootElement) diff --git a/tests/elements/__init__.py b/tests/elements/__init__.py new file mode 100644 index 0000000..29f614c --- /dev/null +++ b/tests/elements/__init__.py @@ -0,0 +1,10 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom diff --git a/tests/elements/test_element.py b/tests/elements/test_element.py new file mode 100644 index 0000000..7279204 --- /dev/null +++ b/tests/elements/test_element.py @@ -0,0 +1,17 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element + + +def test_initialization(): + element = Element(level=-1, pointer="", tag="", value="") + assert isinstance(element, Element) diff --git a/tests/elements/test_family.py b/tests/elements/test_family.py new file mode 100644 index 0000000..3f7d28e --- /dev/null +++ b/tests/elements/test_family.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.family import FamilyElement +import gedcom.tags + + +def test_initialization(): + family_element = FamilyElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_FAMILY, value="") + assert isinstance(family_element, Element) + assert isinstance(family_element, FamilyElement) diff --git a/tests/elements/test_header.py b/tests/elements/test_header.py new file mode 100644 index 0000000..25f624d --- /dev/null +++ b/tests/elements/test_header.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.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_individual.py b/tests/elements/test_individual.py similarity index 60% rename from tests/element/test_individual.py rename to tests/elements/test_individual.py index f5dfabd..16c016f 100644 --- a/tests/element/test_individual.py +++ b/tests/elements/test_individual.py @@ -1,5 +1,16 @@ -from gedcom.element.element import Element -from gedcom.element.individual import IndividualElement +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.individual import IndividualElement import gedcom.tags diff --git a/tests/elements/test_note.py b/tests/elements/test_note.py new file mode 100644 index 0000000..3600617 --- /dev/null +++ b/tests/elements/test_note.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.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/elements/test_object.py b/tests/elements/test_object.py new file mode 100644 index 0000000..3b238a7 --- /dev/null +++ b/tests/elements/test_object.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.object import ObjectElement +import gedcom.tags + + +def test_initialization(): + object_element = ObjectElement(level=-1, pointer="", tag=gedcom.tags.GEDCOM_TAG_OBJECT, value="") + assert isinstance(object_element, Element) + assert isinstance(object_element, ObjectElement) diff --git a/tests/elements/test_repository.py b/tests/elements/test_repository.py new file mode 100644 index 0000000..cfaabec --- /dev/null +++ b/tests/elements/test_repository.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.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/elements/test_root.py b/tests/elements/test_root.py new file mode 100644 index 0000000..66208d2 --- /dev/null +++ b/tests/elements/test_root.py @@ -0,0 +1,19 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.root import RootElement + + +def test_initialization(): + root_element = RootElement(level=-1, pointer="", tag="ROOT", value="") + assert isinstance(root_element, Element) + assert isinstance(root_element, RootElement) diff --git a/tests/elements/test_source.py b/tests/elements/test_source.py new file mode 100644 index 0000000..d9b8431 --- /dev/null +++ b/tests/elements/test_source.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.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/elements/test_submission.py b/tests/elements/test_submission.py new file mode 100644 index 0000000..f655e9a --- /dev/null +++ b/tests/elements/test_submission.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.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/elements/test_submitter.py b/tests/elements/test_submitter.py new file mode 100644 index 0000000..d7b3cb5 --- /dev/null +++ b/tests/elements/test_submitter.py @@ -0,0 +1,20 @@ +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.element import Element +from gedcom.elements.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, SubmitterElement) diff --git a/tests/test_parser.py b/tests/test_parser.py index 451a3fa..09e9ee5 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1,5 +1,16 @@ -from gedcom.element.individual import IndividualElement -from gedcom.element.root import RootElement +# Copyright (C) 2020 +# +# This file is part of the Python GEDCOM Parser. +# +# 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. +# +# For more, have a look at the GitHub repository at: +# https://github.com/nickreynke/python-gedcom + +from gedcom.elements.individual import IndividualElement +from gedcom.elements.root import RootElement from gedcom.parser import Parser @@ -62,7 +73,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 +97,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 +123,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) diff --git a/tox.ini b/tox.ini index 8cca615..2f00a83 100644 --- a/tox.ini +++ b/tox.ini @@ -13,6 +13,8 @@ basepython = py37: python3.7 py38: python3.8 deps = + chardet + ansel check-manifest flake8 pytest