medintell 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- medintell-0.1.0/.gitignore +7 -0
- medintell-0.1.0/LICENSE +21 -0
- medintell-0.1.0/PKG-INFO +92 -0
- medintell-0.1.0/README.md +81 -0
- medintell-0.1.0/medintell/__init__.py +6 -0
- medintell-0.1.0/medintell/client.py +235 -0
- medintell-0.1.0/pyproject.toml +19 -0
- medintell-0.1.0/tests/test_smoke.py +15 -0
medintell-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MedIntell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
medintell-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: medintell
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the MedIntell REST API.
|
|
5
|
+
Project-URL: Documentation, https://docs.medintell.co/api/sdks
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: api,fhir,healthcare,his,medintell,sdk
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# medintell
|
|
13
|
+
|
|
14
|
+
Official Python SDK for the [MedIntell REST API](https://docs.medintell.co/api/overview).
|
|
15
|
+
Zero third-party dependencies (standard-library only).
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install medintell
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quickstart
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import os
|
|
27
|
+
from medintell import MedIntell
|
|
28
|
+
|
|
29
|
+
mi = MedIntell(api_key=os.environ["MI_KEY"])
|
|
30
|
+
|
|
31
|
+
# Verify the connection
|
|
32
|
+
health = mi.health()
|
|
33
|
+
# {"status": "ok", "org_id": "org_3aK9Lm", "role": "manager", "facility_id": "fac_1B7dQ2"}
|
|
34
|
+
|
|
35
|
+
# Seed reference data in dependency order, reusing the returned ids
|
|
36
|
+
dept = mi.departments.create(name="Cardiology", facility_id="fac_1B7dQ2")
|
|
37
|
+
doc = mi.doctors.create(name="Dr. Shakshouka Hummusi", department_id=dept["id"], facility_id="fac_1B7dQ2")
|
|
38
|
+
payer = mi.payers.create(name="Falafel Assurance Co.")
|
|
39
|
+
|
|
40
|
+
patient = mi.patients.create(
|
|
41
|
+
mrn="MRN-2026-00001",
|
|
42
|
+
facility_id="fac_1B7dQ2",
|
|
43
|
+
first_name="Kabsa",
|
|
44
|
+
last_name="Al-Majboos",
|
|
45
|
+
dob="1985-03-15",
|
|
46
|
+
gender="M",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
visit = mi.visits.create(
|
|
50
|
+
facility_id="fac_1B7dQ2",
|
|
51
|
+
patient_mrn="MRN-2026-00001",
|
|
52
|
+
source_visit_id="V-2026-12345",
|
|
53
|
+
visit_date="2026-06-15T10:30:00",
|
|
54
|
+
type_of_visit="Consultation",
|
|
55
|
+
department_id=dept["id"],
|
|
56
|
+
doctor_id=doc["id"],
|
|
57
|
+
payer_id=payer["payer_id"],
|
|
58
|
+
total_cost=1500.0,
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Features
|
|
63
|
+
|
|
64
|
+
- **Resource model** — `mi.<resource>.<action>()` mirrors the REST API.
|
|
65
|
+
- **Auth** — the API key is attached to every request.
|
|
66
|
+
- **Idempotency** — every create sends an `Idempotency-Key` automatically; pass
|
|
67
|
+
`idempotency_key=...` to make a specific retry idempotent.
|
|
68
|
+
- **Retries** — `429` / `5xx` / network errors retry with backoff (honours `Retry-After`).
|
|
69
|
+
- **Cursor pagination** — `for patient in mi.patients.iterate(): ...`.
|
|
70
|
+
- **Typed errors** — failures raise `MedIntellError` with `.status`, `.code`, `.request_id`.
|
|
71
|
+
|
|
72
|
+
## Pagination
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
for patient in mi.patients.iterate(search="MRN-2026"):
|
|
76
|
+
print(patient["mrno"])
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Errors
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from medintell import MedIntell, MedIntellError
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
mi.patients.retrieve("pat_does_not_exist")
|
|
86
|
+
except MedIntellError as err:
|
|
87
|
+
print(err.status, err.code, err.request_id)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# medintell
|
|
2
|
+
|
|
3
|
+
Official Python SDK for the [MedIntell REST API](https://docs.medintell.co/api/overview).
|
|
4
|
+
Zero third-party dependencies (standard-library only).
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install medintell
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Quickstart
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import os
|
|
16
|
+
from medintell import MedIntell
|
|
17
|
+
|
|
18
|
+
mi = MedIntell(api_key=os.environ["MI_KEY"])
|
|
19
|
+
|
|
20
|
+
# Verify the connection
|
|
21
|
+
health = mi.health()
|
|
22
|
+
# {"status": "ok", "org_id": "org_3aK9Lm", "role": "manager", "facility_id": "fac_1B7dQ2"}
|
|
23
|
+
|
|
24
|
+
# Seed reference data in dependency order, reusing the returned ids
|
|
25
|
+
dept = mi.departments.create(name="Cardiology", facility_id="fac_1B7dQ2")
|
|
26
|
+
doc = mi.doctors.create(name="Dr. Shakshouka Hummusi", department_id=dept["id"], facility_id="fac_1B7dQ2")
|
|
27
|
+
payer = mi.payers.create(name="Falafel Assurance Co.")
|
|
28
|
+
|
|
29
|
+
patient = mi.patients.create(
|
|
30
|
+
mrn="MRN-2026-00001",
|
|
31
|
+
facility_id="fac_1B7dQ2",
|
|
32
|
+
first_name="Kabsa",
|
|
33
|
+
last_name="Al-Majboos",
|
|
34
|
+
dob="1985-03-15",
|
|
35
|
+
gender="M",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
visit = mi.visits.create(
|
|
39
|
+
facility_id="fac_1B7dQ2",
|
|
40
|
+
patient_mrn="MRN-2026-00001",
|
|
41
|
+
source_visit_id="V-2026-12345",
|
|
42
|
+
visit_date="2026-06-15T10:30:00",
|
|
43
|
+
type_of_visit="Consultation",
|
|
44
|
+
department_id=dept["id"],
|
|
45
|
+
doctor_id=doc["id"],
|
|
46
|
+
payer_id=payer["payer_id"],
|
|
47
|
+
total_cost=1500.0,
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **Resource model** — `mi.<resource>.<action>()` mirrors the REST API.
|
|
54
|
+
- **Auth** — the API key is attached to every request.
|
|
55
|
+
- **Idempotency** — every create sends an `Idempotency-Key` automatically; pass
|
|
56
|
+
`idempotency_key=...` to make a specific retry idempotent.
|
|
57
|
+
- **Retries** — `429` / `5xx` / network errors retry with backoff (honours `Retry-After`).
|
|
58
|
+
- **Cursor pagination** — `for patient in mi.patients.iterate(): ...`.
|
|
59
|
+
- **Typed errors** — failures raise `MedIntellError` with `.status`, `.code`, `.request_id`.
|
|
60
|
+
|
|
61
|
+
## Pagination
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
for patient in mi.patients.iterate(search="MRN-2026"):
|
|
65
|
+
print(patient["mrno"])
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Errors
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from medintell import MedIntell, MedIntellError
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
mi.patients.retrieve("pat_does_not_exist")
|
|
75
|
+
except MedIntellError as err:
|
|
76
|
+
print(err.status, err.code, err.request_id)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""MedIntell — official Python client for the MedIntell REST API.
|
|
2
|
+
|
|
3
|
+
Zero third-party dependencies (standard-library ``urllib``).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import random
|
|
10
|
+
import time
|
|
11
|
+
import urllib.error
|
|
12
|
+
import urllib.parse
|
|
13
|
+
import urllib.request
|
|
14
|
+
import uuid
|
|
15
|
+
from typing import Any, Iterator
|
|
16
|
+
|
|
17
|
+
DEFAULT_BASE_URL = "https://api.medintell.co"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MedIntellError(Exception):
|
|
21
|
+
"""Raised on any non-2xx API response or transport failure."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, message: str, *, status: int | None = None, code: str | None = None,
|
|
24
|
+
type: str | None = None, request_id: str | None = None):
|
|
25
|
+
super().__init__(message)
|
|
26
|
+
self.status = status
|
|
27
|
+
self.code = code
|
|
28
|
+
self.type = type
|
|
29
|
+
self.request_id = request_id
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _Http:
|
|
33
|
+
def __init__(self, api_key: str, base_url: str, timeout: float, max_retries: int):
|
|
34
|
+
if not api_key:
|
|
35
|
+
raise MedIntellError("api_key is required")
|
|
36
|
+
self._api_key = api_key
|
|
37
|
+
self._base_url = base_url.rstrip("/")
|
|
38
|
+
self._timeout = timeout
|
|
39
|
+
self._max_retries = max_retries
|
|
40
|
+
|
|
41
|
+
def request(self, method: str, path: str, *, query: dict | None = None,
|
|
42
|
+
body: Any | None = None, idempotency_key: str | None = None) -> Any:
|
|
43
|
+
url = self._base_url + path
|
|
44
|
+
if query:
|
|
45
|
+
clean = {k: v for k, v in query.items() if v is not None}
|
|
46
|
+
if clean:
|
|
47
|
+
url += "?" + urllib.parse.urlencode(clean)
|
|
48
|
+
|
|
49
|
+
data = json.dumps(body).encode() if body is not None else None
|
|
50
|
+
headers = {"Authorization": f"Bearer {self._api_key}", "Accept": "application/json"}
|
|
51
|
+
if data is not None:
|
|
52
|
+
headers["Content-Type"] = "application/json"
|
|
53
|
+
if method == "POST":
|
|
54
|
+
headers["Idempotency-Key"] = idempotency_key or str(uuid.uuid4())
|
|
55
|
+
|
|
56
|
+
attempt = 0
|
|
57
|
+
while True:
|
|
58
|
+
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
|
59
|
+
try:
|
|
60
|
+
with urllib.request.urlopen(req, timeout=self._timeout) as resp:
|
|
61
|
+
raw = resp.read().decode()
|
|
62
|
+
return json.loads(raw) if raw else {}
|
|
63
|
+
except urllib.error.HTTPError as e:
|
|
64
|
+
if e.code == 429 or e.code >= 500:
|
|
65
|
+
if attempt < self._max_retries:
|
|
66
|
+
retry_after = e.headers.get("Retry-After")
|
|
67
|
+
time.sleep(float(retry_after) if retry_after else 2 ** attempt * 0.2 + random.random() * 0.1)
|
|
68
|
+
attempt += 1
|
|
69
|
+
continue
|
|
70
|
+
raw = e.read().decode() if e.fp else ""
|
|
71
|
+
payload = json.loads(raw) if raw else {}
|
|
72
|
+
err = payload.get("error", {}) if isinstance(payload, dict) else {}
|
|
73
|
+
raise MedIntellError(
|
|
74
|
+
err.get("message") or f"HTTP {e.code}",
|
|
75
|
+
status=e.code,
|
|
76
|
+
code=err.get("code"),
|
|
77
|
+
type=err.get("type"),
|
|
78
|
+
request_id=err.get("request_id") or e.headers.get("X-Request-ID"),
|
|
79
|
+
) from None
|
|
80
|
+
except (urllib.error.URLError, TimeoutError) as e:
|
|
81
|
+
if attempt < self._max_retries:
|
|
82
|
+
time.sleep(2 ** attempt * 0.2 + random.random() * 0.1)
|
|
83
|
+
attempt += 1
|
|
84
|
+
continue
|
|
85
|
+
raise MedIntellError(f"network error: {e}") from None
|
|
86
|
+
|
|
87
|
+
def get(self, path, query=None):
|
|
88
|
+
return self.request("GET", path, query=query)
|
|
89
|
+
|
|
90
|
+
def post(self, path, body=None, idempotency_key=None):
|
|
91
|
+
return self.request("POST", path, body=body, idempotency_key=idempotency_key)
|
|
92
|
+
|
|
93
|
+
def put(self, path, body=None):
|
|
94
|
+
return self.request("PUT", path, body=body)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class _Resource:
|
|
98
|
+
def __init__(self, http: _Http, base: str):
|
|
99
|
+
self._http = http
|
|
100
|
+
self._base = base
|
|
101
|
+
|
|
102
|
+
def iterate(self, **query) -> Iterator[dict]:
|
|
103
|
+
"""Yield every row, walking pages via the cursor."""
|
|
104
|
+
cursor = "" # empty cursor = keyset mode from page one
|
|
105
|
+
while True:
|
|
106
|
+
page = self._http.get(self._base, {"limit": 200, "cursor": cursor, **query})
|
|
107
|
+
for row in page.get("data", []):
|
|
108
|
+
yield row
|
|
109
|
+
if not page.get("has_more") or not page.get("next_cursor"):
|
|
110
|
+
return
|
|
111
|
+
cursor = page["next_cursor"]
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class _Organizations(_Resource):
|
|
115
|
+
def list(self):
|
|
116
|
+
return self._http.get(self._base)
|
|
117
|
+
|
|
118
|
+
def retrieve(self, org_id):
|
|
119
|
+
return self._http.get(f"{self._base}/{org_id}")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class _Facilities(_Resource):
|
|
123
|
+
def list(self):
|
|
124
|
+
return self._http.get(self._base)
|
|
125
|
+
|
|
126
|
+
def create(self, *, org_id, **body):
|
|
127
|
+
return self._http.post(f"/api/v1/organizations/{org_id}/branches", body)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class _Departments(_Resource):
|
|
131
|
+
def list(self, **query):
|
|
132
|
+
return self._http.get(self._base, query)
|
|
133
|
+
|
|
134
|
+
def retrieve(self, department_id):
|
|
135
|
+
return self._http.get(f"{self._base}/{department_id}")
|
|
136
|
+
|
|
137
|
+
def create(self, *, idempotency_key=None, **body):
|
|
138
|
+
return self._http.post(self._base, body, idempotency_key)
|
|
139
|
+
|
|
140
|
+
def update(self, department_id, **body):
|
|
141
|
+
return self._http.put(f"{self._base}/{department_id}", body)
|
|
142
|
+
|
|
143
|
+
def kpis(self, **query):
|
|
144
|
+
return self._http.get(f"{self._base}/kpis", query)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class _Doctors(_Resource):
|
|
148
|
+
def list(self, **query):
|
|
149
|
+
return self._http.get(self._base, query)
|
|
150
|
+
|
|
151
|
+
def retrieve(self, doctor_id):
|
|
152
|
+
return self._http.get(f"{self._base}/{doctor_id}")
|
|
153
|
+
|
|
154
|
+
def create(self, *, idempotency_key=None, **body):
|
|
155
|
+
return self._http.post(self._base, body, idempotency_key)
|
|
156
|
+
|
|
157
|
+
def update(self, doctor_id, **body):
|
|
158
|
+
return self._http.put(f"{self._base}/{doctor_id}", body)
|
|
159
|
+
|
|
160
|
+
def kpis(self, **query):
|
|
161
|
+
return self._http.get(f"{self._base}/kpis", query)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class _Payers(_Resource):
|
|
165
|
+
def list(self, **query):
|
|
166
|
+
return self._http.get(self._base, query)
|
|
167
|
+
|
|
168
|
+
def create(self, *, idempotency_key=None, **body):
|
|
169
|
+
return self._http.post(self._base, body, idempotency_key)
|
|
170
|
+
|
|
171
|
+
def update(self, payer_id, **body):
|
|
172
|
+
return self._http.put(f"{self._base}/{payer_id}", body)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class _Patients(_Resource):
|
|
176
|
+
def list(self, **query):
|
|
177
|
+
return self._http.get(self._base, query)
|
|
178
|
+
|
|
179
|
+
def retrieve(self, patient_id):
|
|
180
|
+
return self._http.get(f"{self._base}/{patient_id}")
|
|
181
|
+
|
|
182
|
+
def create(self, *, idempotency_key=None, **body):
|
|
183
|
+
return self._http.post(self._base, body, idempotency_key)
|
|
184
|
+
|
|
185
|
+
def update(self, patient_id, **body):
|
|
186
|
+
return self._http.put(f"{self._base}/{patient_id}", body)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class _Visits(_Resource):
|
|
190
|
+
def list(self, **query):
|
|
191
|
+
return self._http.get(self._base, query)
|
|
192
|
+
|
|
193
|
+
def stats(self):
|
|
194
|
+
return self._http.get(f"{self._base}/stats")
|
|
195
|
+
|
|
196
|
+
def create(self, *, idempotency_key=None, **body):
|
|
197
|
+
return self._http.post(self._base, body, idempotency_key)
|
|
198
|
+
|
|
199
|
+
def update(self, visit_id, **body):
|
|
200
|
+
return self._http.put(f"{self._base}/{visit_id}", body)
|
|
201
|
+
|
|
202
|
+
def correct_diagnosis(self, visit_id, **body):
|
|
203
|
+
return self._http.put(f"{self._base}/{visit_id}/diagnoses", body)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class _Ingest:
|
|
207
|
+
def __init__(self, http: _Http):
|
|
208
|
+
self._http = http
|
|
209
|
+
|
|
210
|
+
def patients(self, *, idempotency_key=None, **body):
|
|
211
|
+
return self._http.post("/api/v1/ingest/patients", body, idempotency_key)
|
|
212
|
+
|
|
213
|
+
def schema(self):
|
|
214
|
+
return self._http.get("/api/v1/ingest/schema")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class MedIntell:
|
|
218
|
+
"""Entry point. ``MedIntell(api_key=...)`` then ``client.<resource>.<action>()``."""
|
|
219
|
+
|
|
220
|
+
def __init__(self, api_key: str, *, base_url: str = DEFAULT_BASE_URL,
|
|
221
|
+
timeout: float = 30.0, max_retries: int = 2):
|
|
222
|
+
http = _Http(api_key, base_url, timeout, max_retries)
|
|
223
|
+
self._http = http
|
|
224
|
+
self.organizations = _Organizations(http, "/api/v1/organizations")
|
|
225
|
+
self.facilities = _Facilities(http, "/api/v1/branches")
|
|
226
|
+
self.departments = _Departments(http, "/api/v1/departments")
|
|
227
|
+
self.doctors = _Doctors(http, "/api/v1/doctors")
|
|
228
|
+
self.payers = _Payers(http, "/api/v1/payers")
|
|
229
|
+
self.patients = _Patients(http, "/api/v1/patients")
|
|
230
|
+
self.visits = _Visits(http, "/api/v1/visits")
|
|
231
|
+
self.ingest = _Ingest(http)
|
|
232
|
+
|
|
233
|
+
def health(self) -> dict:
|
|
234
|
+
"""Authenticated connectivity check."""
|
|
235
|
+
return self._http.get("/api/v1/health")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "medintell"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official Python SDK for the MedIntell REST API."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
keywords = ["medintell", "healthcare", "api", "sdk", "fhir", "his"]
|
|
13
|
+
dependencies = []
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Documentation = "https://docs.medintell.co/api/sdks"
|
|
17
|
+
|
|
18
|
+
[tool.hatch.build.targets.wheel]
|
|
19
|
+
packages = ["medintell"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from medintell import MedIntell, MedIntellError
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_constructs_resources():
|
|
6
|
+
mi = MedIntell(api_key="mi_live_test")
|
|
7
|
+
for r in ["organizations", "facilities", "departments", "doctors", "payers", "patients", "visits", "ingest"]:
|
|
8
|
+
assert hasattr(mi, r)
|
|
9
|
+
assert callable(mi.health)
|
|
10
|
+
assert callable(mi.patients.iterate)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_requires_api_key():
|
|
14
|
+
with pytest.raises(MedIntellError):
|
|
15
|
+
MedIntell(api_key="")
|