or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client.mdindex.mdreferences.mdresources.mdsearch.mdutilities.md

utilities.mddocs/

0

# Utilities

1

2

Helper functions and classes for data manipulation, parameter transformation, and path-based access. These utilities support common operations needed when working with FHIR data structures.

3

4

## Capabilities

5

6

### Dictionary and List Extensions

7

8

Enhanced dictionary and list classes with path-based access capabilities.

9

10

```python { .api }

11

class AttrDict(dict):

12

"""Dictionary with attribute-style access and path-based operations."""

13

14

def __init__(self, *args, **kwargs):

15

"""Initialize AttrDict from dict or keyword arguments."""

16

17

def get_by_path(self, path: str, default=None):

18

"""

19

Get value using dot-separated path.

20

21

Parameters:

22

- path: Dot-separated path string (e.g., 'address.0.city')

23

- default: Value to return if path not found

24

25

Returns:

26

Value at path or default

27

"""

28

29

class SearchList(list):

30

"""List with path-based access capabilities."""

31

32

def get_by_path(self, path: str, default=None):

33

"""

34

Get value using dot-separated path.

35

36

Parameters:

37

- path: Dot-separated path string

38

- default: Value to return if path not found

39

40

Returns:

41

Value at path or default

42

"""

43

```

44

45

### Collection Utilities

46

47

Functions for working with collections and data processing.

48

49

```python { .api }

50

def chunks(lst: list, n: int) -> Generator:

51

"""

52

Split list into chunks of specified size.

53

54

Parameters:

55

- lst: List to split

56

- n: Chunk size

57

58

Yields:

59

Sublists of size n (last chunk may be smaller)

60

"""

61

62

def unique_everseen(seq: list) -> list:

63

"""

64

Get unique items from sequence, preserving order.

65

66

Parameters:

67

- seq: Input sequence

68

69

Returns:

70

List with unique items in original order

71

"""

72

```

73

74

### Path Operations

75

76

Functions for parsing and manipulating dot-separated paths.

77

78

```python { .api }

79

def parse_path(path: str) -> list:

80

"""

81

Parse dot-separated path into list of keys.

82

83

Parameters:

84

- path: Dot-separated path string

85

86

Returns:

87

List of path components

88

"""

89

90

def get_by_path(obj, path: list, default=None):

91

"""

92

Get value from nested object using path list.

93

94

Parameters:

95

- obj: Object to traverse

96

- path: List of keys/indices

97

- default: Value to return if path not found

98

99

Returns:

100

Value at path or default

101

"""

102

103

def set_by_path(obj, path: str, value):

104

"""

105

Set value in nested object using dot-separated path.

106

107

Parameters:

108

- obj: Object to modify

109

- path: Dot-separated path string

110

- value: Value to set

111

"""

112

113

def convert_values(data, fn):

114

"""

115

Recursively convert data values using provided function.

116

117

Parameters:

118

- data: Data structure to convert (dict, list, or other)

119

- fn: Function that takes a value and returns (converted_value, stop_flag)

120

121

Returns:

122

Converted data structure with fn applied recursively

123

"""

124

```

125

126

### URL and Parameter Encoding

127

128

Functions for encoding parameters and working with URLs.

129

130

```python { .api }

131

def encode_params(params: dict) -> str:

132

"""

133

Encode parameters for URL query string.

134

135

Parameters:

136

- params: Dictionary of parameters

137

138

Returns:

139

URL-encoded query string

140

"""

141

```

142

143

### FHIR Date and Value Formatting

144

145

Functions for formatting dates and values according to FHIR specifications.

146

147

```python { .api }

148

def format_date_time(date: datetime) -> str:

149

"""

150

Format datetime for FHIR (ISO 8601 format).

151

152

Parameters:

153

- date: Python datetime object

154

155

Returns:

156

FHIR-formatted datetime string (YYYY-MM-DDTHH:MM:SSZ)

157

"""

158

159

def format_date(date: date) -> str:

160

"""

161

Format date for FHIR.

162

163

Parameters:

164

- date: Python date object

165

166

Returns:

167

FHIR-formatted date string (YYYY-MM-DD)

168

"""

169

170

def transform_param(param: str) -> str:

171

"""

172

Transform parameter name for FHIR (underscore to dash).

173

174

Parameters:

175

- param: Parameter name with underscores

176

177

Returns:

178

Parameter name with dashes (preserves leading underscore/dot)

179

"""

180

181

def transform_value(value) -> str:

182

"""

183

Transform value for FHIR search parameters.

184

185

Handles:

186

- datetime objects → ISO format strings

187

- date objects → YYYY-MM-DD strings

188

- bool → 'true'/'false' strings

189

- BaseResource/BaseReference → reference strings

190

191

Parameters:

192

- value: Value to transform

193

194

Returns:

195

String representation suitable for FHIR

196

"""

197

```

198

199

## Usage Examples

200

201

### Path-Based Data Access

202

203

```python

204

from fhirpy.base.utils import AttrDict, get_by_path, set_by_path, parse_path

205

206

def path_access_examples():

207

# AttrDict with attribute access

208

patient_data = AttrDict({

209

'name': [

210

{'family': 'Doe', 'given': ['John', 'William']},

211

{'family': 'Smith', 'given': ['Johnny'], 'use': 'nickname'}

212

],

213

'address': [{

214

'line': ['123 Main St', 'Apt 4B'],

215

'city': 'Springfield',

216

'postalCode': '12345'

217

}],

218

'telecom': [

219

{'system': 'phone', 'value': '555-1234'},

220

{'system': 'email', 'value': 'john@example.com'}

221

]

222

})

223

224

# Access using paths

225

family_name = patient_data.get_by_path('name.0.family') # 'Doe'

226

first_given = patient_data.get_by_path('name.0.given.0') # 'John'

227

street = patient_data.get_by_path('address.0.line.0') # '123 Main St'

228

phone = patient_data.get_by_path('telecom.0.value') # '555-1234'

229

230

# Safe access with defaults

231

fax = patient_data.get_by_path('telecom.2.value', 'No fax') # 'No fax'

232

233

print(f"Patient: {first_given} {family_name}")

234

print(f"Address: {street}, {patient_data.get_by_path('address.0.city')}")

235

236

# Attribute-style access

237

print(f"Name array: {patient_data.name}")

238

print(f"City: {patient_data.address[0]['city']}")

239

```

240

241

### Data Manipulation Utilities

242

243

```python

244

from fhirpy.base.utils import chunks, unique_everseen, set_by_path

245

246

def data_manipulation_examples():

247

# Split large datasets into manageable chunks

248

patient_ids = [f"patient-{i}" for i in range(1, 101)] # 100 patient IDs

249

250

# Process in chunks of 20

251

for chunk in chunks(patient_ids, 20):

252

print(f"Processing batch of {len(chunk)} patients")

253

# Process chunk...

254

255

# Remove duplicates while preserving order

256

search_params = ['name', 'birthdate', 'gender', 'name', 'active', 'gender']

257

unique_params = unique_everseen(search_params)

258

print(f"Unique parameters: {unique_params}") # ['name', 'birthdate', 'gender', 'active']

259

260

# Modify nested data structures

261

patient_data = {'name': [{'family': 'Doe'}]}

262

set_by_path(patient_data, 'name.0.given', ['John'])

263

set_by_path(patient_data, 'active', True)

264

set_by_path(patient_data, 'address.0.city', 'Springfield') # Creates nested structure

265

266

print(f"Modified patient: {patient_data}")

267

```

268

269

### FHIR Parameter Transformation

270

271

```python

272

import datetime

273

from fhirpy.base.utils import transform_param, transform_value, format_date_time, format_date

274

275

def parameter_transformation_examples():

276

# Parameter name transformation

277

fhir_param = transform_param('general_practitioner') # 'general-practitioner'

278

preserved = transform_param('_id') # '_id' (unchanged)

279

dot_param = transform_param('.effectiveDate') # '.effectiveDate' (unchanged)

280

281

print(f"Transformed: {fhir_param}")

282

283

# Value transformation for search parameters

284

now = datetime.datetime(2024, 1, 15, 10, 30, 0, tzinfo=datetime.timezone.utc)

285

today = datetime.date(2024, 1, 15)

286

287

datetime_str = transform_value(now) # '2024-01-15T10:30:00Z'

288

date_str = transform_value(today) # '2024-01-15'

289

bool_str = transform_value(True) # 'true'

290

false_str = transform_value(False) # 'false'

291

regular_str = transform_value('text') # 'text'

292

293

print(f"DateTime: {datetime_str}")

294

print(f"Date: {date_str}")

295

print(f"Boolean: {bool_str}")

296

297

# Direct date formatting

298

fhir_datetime = format_date_time(now) # '2024-01-15T10:30:00Z'

299

fhir_date = format_date(today) # '2024-01-15'

300

```

301

302

### URL Parameter Encoding

303

304

```python

305

from fhirpy.base.utils import encode_params

306

307

def parameter_encoding_examples():

308

# Simple parameters

309

params1 = {'name': ['Smith'], 'active': ['true']}

310

query1 = encode_params(params1) # 'name=Smith&active=true'

311

312

# Multiple values for same parameter

313

params2 = {'status:not': ['active', 'entered-in-error']}

314

query2 = encode_params(params2) # 'status:not=active&status:not=entered-in-error'

315

316

# Complex parameters with modifiers

317

params3 = {

318

'name:contains': ['John'],

319

'birthdate:ge': ['1990-01-01'],

320

'address-city': ['Springfield', 'Boston']

321

}

322

query3 = encode_params(params3)

323

324

print(f"Simple: {query1}")

325

print(f"Multiple: {query2}")

326

print(f"Complex: {query3}")

327

```

328

329

### Working with Search Results

330

331

```python

332

from fhirpy.base.utils import AttrDict, SearchList

333

import json

334

335

async def search_results_processing():

336

# Simulate FHIR Bundle response

337

bundle_data = {

338

'resourceType': 'Bundle',

339

'total': 3,

340

'entry': [

341

{

342

'resource': {

343

'resourceType': 'Patient',

344

'id': '1',

345

'name': [{'family': 'Doe', 'given': ['John']}],

346

'address': [{'city': 'Springfield'}]

347

}

348

},

349

{

350

'resource': {

351

'resourceType': 'Patient',

352

'id': '2',

353

'name': [{'family': 'Smith', 'given': ['Jane']}],

354

'address': [{'city': 'Boston'}]

355

}

356

}

357

]

358

}

359

360

# Convert to AttrDict for easier access

361

bundle = AttrDict(bundle_data)

362

363

# Extract patient data with path operations

364

patients = SearchList()

365

for entry in bundle.entry:

366

patient = AttrDict(entry.resource)

367

patients.append(patient)

368

369

# Process patients using path-based access

370

for patient in patients:

371

name = patient.get_by_path('name.0.family')

372

given = patient.get_by_path('name.0.given.0')

373

city = patient.get_by_path('address.0.city', 'Unknown')

374

375

print(f"Patient {patient.id}: {given} {name} from {city}")

376

377

# Aggregate data

378

cities = [p.get_by_path('address.0.city') for p in patients if p.get_by_path('address.0.city')]

379

unique_cities = unique_everseen(cities)

380

print(f"Cities represented: {unique_cities}")

381

```

382

383

### Utility Integration with FHIR Operations

384

385

```python

386

from fhirpy import AsyncFHIRClient

387

from fhirpy.base.utils import chunks, transform_value

388

import datetime

389

390

async def utility_integration_example():

391

client = AsyncFHIRClient('https://hapi.fhir.org/baseR4')

392

393

# Batch process large number of patients

394

patient_ids = [f"patient-{i}" for i in range(1, 101)]

395

396

all_patients = []

397

for id_chunk in chunks(patient_ids, 10): # Process 10 at a time

398

# Build search for this chunk

399

id_query = '|'.join(id_chunk) # FHIR OR syntax

400

401

patients = await (client.resources('Patient')

402

.search(_id=id_query)

403

.fetch())

404

all_patients.extend(patients)

405

406

print(f"Processed {len(all_patients)} patients")

407

408

# Use date transformation for search

409

cutoff_date = datetime.date(2020, 1, 1)

410

recent_patients = await (client.resources('Patient')

411

.search(birthdate__ge=transform_value(cutoff_date))

412

.fetch())

413

414

print(f"Found {len(recent_patients)} patients born after {cutoff_date}")

415

416

# Process results with path operations

417

for patient in recent_patients:

418

birth_date = patient.get_by_path('birthDate')

419

name = patient.get_by_path('name.0.family', 'Unknown')

420

print(f"{name}: {birth_date}")

421

```