Skip to content

Commit 7b6b70e

Browse files
authored
Modifies data model to distinguish between IDs pardner creates and IDs the service creates (#72)
Part of #45 The code for translating JSON to a vertical model object is messy and lengthy, so for the future, this is something I'm considering: #71 This PR also renames the parsing methods for consistency.
1 parent 5e57cc1 commit 7b6b70e

4 files changed

Lines changed: 43 additions & 11 deletions

File tree

src/pardner/services/strava.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ def _convert_to_datetime(self, raw_datetime: str | None) -> datetime | None:
7373
return datetime.strptime(raw_datetime, '%Y-%m-%dT%H:%M:%SZ')
7474
return None
7575

76-
def _parse_social_posting(self, raw_data: Any) -> SocialPostingVertical | None:
76+
def parse_social_posting_vertical(
77+
self, raw_data: Any
78+
) -> SocialPostingVertical | None:
7779
"""
7880
Given the response from the API request, creates a
7981
:class:`SocialPostingVertical` model object, if possible.
@@ -114,8 +116,12 @@ def _parse_social_posting(self, raw_data: Any) -> SocialPostingVertical | None:
114116
for photo_url in photo_urls
115117
]
116118

119+
athlete_id = str(raw_data_dict['athlete'].get('id'))
120+
117121
return SocialPostingVertical(
118-
creator_user_id=str(raw_data_dict['athlete'].get('id')),
122+
creator_user_id=athlete_id,
123+
data_owner_id=athlete_id,
124+
service_object_id=raw_data_dict.get('id'),
119125
service=self._service_name,
120126
created_at=created_at,
121127
url=url_str,
@@ -150,15 +156,15 @@ def fetch_social_posting_vertical(
150156
'athlete/activities', params={'per_page': count, **request_params}
151157
).json()
152158
return [
153-
self._parse_social_posting(raw_social_posting)
159+
self.parse_social_posting_vertical(raw_social_posting)
154160
for raw_social_posting in raw_social_postings
155161
], raw_social_postings
156162
raise UnsupportedRequestException(
157163
self._service_name,
158164
f'can only make a request for at most {max_count} posts at a time.',
159165
)
160166

161-
def _parse_physical_activity(
167+
def parse_physical_activity_vertical(
162168
self, raw_data: Any
163169
) -> PhysicalActivityVertical | None:
164170
"""
@@ -170,7 +176,7 @@ def _parse_physical_activity(
170176
:returns: :class:`PhysicalActivityVertical` or ``None``, depending on whether it
171177
was possible to extract data from the response
172178
"""
173-
social_posting = self._parse_social_posting(raw_data)
179+
social_posting = self.parse_social_posting_vertical(raw_data)
174180
if not social_posting:
175181
return None
176182

@@ -233,7 +239,7 @@ def fetch_physical_activity_vertical(
233239
'athlete/activities', params={'per_page': count, **request_params}
234240
).json()
235241
return [
236-
self._parse_physical_activity(raw_activity)
242+
self.parse_physical_activity_vertical(raw_activity)
237243
for raw_activity in raw_activities
238244
], raw_activities
239245
raise UnsupportedRequestException(

src/pardner/verticals/base.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from datetime import datetime
44
from typing import Type
55

6-
from pydantic import AnyHttpUrl, BaseModel, Field
6+
from pydantic import AnyHttpUrl, BaseModel, ConfigDict, Field
77

88

99
class BaseVertical(BaseModel, ABC):
@@ -13,8 +13,28 @@ class BaseVertical(BaseModel, ABC):
1313
supported by every transfer service.
1414
"""
1515

16-
id: str = Field(default_factory=lambda: uuid.uuid4().hex)
17-
creator_user_id: str
16+
model_config = ConfigDict(coerce_numbers_to_str=True)
17+
18+
pardner_object_id: str = Field(
19+
default_factory=lambda: uuid.uuid4().hex,
20+
description='The id of the vertical object for identification from pardner. '
21+
'Differs from the service_generated_id, which is created by the service.',
22+
)
23+
service_object_id: str | None = Field(
24+
description='The id of the vertical object, generated by the service itself '
25+
'rather than pardner.',
26+
default=None,
27+
)
28+
29+
creator_user_id: str | None = Field(
30+
description='The user who created the vertical. '
31+
'May or may not be the data owner. Generated by the service.',
32+
default=None,
33+
)
34+
data_owner_id: str = Field(
35+
description='The id of the user whose data the vertical object comes from. '
36+
'Generated by the service.'
37+
)
1838
service: str = Field(
1939
description='The name of the service the data was pulled from.'
2040
)

src/pardner/verticals/conversation_direct.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ class ConversationDirectVertical(ConversationVertical):
88
"""
99

1010
vertical_name: str = 'conversation_direct'
11+
1112
is_group_conversation: bool = False
13+
members_count: int = 2

tests/test_transfer_services/test_strava.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,12 @@ def test_fetch_physical_activity_vertical(mocker, mock_strava_transfer_service):
174174
)
175175

176176
model_obj1_json = model_obj1.model_dump()
177-
del model_obj1_json['id']
177+
del model_obj1_json['pardner_object_id']
178178

179179
assert model_obj1_json == {
180+
'service_object_id': '154504250376823',
180181
'creator_user_id': '134815',
182+
'data_owner_id': '134815',
181183
'service': 'Strava',
182184
'vertical_name': 'physical_activity',
183185
'created_at': datetime.datetime(2018, 5, 2, 12, 15, 9),
@@ -216,10 +218,12 @@ def test_fetch_physical_activity_vertical(mocker, mock_strava_transfer_service):
216218
}
217219

218220
model_obj2_json = model_obj2.model_dump()
219-
del model_obj2_json['id']
221+
del model_obj2_json['pardner_object_id']
220222

221223
assert model_obj2_json == {
224+
'service_object_id': '1234567809',
222225
'creator_user_id': '167560',
226+
'data_owner_id': '167560',
223227
'service': 'Strava',
224228
'vertical_name': 'physical_activity',
225229
'created_at': datetime.datetime(2018, 4, 30, 12, 35, 51),

0 commit comments

Comments
 (0)