Beispiel #1
0
 def setUp(self):
     gedcom_parser = Parser()
     file_path = 'tests/files/Musterstammbaum.ged'
     gedcom_parser.parse_file(file_path)
     self.parser = gedcom_parser
     self.root = gedcom_parser.get_root_element()
     self.child_elements = gedcom_parser.get_root_child_elements()
Beispiel #2
0
    def parse(self, gedcom_file_path: str):
        parser = Parser()
        parser.parse_file(gedcom_file_path)
        root = parser.get_root_child_elements()

        for element in root:
            if isinstance(element, IndividualElement):
                self._parse_individual(element)
            elif isinstance(element, FamilyElement):
                self._parse_family(element)
Beispiel #3
0
def test_invalidate_cache():
    parser = Parser()
    parser.parse_file('tests/files/Musterstammbaum.ged')

    assert len(parser.get_element_list()) == 396
    assert len(parser.get_element_dictionary()) == 32

    parser.invalidate_cache()

    assert len(parser.get_element_list()) == 396
    assert len(parser.get_element_dictionary()) == 32
Beispiel #4
0
def test_to_gedcom_string():
    # From string
    case_1 = """0 @I5@ INDI
1 NAME First /Last/
1 SEX M
1 BIRT
2 DATE 1 JAN 1900
2 PLAC Kirkland, King, Washington, USA
3 MAP
4 LATI N47.680663
4 LONG W122.234319
"""

    gedcom_parser = Parser()
    gedcom_parser.parse([(a + '\n').encode('utf-8-sig')
                         for a in case_1.splitlines()])

    case_1_string_array = case_1.splitlines()
    gedcom_string = gedcom_parser.to_gedcom_string(True)
    gedcom_string_array = gedcom_string.splitlines()

    # Check number of lines
    assert len(case_1_string_array) == len(gedcom_string_array) == 9

    # Check each line
    for i in range(len(case_1_string_array)):
        assert case_1_string_array[i] == gedcom_string_array[i]

    # Check whole file string
    assert gedcom_string == case_1

    # From file
    case_2 = ""

    with open('tests/files/Musterstammbaum.ged', 'rb') as gedcom_stream:
        for line in gedcom_stream:
            case_2 += line.decode('utf-8-sig')

    gedcom_parser.parse_file('tests/files/Musterstammbaum.ged')

    case_2_string_array = case_2.splitlines()
    gedcom_string = gedcom_parser.to_gedcom_string(True)
    gedcom_string_array = gedcom_string.splitlines()

    # Check number of lines
    assert len(case_2_string_array) == len(gedcom_string_array) == 396

    # Check each line
    for i in range(len(case_2_string_array)):
        assert case_2_string_array[i] == gedcom_string_array[i]

    # Check whole file string
    assert gedcom_string == case_2
Beispiel #5
0
    def handle(self, *args, **kwargs):
        filename = kwargs["file name"]

        # validate that the user gave file with extension ged
        if filename.suffix != ".ged":
            raise CommandError("Please specify GEDCOM file, ex: myGedcom.ged")

        # Check that the file is there
        path = Path(
            "mysite/familytree/management/commands/gedcom_files/"
        )  # @@TODO: update to take the whole path (so it doesn't need to be saved in a particular folder)
        path_plus_file = path.joinpath(filename)

        if path_plus_file.is_file():
            gedcom_parser = Parser()
            gedcom_parser.parse_file(path_plus_file)
            root_child_elements = gedcom_parser.get_root_child_elements()

            # Find/add person records
            for element in root_child_elements:
                if isinstance(element, IndividualElement):
                    self.handle_person(element)

            # Find/add family records (after person records exist, so we can look up parents)
            # also save intermediate dictionary: CHIL INDI - family INDI
            for element in root_child_elements:
                if isinstance(element, FamilyElement):
                    self.handle_family(element)

            # now that we've saved all the people and families, populate orig_family on people records
            self.add_person_family_values(self.child_family_dict)

        else:
            raise CommandError(
                "That gedcom file does not exist in the expected directory"
            )

        # gather run results
        run_results = "gedcom_person_records: " + str(self.gedcom_person_records) + "\n"
        run_results += (
            "gedcom_family_records: " + str(self.gedcom_family_records) + "\n"
        )
        run_results += "person_added_count: " + str(self.person_added_count) + "\n"
        run_results += "person_skipped_count: " + str(self.person_skipped_count) + "\n"
        run_results += "family_added_count: " + str(self.family_added_count) + "\n"

        # Display and log them
        self.stdout.write(self.style.SUCCESS("You passed filename: ") + str(filename))
        self.stdout.write(run_results)
        f = open("ImportInfo.txt", "w")
        f.write(run_results)
        f.closed
    def import_gedcom_file(self, gedcom_file_path):
        gedcom_parser = Parser()
        gedcom_parser.parse_file(gedcom_file_path)
        root_child_elements = gedcom_parser.get_root_child_elements()

        # Parse all elements in the GEDCOM file, recording details from
        # individual and family elements.

        families = []
        # Lookup from gedcom individual pointer (e.g. "@I219") to api.Individual.
        individuals = dict()
        for element in root_child_elements:
            if isinstance(element, IndividualElement):
                individuals[element.get_pointer()] = self.parse_indi(element)
            elif isinstance(element, FamilyElement):
                families.append(self.parse_family(element))

        # Note: in order to relations in the DB, we need to commit the
        # Individuals to the DB so they have valid PK's.
        for individual in individuals.values():
            individual.save()

        for (husband, wife, married_date, place, children, note) in families:
            family = Family(
                married_date = married_date,
                married_location = place,
                note = note,
            )
            family.save()
            for partner in filter(lambda k: k != '', [husband, wife]):
                individuals[partner].partner_in_families.add(family)
                individuals[partner].save()
            family.save()

            for child in children:
                if individuals[child].child_in_family != None:
                    raise Exception("Can't handle child {} being a child of two families!".format(child))
                individuals[child].child_in_family = family
                individuals[child].save()

        self.stdout.write(self.style.SUCCESS('Successfully parsed {} individuals {} families'.format(
            len(individuals), len(families))))
Beispiel #7
0
def test_parse_file():
    parser = Parser()

    assert len(parser.get_root_child_elements()) == 0

    parser.parse_file('tests/files/Musterstammbaum.ged')

    assert len(parser.get_root_child_elements()) == 34

    individuals_in_root_child_elements = 0
    individuals_in_element_list = 0

    for element in parser.get_root_child_elements():
        if isinstance(element, IndividualElement):
            individuals_in_root_child_elements += 1

    for element in parser.get_element_list():
        if isinstance(element, IndividualElement):
            individuals_in_element_list += 1

    assert individuals_in_root_child_elements == 20
    assert individuals_in_element_list == 20
        familyTable.add_row(famData.Get_details())
    print("Individuals")
    print(indiTable)
    print("Families")
    print(familyTable)


# Path to your `.ged` file
file_path = 'FamilyTree.ged'
#file_path ='gedcom'

# Initialize the parser
gedcom_parser = Parser()

# Parse your file
gedcom_parser.parse_file(file_path)

root_elements = gedcom_parser.get_element_list()

info = {"INDI": [], "FAM": []}

for element in root_elements:
    if str(element.get_tag()) == "INDI" or str(element.get_tag()) == "FAM":
        if element.get_tag() == "INDI" and len(info[element.get_tag()]) > 5000:
            raise ValueError("Too many individuals in file")
        if element.get_tag() == "FAM" and len(info[element.get_tag()]) > 1000:
            raise ValueError("Too many families in file")

months = {
    "JAN": 1,
    "FEB": 2,
Beispiel #9
0
def processGedFile(file_path):
    # Path to your `.ged` file
    #file_path ='FamilyTree.ged'

    #file_path ='gedcom'

    # Initialize the parser
    gedcom_parser = Parser()

    # Parse your file
    gedcom_parser.parse_file(file_path)

    root_elements = gedcom_parser.get_element_list()

    info = {"INDI": [], "FAM": []}

    for element in root_elements:
        if str(element.get_tag()) == "INDI" or str(element.get_tag()) == "FAM":
            if element.get_tag() == "INDI" and len(
                    info[element.get_tag()]) > 5000:
                raise ValueError("Too many individuals in file")
            if element.get_tag() == "FAM" and len(
                    info[element.get_tag()]) > 1000:
                raise ValueError("Too many families in file")

    months = {
        "JAN": 1,
        "FEB": 2,
        "MAR": 3,
        "APR": 4,
        "MAY": 5,
        "JUN": 6,
        "JUL": 7,
        "AUG": 8,
        "SEP": 9,
        "OCT": 10,
        "NOV": 11,
        "DEC": 12
    }

    # Individual dictionary
    indiDict = OrderedDict()
    myTag = ""

    famDict = OrderedDict()
    famTag = ""
    isMarried = False
    isDivorced = False
    indiDict["DupI_ID"] = indiClass("DupI_ID")
    famDict["DupliID_fam"] = familyClass("DupliID_fam")

    #Line Dictionary for the items
    lines_dict = dict()
    lines_dict["Duplicate Ind"] = list()
    lines_dict["Duplicate Fam"] = list()
    line_count = 0

    for element in root_elements:
        age = 0
        line_count = line_count + 1

        # Fetch Individual ID details
        if (element.get_level() == 0 and element.get_tag() == "INDI"):
            individualString = element.to_gedcom_string()
            individualString = individualString.replace('@',
                                                        '').strip().split(" ")

            #Fetch Individual ID tag
            myTag = individualString[1]

            if myTag in indiDict:
                indiDict["DupI_ID"].Set_DupliID(myTag)
                lines_dict["Duplicate Ind"].append(line_count)
                continue
            else:
                indiDict[myTag] = indiClass(myTag)
                indiDict[myTag].Set_ID(myTag)
                lines_dict[str(f"{myTag}: ID set")] = line_count

        # Fetch ans set Child ID details for individual
        if (element.get_level() == 1) and element.get_tag() == "FAMC":
            childString = element.to_gedcom_string()
            childString = childString.replace('@', '').strip().split(" ")
            indiDict[myTag].Set_child(childString[2])
            lines_dict[str(
                f"{myTag}: {childString[2]} child set")] = line_count

        # Fetch ans set Spouse ID details for individual
        if (element.get_level() == 1) and element.get_tag() == "FAMS":
            spouseString = element.to_gedcom_string()
            spouseString = spouseString.replace('@', '').strip().split(" ")
            indiDict[myTag].Set_spouse(spouseString[2])
            lines_dict[str(
                f"{myTag}: {spouseString[2]} spouse set")] = line_count

        if isinstance(element, IndividualElement):

            # Fetch and set the name
            (first, last) = element.get_name()
            indiDict[myTag].Set_name(str(first + " " + last))
            lines_dict[str(
                f"{myTag}: First and last name set")] = line_count + 1

            # Fetch the Gender and set the gender
            indiDict[myTag].Set_gender(element.get_gender())
            lines_dict[str(f"{myTag}: Gender set")] = line_count + 5

            # Check if individual is alive
            if (element.is_deceased() == True):

                # Set Alive status to false
                indiDict[myTag].Set_alive(False)
                lines_dict[str(f"{myTag}: Living status set")] = line_count + 9

                # Fetch Birth and death dates
                bday = element.get_birth_data()[0]
                death = element.get_death_data()[0]

                #fetch birth and death places
                bplace = element.get_birth_data()[1]
                #dplace = element.get_death_data()[1]

                #get occupation
                #occupation = element.get_occupation()

                # Format Dates in Day Month and Year
                bday = bday.split(" ")
                bday = datetime.date(int(bday[2]), int(months[bday[1]]),
                                     int(bday[0]))
                death = death.split(" ")
                death = datetime.date(int(death[2]), int(months[death[1]]),
                                      int(death[0]))

                # Set Birthday
                indiDict[myTag].Set_birthday(bday)
                lines_dict[str(f"{myTag}: Birthday set")] = line_count + 7
                # Set Death day
                indiDict[myTag].Set_death(death)
                #add death day if birth place is not empty
                if len(bplace) > 0:
                    lines_dict[str(
                        f"{myTag}: Death date set")] = line_count + 10
                else:
                    lines_dict[str(
                        f"{myTag}: Death date set")] = line_count + 9

                # Calculate the age
                age = from_dob_to_death(bday, death)
                # Set Age
                indiDict[myTag].Set_age(age)

            else:
                # Set Alive status to true
                indiDict[myTag].Set_alive(True)
                # Fetch Birth dates
                bday = element.get_birth_data()[0].split(" ")
                bday = datetime.date(int(bday[2]), int(months[bday[1]]),
                                     int(bday[0]))
                # Set Birthday
                indiDict[myTag].Set_birthday(bday)
                lines_dict[str(f"{myTag}: Birthday set")] = line_count + 7
                # Calculate the age
                age = from_dob_to_age(bday)
                # Set Age
                indiDict[myTag].Set_age(age)

        if (element.get_level() == 0 and element.get_tag() == "FAM"):
            familyString = element.to_gedcom_string()
            familyString = familyString.replace('@', '').strip().split(" ")
            famTag = familyString[1]
            if famTag in famDict:
                famDict["DupliID_fam"].Set_DupliID_fam(famTag)
                lines_dict["Duplicate Fam"].append(line_count)
                continue
            else:
                famDict[famTag] = familyClass(famTag)
                famDict[famTag].Set_ID(famTag)
                lines_dict[str(f"{famTag}: ID set")] = line_count
        if (element.get_level() == 1 and element.get_tag() == "MARR"):
            isMarried = True
        if (isMarried and element.get_tag() == "DATE"
                and element.get_level() == 2):
            marriedDay = element.get_value()
            marriedDay = marriedDay.split(" ")
            marriedDay = datetime.date(int(marriedDay[2]),
                                       int(months[marriedDay[1]]),
                                       int(marriedDay[0]))
            famDict[famTag].Set_married(marriedDay)
            lines_dict[str(f"{famTag}: Married date set")] = line_count
            isMarried = False
        if (element.get_tag() == "DIV" and element.get_level() == 1):
            isDivorced = True
        if (isDivorced and element.get_tag() == "DATE"
                and element.get_level() == 2):
            divorcedDay = element.get_value()
            divorcedDay = divorcedDay.split(" ")
            divorcedDay = datetime.date(int(divorcedDay[2]),
                                        int(months[divorcedDay[1]]),
                                        int(divorcedDay[0]))
            famDict[famTag].Set_divorced(divorcedDay)
            lines_dict[str(f"{famTag}: Divorced date set")] = line_count
            isDivorced = False
        if (element.get_level() == 1 and element.get_tag() == "HUSB"):
            husbStr = element.to_gedcom_string()
            husbStr = husbStr.replace('@', '').strip().split(" ")[2]
            famDict[famTag].Set_husbandID(husbStr)
            lines_dict[str(f"{famTag}: Husband ID set")] = line_count
            famDict[famTag].Set_husbandName(indiDict[husbStr].Get_name())
            lines_dict[str(f"{famTag}: Husband name set")] = line_count
        if (element.get_level() == 1 and element.get_tag() == "WIFE"):
            wifeStr = element.to_gedcom_string()
            wifeStr = wifeStr.replace('@', '').strip().split(" ")[2]
            famDict[famTag].Set_wifeID(wifeStr)
            lines_dict[str(f"{famTag}: Wife ID set")] = line_count
            famDict[famTag].Set_wifeName(indiDict[wifeStr].Get_name())
            lines_dict[str(f"{famTag}: Wife name set")] = line_count
        if (element.get_level() == 1 and element.get_tag() == "CHIL"):
            child = element.to_gedcom_string()
            child = child.replace('@', '').strip().split(" ")[2]
            famDict[famTag].Set_children(child)
            lines_dict[str(
                f"{famTag}: {child} added to children")] = line_count

    return indiDict, famDict, lines_dict
Beispiel #10
0
class GedcomManipulator:
    def __init__(self, file_path):
        self.gedcom_parser = Parser()
        self.gedcom_parser.parse_file(file_path,
                                      False)  # Disable strict parsing
        self.root_child_elements = self.gedcom_parser.get_root_child_elements()
        self.fullName = []

    @staticmethod
    def first_name(el):
        "Returns the first name of the element (joined)"
        return ''.join(el.get_name()[0])

    def get_full_name(self, el):
        """Returns the full names of all elements in a gedcome file (.ged)"""

        self.fullName = [self.first_name(el)]
        parent = el
        while parent:  # while parent is not an empty list
            parent = self.gedcom_parser.get_parents(parent)
            if parent:
                self.fullName.append(self.first_name(parent[0]))
                parent = parent[0]

        if el.get_name()[1]:
            self.fullName.append(el.get_name()[1])

        return self.fullName

    def write_csv(self, output_file_path):
        pointer = [el.get_pointer() for el in self.root_child_elements[1:2260]]
        wb = Workbook()
        ws = wb.active
        row = 2
        for el in self.root_child_elements[1:]:
            if el.get_tag(
            ) == 'FAM':  # if element tag is "Individual," extract full name.
                for child in el.get_child_elements():
                    element = self.root_child_elements[
                        pointer.index(child.get_value()) + 1]
                    full_name = self.get_full_name(element)
                    if child.get_tag() != 'CHIL':
                        for col, val in enumerate(full_name[::-1], start=1):
                            cell = ws.cell(row=row, column=col + 1)
                            cell.value = val
                            if child.get_tag() == 'HUSB':
                                cell.fill = PatternFill("solid",
                                                        fgColor="66CCFF")
                            elif child.get_tag() == 'WIFE':
                                cell.fill = PatternFill("solid",
                                                        fgColor="FFCCFF")
                        row += 1
                    else:
                        cell = ws.cell(row=row, column=2)
                        cell.value = self.first_name(element)
                        cell.fill = PatternFill("solid", fgColor="00CCCC")
                        row += 1
                row += 1
            else:  # else terminate, i.e. if tag is "family"
                pass
        wb.save(output_file_path)
Beispiel #11
0
from gedcom.element.individual import IndividualElement
from gedcom.parser import Parser

file_path = "MyTree.ged"

file_record = open("fact.pl", 'w', encoding='utf-8')

gedcom_parser = Parser()

gedcom_parser.parse_file(file_path, False)

root_child_elements = gedcom_parser.get_root_child_elements()

for element in root_child_elements:
    if isinstance(element, IndividualElement):
        if len(gedcom_parser.get_parents(element)) != 0:
            name_of_child = element.get_name()[0]
            sur_of_child = element.get_name()[1]
            mother = gedcom_parser.get_parents(element)[1].get_name()
            father = gedcom_parser.get_parents(element)[0].get_name()
            file_record.write(
                'parents(\'{} {}\', \'{} {}\', \'{} {}\').\n'.format(
                    name_of_child, sur_of_child, father[0], father[1],
                    mother[0], mother[1]))
# Author: Evgeny Blokhin
# License: MIT

import sys
from gedcom.parser import Parser
from gedcom.element.individual import IndividualElement
from gedcom.element.family import FamilyElement

try: workpath = sys.argv[1]
except IndexError: sys.exit("No gedcom defined!")

def term2id(el):
    return "i" + el.get_pointer().replace('@', '').lower()

g = Parser()
g.parse_file(workpath)
gedcom_dict = g.get_element_dictionary()
individuals, marriages = {}, {}

for k, v in gedcom_dict.items():
    if isinstance(v, IndividualElement):
        children, siblings = set(), set()
        idx = term2id(v)

        title = v.get_name()[0] + " " + v.get_name()[1]
        title = title.replace('"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').strip()

        own_families = g.get_families(v, 'FAMS')
        for fam in own_families:
            children |= set(term2id(i) for i in g.get_family_members(fam, "CHIL"))
Beispiel #13
0
def run_checker(file_path):
    results = "Individual Name,Spouse Name,Shared Ancestor, # of Generations Removed from Individual, # of Generations Removed from Spouse<br />"

    # Initialize the parser
    gedcom_parser = Parser()

    # Parse your file
    gedcom_parser.parse_file(file_path, False)

    root_child_elements = gedcom_parser.get_root_child_elements()

    def print_name(person):
        name = person.get_name()
        return name[0] + " " + name[1]

    def get_ancestors(person, level=0):
        parents = gedcom_parser.get_parents(person, "ALL")

        for index, parent in enumerate(parents):
            parents[index] = (parent, level)

        ancestors = []
        ancestors.extend(parents)

        for parent in parents:
            ancestors.extend(get_ancestors(parent[0], level + 1))

        return ancestors

    def are_related(person_one, person_two):
        ancestors_one = get_ancestors(person_one)
        ancestors_two = get_ancestors(person_two)

        # traverse in the 1st list
        for x in ancestors_one:
            # traverse in the 2nd list
            for y in ancestors_two:
                # if one common
                if x[0] == y[0]:
                    return (x[0], x[1], y[1])
        return False

    count = 0

    # Iterate through all root child elements
    for individual in root_child_elements:
        # Is the `element` an actual `IndividualElement`? (Allows usage of extra functions such as `surname_match` and `get_name`.)
        if isinstance(individual, IndividualElement):
            families = gedcom_parser.get_families(
                individual, gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE)
            for family in families:
                family_members = gedcom_parser.get_family_members(
                    family, members_type=gedcom.tags.GEDCOM_TAG_WIFE)

                if len(family_members) > 0:
                    for spouse in family_members:
                        shared_ancestor_tuple = are_related(individual, spouse)
                        if individual != spouse and shared_ancestor_tuple:
                            results += print_name(
                                individual
                            ) + "," + print_name(spouse) + "," + print_name(
                                shared_ancestor_tuple[0]) + "," + str(
                                    shared_ancestor_tuple[1]) + "," + str(
                                        shared_ancestor_tuple[2]) + "<br />"
                            count += 1

    results += 'Total count: ' + str(count)

    return results
Beispiel #14
0
class GedcomManipulator(object):
    def __init__(self, filename):
        self.filename = filename
        self.gedcom = Parser()
        self.gedcom.parse_file(self.filename)
        self.names = None

    @property
    def namelist(self):
        if self.names is None:
            self.names = []
            root_child_elements = self.gedcom.get_root_child_elements()

            for element in root_child_elements:
                if isinstance(element, IndividualElement):
                    self.names.append(
                        (element.get_pointer(), " ".join(element.get_name())))

        return self.names

    def get_cousins(self, _id, level=2):
        """Find all cousins of given distance."""
        root = self.gedcom[_id]

        assert root is not None

        atlevel = 0
        prevqueue = [
            root,
        ]
        while atlevel < level:
            queue = []
            for person in prevqueue:
                for par in person.parents:
                    queue.append(par)

            prevqueue = queue
            atlevel += 1

        queue = set()
        for person in prevqueue:
            famc = person['FAMC']
            if famc is None:
                continue

            def add_siblings(*families):
                for family in families:
                    for child in family.as_individual().children:
                        if child.as_individual().id != person.id:
                            queue.add(child.as_individual())

            if isinstance(famc, list):
                add_siblings(*famc)
            else:
                add_siblings(famc)

        prevqueue = queue

        while atlevel > 0:
            queue = set()
            for person in prevqueue:
                fams = person['FAMS']
                if fams is None:
                    continue

                def add_children(*families):
                    for family in families:
                        for child in family.as_individual().children:
                            queue.add(child.as_individual())

                if isinstance(fams, list):
                    add_children(*fams)
                else:
                    add_children(fams)

            prevqueue = queue
            atlevel -= 1

        return prevqueue

    def get_ydna(self, _id):
        """Find all people that would/should have the same Y-DNA."""

        root = self.gedcom[_id]

        queue = [
            root,
        ]
        outelements = set()

        while queue:
            cur = queue.pop(0)

            if cur is None:
                continue

            if cur in outelements:
                continue

            fams = cur['FAMS']

            if cur.father:
                queue.append(cur.father)

            if fams is not None:

                def add_children(*families):
                    for family in families:
                        for child in family.as_individual().children:
                            if child.as_individual().is_male:
                                queue.append(child.as_individual())

                if isinstance(fams, list):
                    add_children(*fams)
                else:
                    add_children(fams)

            outelements.add(cur)

        return outelements

    def get_branch(self,
                   _id,
                   siblings=False,
                   descendants=False,
                   ancestors=True):
        root = self.gedcom[_id]

        queue = [
            root,
        ]
        outelements = set()

        while queue:
            # print(len(queue))
            cur = queue.pop(0)

            if cur is None:
                continue

            if cur in outelements:
                continue

            famc = cur['FAMC']
            fams = cur['FAMS']

            if ancestors and famc:
                if famc is not None:
                    outelements.add(famc)

                for par in cur.parents:
                    queue.append(par)

            if siblings and famc:
                if isinstance(famc, list):
                    continue

                fam = famc.as_individual()
                if fam is not None:
                    outelements.add(fam)
                    for child in fam.children:
                        queue.append(child.as_individual())

            if descendants and fams:
                # if cur != root:
                if isinstance(fams, list):
                    for fam in fams:
                        fam = fam.as_individual()
                        if fam is None:
                            continue
                        outelements.add(fams)
                        if fam.husband is not None:
                            outelements.add(fam.husband.as_individual())
                        if fam.wife is not None:
                            outelements.add(fam.wife.as_individual())
                        for child in fam.children:
                            queue.append(child.as_individual())
                elif isinstance(fams, gedcom.Spouse):
                    fam = fams.as_individual()
                    if fam is not None:
                        outelements.add(fams)
                        if fam.husband is not None:
                            outelements.add(fam.husband.as_individual())
                        if fam.wife is not None:
                            outelements.add(fam.wife.as_individual())
                        for child in fam.children:
                            queue.append(child.as_individual())
                elif fams is None:
                    pass
                else:
                    # print(type(fams))
                    pass

            outelements.add(cur)

        output = gedcom.GedcomFile()
        for element in outelements:
            output.add_element(element)
        print(len(outelements))
        return output
Beispiel #15
0
# US27: Include person's current age when listing individuals
# Author: Kristin Kim

from datetime import date
from gedcom.parser import Parser
from gedcom.element.individual import IndividualElement

file_path = 'DiazJGedcomProject1.ged'

gedcom_parser = Parser()
gedcom_parser.parse_file(file_path, False)  # Disable strict parsing
elements = gedcom_parser.get_element_list()

today = date.today()
d4 = today.strftime("%d %b %Y").split(" ")  # ['09', 'Oct', '2020']
t_day = int(d4[0])
t_month = d4[1].upper()
t_year = d4[2]

month_list = [
    "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT",
    "NOV", "DEC"
]

t_month_int = month_list.index(t_month) + 1  # JAN=1, FEB=2, DEC=12

n = []


def individual_age(a):
Beispiel #16
0
def processGEDCOM(file_path):

    gedcom_parser = Parser()
    gedcom_parser.parse_file(file_path)
    root_elements = gedcom_parser.get_element_list()

    info = {"INDI": [], "FAM": []}

    for element in root_elements:
        if str(element.get_tag()) == "INDI" or str(element.get_tag()) == "FAM":
            if element.get_tag() == "INDI" and len(
                    info[element.get_tag()]) > 5000:
                raise ValueError("Too many individuals in file")
            if element.get_tag() == "FAM" and len(
                    info[element.get_tag()]) > 1000:
                raise ValueError("Too many families in file")

    months = {
        "JAN": 1,
        "FEB": 2,
        "MAR": 3,
        "APR": 4,
        "MAY": 5,
        "JUN": 6,
        "JUL": 7,
        "AUG": 8,
        "SEP": 9,
        "OCT": 10,
        "NOV": 11,
        "DEC": 12
    }

    indiDict = OrderedDict()
    myTag = ""

    famDict = OrderedDict()
    famTag = ""
    isMarried = False
    isDivorced = False
    for element in root_elements:
        age = 0

        if (element.get_level() == 0 and element.get_tag() == "INDI"):
            individualString = element.to_gedcom_string()
            individualString = individualString.replace('@',
                                                        '').strip().split(" ")

            myTag = individualString[1]

            indiDict[myTag] = indiClass(myTag)
            indiDict[myTag].Set_ID(myTag)

        if (element.get_level() == 1) and element.get_tag() == "FAMC":
            childString = element.to_gedcom_string()
            childString = childString.replace('@', '').strip().split(" ")
            indiDict[myTag].Set_child(childString[2])

        if (element.get_level() == 1) and element.get_tag() == "FAMS":
            spouseString = element.to_gedcom_string()
            spouseString = spouseString.replace('@', '').strip().split(" ")
            indiDict[myTag].Set_spouse(spouseString[2])

        if isinstance(element, IndividualElement):

            (first, last) = element.get_name()
            indiDict[myTag].Set_name(str(first + " " + last))

            indiDict[myTag].Set_gender(element.get_gender())

            if (element.is_deceased() == True):

                indiDict[myTag].Set_alive(False)

                bday = element.get_birth_data()[0]
                death = element.get_death_data()[0]

                bday = bday.split(" ")
                bday = datetime.date(int(bday[2]), int(months[bday[1]]),
                                     int(bday[0]))
                death = death.split(" ")
                death = datetime.date(int(death[2]), int(months[death[1]]),
                                      int(death[0]))

                indiDict[myTag].Set_birthday(bday)
                indiDict[myTag].Set_death(death)
                age = from_dob_to_death(bday, death)
                indiDict[myTag].Set_age(age)

            else:
                indiDict[myTag].Set_alive(True)
                bday = element.get_birth_data()[0].split(" ")
                bday = datetime.date(int(bday[2]), int(months[bday[1]]),
                                     int(bday[0]))
                indiDict[myTag].Set_birthday(bday)
                age = from_dob_to_age(bday)
                indiDict[myTag].Set_age(age)

        if (element.get_level() == 0 and element.get_tag() == "FAM"):
            familyString = element.to_gedcom_string()
            familyString = familyString.replace('@', '').strip().split(" ")
            famTag = familyString[1]
            famDict[famTag] = family(famTag)
            famDict[famTag].Set_ID(famTag)
        if (element.get_level() == 1 and element.get_tag() == "MARR"):
            isMarried = True
        if (isMarried and element.get_tag() == "DATE"
                and element.get_level() == 2):
            marriedDay = element.get_value()
            marriedDay = marriedDay.split(" ")
            marriedDay = datetime.date(int(marriedDay[2]),
                                       int(months[marriedDay[1]]),
                                       int(marriedDay[0]))
            famDict[famTag].Set_married(marriedDay)
            isMarried = False
        if (element.get_tag() == "DIV" and element.get_level() == 1):
            isDivorced = True
        if (isDivorced and element.get_tag() == "DATE"
                and element.get_level() == 2):
            divorcedDay = element.get_value()
            divorcedDay = divorcedDay.split(" ")
            divorcedDay = datetime.date(int(divorcedDay[2]),
                                        int(months[divorcedDay[1]]),
                                        int(divorcedDay[0]))
            famDict[famTag].Set_divorced(divorcedDay)
            isDivorced = False
        if (element.get_level() == 1 and element.get_tag() == "HUSB"):
            husbStr = element.to_gedcom_string()
            husbStr = husbStr.replace('@', '').strip().split(" ")[2]
            famDict[famTag].Set_husbandID(husbStr)
            famDict[famTag].Set_husbandName(indiDict[husbStr].Get_name())
        if (element.get_level() == 1 and element.get_tag() == "WIFE"):
            wifeStr = element.to_gedcom_string()
            wifeStr = wifeStr.replace('@', '').strip().split(" ")[2]
            famDict[famTag].Set_wifeID(wifeStr)
            famDict[famTag].Set_wifeName(indiDict[wifeStr].Get_name())
        if (element.get_level() == 1 and element.get_tag() == "CHIL"):
            child = element.to_gedcom_string()
            child = child.replace('@', '').strip().split(" ")[2]
            famDict[famTag].Set_children(child)

    return indiDict, famDict
Beispiel #17
0
def main():
    print("Running!")

    # Parses arguments
    parser = argparse.ArgumentParser(description="Parse GEDCOM files for web viewing")
    parser.add_argument("--file", "-f", help="Source GEDCOM file", default="familyTree.ged")
    args = parser.parse_args()

    # Gets our input filename
    filename = args.file

    # The folder for the data files
    dataFolder = "../data/"

    # Data filenames
    structureOutput = f"{dataFolder}structure.json"
    detailsOutput = f"{dataFolder}details.json"
    burialOutput = f"{dataFolder}burials.json"
    birthdayOutput = f"{dataFolder}birthdays.json"

    # Initialize the structure and details containers
    structure = []
    details = {}
    birthdays = []
    burials = []

    # Initialize the parser
    gedcomParser = Parser()
    gedcomParser.parse_file(filename)
    # Creates lists of individuals, objects, and families
    individuals, objects, families, notes = generateArrays(gedcomParser)

    # No initial person at first
    initialPerson = None

    # Create the person objects
    personObjs = [gu.Person(indiv, families, objects, notes) for indiv in individuals]

    # Now, we do the real work
    for personObj in personObjs:
        # Sanity check - do the Ukrainian name genders check out?
        surname = re.search('/([^/)]+)', personObj.name[0]).group(1)

        if personObj.sex.upper() == "F":
            # Surname check ("ий")
            if surname.endswith("ий"):
                print("{0} should end in 'а', not 'ий'".format(personObj.name[0]))
        elif personObj.sex.upper() == "M":
            if surname.endswith("ська"):
                print("{0} should end in 'ий', not 'а'".format(personObj.name[0]))

        # We check for a common ancestor among all spouses:
        personObj.handleCommonAncestor(personObjs)

        person = {
            "id": personObj.id,
            "name": personObj.name[0],
            "sex": personObj.sex,
            "parents": personObj.parents,
            "spouses": personObj.spouses,
            "children": personObj.children,
            "parentsHidden": personObj.parentsHidden,
            "childrenHidden": personObj.childrenHidden,
            "birth": personObj.simpleBirthData,
            "death": personObj.simpleDeathData,
        }

        if initialPerson is None:
            initialPerson = person['id']

        detail = {
            "id": personObj.id,
            "pics": personObj.pics,
            "names": personObj.name,
            "notes": personObj.notes,
            "events": personObj.birthData +
                      # We only bother sorting the middle stuff
                      # Birth, death, and burial order never change (hopefully)
                      gu.sortEventsByDate(
                          # Marriage events
                          personObj.marriageData +
                          # Divorce events
                          personObj.divorceData +
                          # Occupation events
                          personObj.occupationData
                      ) +
                      personObj.deathData +  # Death event
                      personObj.burialData,  # Burial data
            "redirects": personObj.redirects,
            "redirectsTo": personObj.redirectsTo,
            "ancestors": personObj.ancestors,
        }

        structure.append(person)

        details[person["id"]] = detail

        # We add the information to the collections - the birthday list and the burial list

        # If birth data exists, and we get rid of the wrapper list, and we have a proper date
        if personObj.birthData and personObj.birthData[0] and personObj.birthData[0][0]:
            date = gu.SimpleDate(personObj.birthData[0][0])

            if date.month and date.day:
                birthdays.append([person["id"], f"{date.month}-{date.day}"])

        # Burial list
        if personObj.burialData and personObj.burialData[0] and personObj.burialData[0][1]:
            burialPlace = personObj.burialData[0][1]

            if burialPlace != "":
                burials.append([person["id"], burialPlace])

    jsonStyling = {"indent": 4, "separators": (',', ':')}

    # Sort the structures and birthday files file
    # Sorting in ukrainian:
    collator = icu.Collator.createInstance(icu.Locale('uk_UK.UTF-8'))

    def reverseNameOrder(p):
        # We split only the first parenthesis
        nonSurnames, surnames = p["name"].split("/", 1)
        return surnames + nonSurnames

    structure.sort(key=lambda p: collator.getSortKey(reverseNameOrder(p)))
    birthdays.sort(key=lambda birthday: date_parser.parse(birthday[1]))
    burials.sort(key=lambda burial: burial[1])

    if not os.path.exists(dataFolder):
        os.makedirs(dataFolder)

    # Generate the structure file
    with open(structureOutput, "w+", encoding="utf8") as f:
        json.dump(structure, f, **jsonStyling)

    # Generate the details file
    with open(detailsOutput, "w+", encoding="utf8") as f:
        json.dump(details, f, **jsonStyling)

    # Generate the birthdays file
    with open(birthdayOutput, "w+", encoding="utf8") as f:
        json.dump(birthdays, f, **jsonStyling)

    # Generate the burials file
    with open(burialOutput, "w+", encoding="utf8") as f:
        json.dump(burials, f, **jsonStyling)

    # Hang so user can see output before closing
    input("Done!")