Skip to content

Commit f7b5ce4

Browse files
author
t.mestan-zade
committed
Merge branch 'SC-1453' into 'develop'
SC-1453: Add method for updating top metadata See merge request SOLO-band/python-sdk!91
2 parents c132a84 + ee3b574 commit f7b5ce4

File tree

4 files changed

+132
-7
lines changed

4 files changed

+132
-7
lines changed

src/rogii_solo/exceptions.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
from typing import Optional
2+
3+
14
class BaseRogiiSoloException(Exception):
2-
pass
5+
default_message = 'Error occurred.'
6+
7+
def __init__(self, message: Optional[str] = None):
8+
self.message = message or self.default_message
9+
10+
def __str__(self):
11+
return str(self.message)
312

413

514
class ProjectNotFoundException(BaseRogiiSoloException):
@@ -16,3 +25,7 @@ class TraceNotFoundException(BaseRogiiSoloException):
1625

1726
class InterpretationOutOfTrajectoryException(BaseRogiiSoloException):
1827
pass
28+
29+
30+
class InvalidTopDataException(BaseRogiiSoloException):
31+
default_message = 'Measured depth value in project units must be in [0; 100000] range.'

src/rogii_solo/papi/base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,3 +1308,10 @@ def replace_well_trajectory(
13081308
}
13091309

13101310
return self._send_put_request(url=url, request_data=request_data, headers=headers)
1311+
1312+
def update_top_meta(self, top_id: str, name: str, md: PapiVar, headers: Optional[Dict] = None) -> bool:
1313+
url = f'tops/{top_id}'
1314+
request_data = {'name': name, 'md': md}
1315+
response = self._send_patch_request(url=url, request_data=request_data, headers=headers)
1316+
1317+
return response.status_code == status_codes.ok

src/rogii_solo/topset.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
from pandas import DataFrame
44

55
import rogii_solo.well
6-
from rogii_solo.base import BaseObject, ComplexObject, ObjectRepository
6+
from rogii_solo.base import ComplexObject, ObjectRepository
77
from rogii_solo.calculations.converters import feet_to_meters
8+
from rogii_solo.exceptions import InvalidTopDataException
89
from rogii_solo.papi.client import PapiClient
910
from rogii_solo.papi.types import PapiStarredTops
1011
from rogii_solo.utils.objects import find_by_uuid
@@ -40,7 +41,8 @@ def tops(self) -> ObjectRepository['Top']:
4041
if self._tops is None:
4142
self._tops = ObjectRepository(
4243
objects=[
43-
Top(topset=self, **item) for item in self._papi_client.get_topset_tops_data(topset_id=self.uuid)
44+
Top(papi_client=self._papi_client, topset=self, **item)
45+
for item in self._papi_client.get_topset_tops_data(topset_id=self.uuid)
4446
]
4547
)
4648

@@ -71,6 +73,9 @@ def starred_top_bottom(self):
7173
return self._starred_top_bottom
7274

7375
def create_top(self, name: str, md: float):
76+
if not 0 <= md <= 100000:
77+
raise InvalidTopDataException
78+
7479
top_id = self._papi_client.create_topset_top(
7580
topset_id=self.uuid, name=name, md=self._papi_client.prepare_papi_var(md)
7681
)
@@ -90,8 +95,10 @@ def _get_starred_tops_data(self):
9095
return self._starred_tops_data
9196

9297

93-
class Top(BaseObject):
94-
def __init__(self, topset: Topset, **kwargs):
98+
class Top(ComplexObject):
99+
def __init__(self, papi_client: PapiClient, topset: Topset, **kwargs):
100+
super().__init__(papi_client)
101+
95102
self.topset = topset
96103
self.measure_units = topset.well.project.measure_unit
97104

@@ -111,3 +118,21 @@ def to_dict(self, get_converted: bool = True) -> Dict[str, Any]:
111118

112119
def to_df(self, get_converted: bool = True) -> DataFrame:
113120
return DataFrame([self.to_dict(get_converted)])
121+
122+
def update_meta(self, name: str, md: float):
123+
if not 0 <= md <= 100000:
124+
raise InvalidTopDataException
125+
126+
func_data = {
127+
func_param: func_arg
128+
for func_param, func_arg in locals().items()
129+
if func_arg is not None and func_param != 'self'
130+
}
131+
request_data = {key: self._papi_client.prepare_papi_var(value) for key, value in func_data.items()}
132+
133+
is_updated = self._papi_client.update_top_meta(top_id=self.uuid, **request_data)
134+
135+
if is_updated:
136+
self.__dict__.update(func_data)
137+
138+
return self

tests/test_solo_client_papi.py

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
from math import fabs
33
from typing import Any
44

5+
import pytest
6+
57
from rogii_solo.calculations.constants import DELTA
68
from rogii_solo.calculations.interpretation import get_segments, get_segments_with_dip
79
from rogii_solo.calculations.trajectory import calculate_trajectory
10+
from rogii_solo.exceptions import InvalidTopDataException
811
from tests.papi_data import (
912
EI_LAST_SEGMENT_EXTENDED_NAME,
1013
LOG_NAME,
1114
NESTED_WELL_NAME,
1215
STARRED_NESTED_WELL_NAME,
13-
STARRED_TOPSET_NAME,
1416
TYPEWELL_NAME,
1517
WELL_NAME,
1618
)
@@ -229,11 +231,27 @@ def test_create_typewell_log(project_papi):
229231
assert typewell.logs.find_by_name(log_name) is not None
230232

231233

234+
def test_update_log_meta(project_papi):
235+
well = project_papi.wells.find_by_name(WELL_NAME)
236+
assert well is not None
237+
238+
log = well.logs.find_by_name(LOG_NAME)
239+
assert log is not None
240+
241+
input_data = {
242+
'name': f'Log {random.randint(0, 10000)}',
243+
}
244+
log.update_meta(**input_data)
245+
246+
log_data = log.to_dict()
247+
assert log_data['name'] == input_data['name']
248+
249+
232250
def test_create_topset_top(project_papi):
233251
well = project_papi.wells.find_by_name(WELL_NAME)
234252
assert well is not None
235253

236-
topset = well.topsets.find_by_name(STARRED_TOPSET_NAME)
254+
topset = well.starred_topset
237255
assert topset is not None
238256

239257
input_data = {
@@ -251,6 +269,68 @@ def test_create_topset_top(project_papi):
251269
assert np_is_close(top_data['md'], input_data['md'])
252270

253271

272+
def test_create_topset_top_with_invalid_md(project_papi):
273+
well = project_papi.wells.find_by_name(WELL_NAME)
274+
assert well is not None
275+
276+
topset = well.starred_topset
277+
assert topset is not None
278+
279+
input_data = {
280+
'name': f'Top {random.randint(0, 10000)}',
281+
'md': -1,
282+
}
283+
with pytest.raises(InvalidTopDataException):
284+
topset.create_top(**input_data)
285+
286+
input_data = {
287+
'name': f'Top {random.randint(0, 10000)}',
288+
'md': 1000001,
289+
}
290+
with pytest.raises(InvalidTopDataException):
291+
topset.create_top(**input_data)
292+
293+
294+
def test_update_topset_top_meta(project_papi):
295+
well = project_papi.wells.find_by_name(WELL_NAME)
296+
assert well is not None
297+
298+
top = well.starred_topset.starred_top_center
299+
assert top is not None
300+
301+
input_data = {
302+
'name': f'Top {random.randint(0, 10000)}',
303+
'md': random.randint(11400, 11500),
304+
}
305+
top.update_meta(**input_data)
306+
307+
top_data = top.to_dict()
308+
assert top_data['name'] == input_data['name']
309+
assert np_is_close(top_data['md'], input_data['md'])
310+
311+
312+
def test_update_topset_top_with_incorrect_md(project_papi):
313+
well = project_papi.wells.find_by_name(WELL_NAME)
314+
assert well is not None
315+
316+
top = well.starred_topset.starred_top_center
317+
assert top is not None
318+
319+
input_data = {
320+
'name': f'Top {random.randint(0, 10000)}',
321+
'md': -1,
322+
}
323+
with pytest.raises(InvalidTopDataException):
324+
top.update_meta(**input_data)
325+
326+
input_data = {
327+
'name': f'Top {random.randint(0, 10000)}',
328+
'md': 1000001,
329+
}
330+
with pytest.raises(InvalidTopDataException):
331+
top.update_meta(**input_data)
332+
333+
254334
def test_update_well_meta(project_papi):
255335
well = project_papi.wells.find_by_name(WELL_NAME)
256336
assert well is not None

0 commit comments

Comments
 (0)