Skip to content

Commit

Permalink
Add set_by_path function
Browse files Browse the repository at this point in the history
  • Loading branch information
pavlushkin committed Jul 4, 2023
1 parent 08fcacc commit f00a017
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 2 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ You can test this library by interactive FHIR course in the repository [Aidbox/j
- [Validate resource using operation $validate](#validate-resource-using-operation-validate)
- [Accessing resource attributes](#accessing-resource-attributes)
- [get_by_path(path, default=None)](#get_by_pathpath-defaultnone)
- [set_by_path(obj, path, value)](#set_by_pathpath)
- [serialize()](#serialize)
- [Reference](#reference-1)
- [Main class structure](#main-class-structure)
Expand Down Expand Up @@ -403,6 +404,18 @@ base_value = invoice.get_by_path([
'amount', 'value'], 0)
```

## set_by_path(obj, path, value)
```python
resource = {
"name": [{"given": ["Firstname"], "family": "Lastname"}],
}

set_by_path(resource, ["name", 0, "given", 0], "FirstnameUpdated")

# resource
# {"name": [{"given": ["FirstnameUpdated"], "family": "Lastname"}]}
```

## serialize()
```Python
# Returns resources as dict
Expand Down
2 changes: 1 addition & 1 deletion fhirpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .lib import SyncFHIRClient, AsyncFHIRClient

__title__ = "fhir-py"
__version__ = "1.3.1"
__version__ = "1.3.2"
__author__ = "beda.software"
__license__ = "None"
__copyright__ = "Copyright 2022 beda.software"
Expand Down
21 changes: 21 additions & 0 deletions fhirpy/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,26 @@ def get_by_path(data, path, default=None):
return default


def set_by_path(obj, path, value):
cursor = obj
last_part = path.pop()

for index, part in enumerate(path):
if isinstance(cursor, dict) and part not in cursor:
nextpart = (path + [last_part])[index + 1]
try:
nnextpart = (path + [last_part])[index + 2]
except IndexError:
nnextpart = ""

if isinstance(nextpart, int):
cursor[part] = [[] if isinstance(nnextpart, int) else {}]
else:
cursor[part] = {}

cursor = cursor[part]
cursor[last_part] = value


def remove_prefix(s, prefix):
return s[len(prefix) :] if s.startswith(prefix) else s
25 changes: 24 additions & 1 deletion tests/test_lib_base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest
from fhirpy import SyncFHIRClient, AsyncFHIRClient
from fhirpy.lib import BaseFHIRReference
from fhirpy.base.utils import AttrDict, SearchList, parse_pagination_url
from fhirpy.base.utils import AttrDict, SearchList, parse_pagination_url, set_by_path


@pytest.mark.parametrize("client", [SyncFHIRClient("mock"), AsyncFHIRClient("mock")])
Expand Down Expand Up @@ -146,6 +146,29 @@ def test_get_by_path(self, client):
assert isinstance(name, AttrDict)
assert name.get_by_path(["given", 0]) == "Firstname"

def test_set_by_path(self, client):
resource = {
"name": [{"given": ["Firstname"], "family": "Lastname"}],
}

resource1 = resource.copy()
set_by_path(resource1, ["name", 0, "given", 0], "FirstnameUpdated")
assert resource1["name"][0]["given"][0] == "FirstnameUpdated"

resource2 = resource.copy()
with pytest.raises(IndexError):
set_by_path(resource2, ["name", 1, "given", 0], "FirstnameUpdated")

resource3 = resource.copy()
set_by_path(resource3, ["name"], None)
assert resource3["name"] == None

resource4 = resource.copy()
set_by_path(resource4, ["name", 0], {"text": "Firstname Lastname"})
assert resource4["name"][0]["text"] == "Firstname Lastname"
with pytest.raises(KeyError):
assert resource4["name"][0]["given"]

def test_set_resource_setdefault(self, client):
resource = client.resource("Patient", id="patient")
resource.setdefault("id", "new_patient")
Expand Down

0 comments on commit f00a017

Please sign in to comment.