Skip to content

Commit dab5b82

Browse files
authored
Add person references index and note handles to DNA match data (#607)
* Add person references index and note handles to DNA match data * Optionally add raw data
1 parent 9e9d30e commit dab5b82

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

gramps_webapi/api/resources/dna.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@
2929
from gramps.gen.const import GRAMPS_LOCALE as glocale
3030
from gramps.gen.db.base import DbReadBase
3131
from gramps.gen.errors import HandleError
32-
from gramps.gen.lib import Note, Person, PersonRef
32+
from gramps.gen.lib import Citation, Note, Person
3333
from gramps.gen.relationship import get_relationship_calculator
3434
from gramps.gen.utils.grampslocale import GrampsLocale
3535
from webargs import fields, validate
3636

3737
from gramps_webapi.api.people_families_cache import CachePeopleFamiliesProxy
38-
from gramps_webapi.types import ResponseReturnValue
38+
from gramps_webapi.types import Handle, ResponseReturnValue
3939

4040
from ...types import Handle
4141
from ..util import get_db_handle, get_locale_for_language, use_args
@@ -57,6 +57,7 @@ class PersonDnaMatchesResource(ProtectedResource):
5757
"locale": fields.Str(
5858
load_default=None, validate=validate.Length(min=2, max=5)
5959
),
60+
"raw": fields.Bool(load_default=False),
6061
},
6162
location="query",
6263
)
@@ -65,23 +66,27 @@ def get(self, args: dict, handle: str):
6566
db_handle = CachePeopleFamiliesProxy(get_db_handle())
6667

6768
try:
68-
person = db_handle.get_person_from_handle(handle)
69+
person: Person | None = db_handle.get_person_from_handle(handle)
6970
except HandleError:
7071
abort(404)
72+
if person is None:
73+
abort(404)
74+
raise AssertionError # for type checker
7175

7276
db_handle.cache_people()
7377
db_handle.cache_families()
7478

7579
locale = get_locale_for_language(args["locale"], default=True)
7680

7781
matches = []
78-
for association in person.get_person_ref_list():
82+
for association_index, association in enumerate(person.get_person_ref_list()):
7983
if association.get_relation() == "DNA":
8084
match_data = get_match_data(
8185
db_handle=db_handle,
8286
person=person,
83-
association=association,
87+
association_index=association_index,
8488
locale=locale,
89+
include_raw_data=args["raw"],
8590
)
8691
matches.append(match_data)
8792
return matches
@@ -102,11 +107,13 @@ def post(self, args: dict) -> ResponseReturnValue:
102107
def get_match_data(
103108
db_handle: DbReadBase,
104109
person: Person,
105-
association: PersonRef,
110+
association_index: int,
106111
locale: GrampsLocale = glocale,
112+
include_raw_data: bool = False,
107113
) -> dict[str, Any]:
108114
"""Get the DNA match data in the appropriate format."""
109115
relationship = get_relationship_calculator(reinit=True, clocale=locale)
116+
association = person.get_person_ref_list()[association_index]
110117
associate = db_handle.get_person_from_handle(association.ref)
111118
data, _ = relationship.get_relationship_distance_new(
112119
db_handle,
@@ -134,15 +141,24 @@ def get_match_data(
134141
segments = []
135142

136143
# Get Notes attached to Association
137-
note_handles = association.get_note_list()
144+
note_handles: list[Handle] = association.get_note_list()
145+
# we'll be building a list of notes that actually contain segment data
146+
note_handles_with_segments: list[Handle] = []
138147

139148
# Get Notes attached to Citation which is attached to the Association
140149
for citation_handle in association.get_citation_list():
141-
citation = db_handle.get_citation_from_handle(citation_handle)
142-
note_handles += citation.get_note_list()
150+
try:
151+
citation: Citation = db_handle.get_citation_from_handle(citation_handle)
152+
except HandleError:
153+
continue
154+
if citation is not None:
155+
note_handles += citation.get_note_list()
143156

144157
for note_handle in note_handles:
145-
segments += get_segments_from_note(db_handle, handle=note_handle, side=side)
158+
note_segments = get_segments_from_note(db_handle, handle=note_handle, side=side)
159+
if note_segments:
160+
segments += note_segments
161+
note_handles_with_segments.append(note_handle)
146162

147163
rel_strings, common_ancestors = relationship.get_all_relationships(
148164
db_handle, person, associate
@@ -159,20 +175,34 @@ def get_match_data(
159175
)
160176
for handle in ancestor_handles
161177
]
162-
return {
178+
result = {
163179
"handle": association.ref,
164180
"segments": segments,
165181
"relation": rel_string,
166182
"ancestor_handles": ancestor_handles,
167183
"ancestor_profiles": ancestor_profiles,
184+
"person_ref_idx": association_index,
185+
"note_handles": note_handles_with_segments,
168186
}
187+
if include_raw_data:
188+
raw_data = []
189+
for note_handle in note_handles_with_segments:
190+
note: Note = db_handle.get_note_from_handle(note_handle)
191+
raw_data.append(note.get())
192+
result["raw_data"] = raw_data
193+
return result
169194

170195

171196
def get_segments_from_note(
172197
db_handle: DbReadBase, handle: Handle, side: str | None = None
173198
) -> list[Segment]:
174199
"""Get the segements from a note handle."""
175-
note: Note = db_handle.get_note_from_handle(handle)
200+
try:
201+
note: Note | None = db_handle.get_note_from_handle(handle)
202+
except HandleError:
203+
return []
204+
if note is None:
205+
return []
176206
raw_string: str = note.get()
177207
return parse_raw_dna_match_string(raw_string, side=side)
178208

gramps_webapi/data/apispec.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,12 @@ paths:
12941294
required: false
12951295
type: string
12961296
description: "Specifies the locale to be used where applicable if one other than the current default is desired. Should be a valid language code from the available list of translations."
1297+
- name: raw
1298+
in: query
1299+
required: false
1300+
type: boolean
1301+
default: false
1302+
description: "Indicates whether to include the raw data for the matches or not."
12971303
responses:
12981304
200:
12991305
description: "OK: Successful operation."
@@ -10786,6 +10792,22 @@ definitions:
1078610792
type: array
1078710793
items:
1078810794
$ref: "#/definitions/DnaSegment"
10795+
person_ref_idx:
10796+
description: The index of the associated person in the original person's person reference list
10797+
type: integer
10798+
example: 0
10799+
note_handles:
10800+
description: The handles of notes associated with the segments of the match
10801+
type: array
10802+
items:
10803+
type: string
10804+
example: 9BXKQC1PVLPYFMD6IX
10805+
raw_data:
10806+
description: The raw note strings
10807+
type: array
10808+
items:
10809+
type: string
10810+
example: "1,1,1,1"
1078910811

1079010812

1079110813
##############################################################################

0 commit comments

Comments
 (0)