def test_gen_file(self): user = User(username="******") user.save() tree = Tree(title="Test", creator=user) tree.save() spouse_1_legal_name = LegalName(first_name="Betty", tree=tree) spouse_1_legal_name.save() spouse_1 = Person(legal_name=spouse_1_legal_name, gender='Female', tree=tree) spouse_1.save() spouse_2_legal_name = LegalName(first_name="Kyle", tree=tree) spouse_2_legal_name.save() spouse_2 = Person(legal_name=spouse_2_legal_name, gender='Male', tree=tree) spouse_2.save() child_legal_name = LegalName(first_name="Symphony", tree=tree) child_legal_name.save() child = Person(legal_name=child_legal_name, gender="Unknown", tree=tree) child.save() marriage_date = datetime.datetime(2000, 12, 1) divorce_date = datetime.datetime(2100, 12, 2) partnership = Partnership( marriage_date=marriage_date, divorce_date=divorce_date, marital_status=Partnership.MaritalStatus.MARRIED, tree=tree) partnership.save() partnership.children.add(child) partnership.save() person_partnership_1 = PersonPartnership(person=spouse_1, partnership=partnership) person_partnership_1.save() person_partnership_2 = PersonPartnership(person=spouse_2, partnership=partnership) person_partnership_2.save() root = gedcom_generator.generate_file(tree) parser = Parser() parser.parse([]) expected = parser.get_root_element() head_element, submitter_element = gedcom_generator.gen_head_and_submitter( tree) expected.add_child_element(head_element) expected.add_child_element(submitter_element) ptr, spouse_1_element = gedcom_generator.gen_individual(spouse_1) expected.add_child_element(spouse_1_element) ptr, spouse_2_element = gedcom_generator.gen_individual(spouse_2) expected.add_child_element(spouse_2_element) ptr, child_element = gedcom_generator.gen_individual(child) expected.add_child_element(child_element) ptr, family = gedcom_generator.gen_family(partnership) expected.add_child_element(family) self.assertTrue(gedcom_helpers.element_equals(root, expected))
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)
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
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 test_to_gedcom_string(): # From string case_1 = """0 @I5@ INDI 1 NAME First /Last/ 1 SEX M 1 BIRT 2 DATE 1 JAN 1900 2 PLAC Kirkland, King, Washington, USA 3 MAP 4 LATI N47.680663 4 LONG W122.234319 """ gedcom_parser = Parser() gedcom_parser.parse([(a + '\n').encode('utf-8-sig') for a in case_1.splitlines()]) case_1_string_array = case_1.splitlines() gedcom_string = gedcom_parser.to_gedcom_string(True) gedcom_string_array = gedcom_string.splitlines() # Check number of lines assert len(case_1_string_array) == len(gedcom_string_array) == 9 # Check each line for i in range(len(case_1_string_array)): assert case_1_string_array[i] == gedcom_string_array[i] # Check whole file string assert gedcom_string == case_1 # From file case_2 = "" with open('tests/files/Musterstammbaum.ged', 'rb') as gedcom_stream: for line in gedcom_stream: case_2 += line.decode('utf-8-sig') gedcom_parser.parse_file('tests/files/Musterstammbaum.ged') case_2_string_array = case_2.splitlines() gedcom_string = gedcom_parser.to_gedcom_string(True) gedcom_string_array = gedcom_string.splitlines() # Check number of lines assert len(case_2_string_array) == len(gedcom_string_array) == 396 # Check each line for i in range(len(case_2_string_array)): assert case_2_string_array[i] == gedcom_string_array[i] # Check whole file string assert gedcom_string == case_2
def 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))))
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()
def test_parse_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()]) element_1 = gedcom_parser.get_root_child_elements()[0] assert isinstance(element_1, IndividualElement) assert element_1.get_tag() == 'INDI' assert element_1.get_pointer() == '@I5@' element_1_children = element_1.get_child_elements() assert len(element_1_children) == 3 assert element_1_children[0].get_tag() == 'NAME' assert element_1_children[1].get_tag() == 'SEX' assert element_1_children[2].get_tag() == 'BIRT' case_2 = """0 @F28@ FAM 1 HUSB @I80@ 1 WIFE @I81@ 1 CHIL @I9@ 2 _FREL Natural 2 _MREL Natural 1 CHIL @I84@ 2 _FREL Natural 2 _MREL Natural 1 CHIL @I85@ 2 _FREL Natural 2 _MREL Natural """ gedcom_parser.parse([(a + '\n').encode('utf-8-sig') 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@' element_2_children = element_2.get_child_elements() assert len(element_2_children) == 5 assert element_2_children[0].get_tag() == 'HUSB' assert element_2_children[1].get_tag() == 'WIFE' assert element_2_children[2].get_tag() == 'CHIL' assert element_2_children[3].get_value() == '@I84@'
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
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)
def test_initialization(): parser = Parser() assert isinstance(parser, Parser)
def get_root_element(f): parser = Parser() parser.parse(f, strict=False) root = parser.get_root_element() return root
def test_get_root_element(): parser = Parser() assert isinstance(parser.get_root_element(), RootElement)
for child in element.get_child_elements(): if child.get_tag() == 'NOBI': titles.append(child.get_value()) return titles try: infile_path = sys.argv[1] except IndexError: sys.exit("No gedcom defined!") outfile_path = infile_path + '.csv' gedcom_parser = Parser() gedcom_parser.parse_file(infile_path) root_child_elements = gedcom_parser.get_root_child_elements() outfile_contents = [] outfile_contents.append(','.join([ "id", "name", "gender", "birth date", "birth place", "death date", "place of death", "title" ])) for element in root_child_elements: if isinstance(element, IndividualElement):
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
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]))
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
def __init__(self, filename): self.filename = filename self.gedcom = Parser() self.gedcom.parse_file(self.filename) self.names = None
indiTable.add_row(individualData.Get_details()) for id in famDict_obj: famData = famDict_obj[id] 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")
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
# TODO adoptive families (>1) are not considered (TODO?) # 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"))
import sys, re from gedcom.element.individual import IndividualElement from gedcom.parser import Parser from prettytable import PrettyTable root_child_elements = [] # Path to .ged file_path = 'windsor-family-Andy-Nguyen.ged' # Initialize parser/Pretty Table gedcom_parser = Parser() # Parse file gedcom_parser.parse_file(file_path) class e(object): root_child_elements = gedcom_parser.get_root_child_elements()
# 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):
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 = []
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
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!")