mphapi 1.12.1__tar.gz → 1.12.2__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.
- {mphapi-1.12.1 → mphapi-1.12.2}/PKG-INFO +2 -3
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/__init__.py +2 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/credentials.py +64 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/pricing.py +0 -3
- {mphapi-1.12.1 → mphapi-1.12.2}/pyproject.toml +1 -1
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/claim.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/client.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/client_test.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/date.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/env.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/fields.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/py.typed +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/response.py +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/snapshots/client_test/test_client/hcfa.json +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/snapshots/client_test/test_client/inpatient.json +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/snapshots/client_test/test_client/outpatient.json +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/testdata/hcfa.json +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/testdata/inpatient.json +0 -0
- {mphapi-1.12.1 → mphapi-1.12.2}/mphapi/testdata/outpatient.json +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: mphapi
|
|
3
|
-
Version: 1.12.
|
|
3
|
+
Version: 1.12.2
|
|
4
4
|
Summary: A Python interface to the MyPriceHealth API
|
|
5
5
|
Author: David Archibald
|
|
6
6
|
Author-email: davidarchibald@myprice.health
|
|
7
7
|
Requires-Python: >=3.12,<4.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
11
10
|
Requires-Dist: pydantic (>=2.6.4,<3.0.0)
|
|
12
11
|
Requires-Dist: python-dotenv (>=1.1.1,<2.0.0)
|
|
13
12
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from .claim import * # noqa: F403, F401
|
|
2
2
|
from .client import * # noqa: F403, F401
|
|
3
|
+
from .credentials import * # noqa: F403, F401
|
|
3
4
|
from .date import * # noqa: F403, F401
|
|
5
|
+
from .fields import * # noqa: F403, F401
|
|
4
6
|
from .pricing import * # noqa: F403, F401
|
|
5
7
|
from .response import * # noqa: F403, F401
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import binascii
|
|
1
3
|
import getpass
|
|
2
4
|
import json
|
|
3
5
|
import os
|
|
4
6
|
import time
|
|
5
7
|
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
6
9
|
|
|
7
10
|
import requests
|
|
8
11
|
from pydantic import BaseModel, Field, RootModel
|
|
@@ -140,6 +143,23 @@ class RefreshTokenResult(BaseModel):
|
|
|
140
143
|
"""Your Google Cloud project ID."""
|
|
141
144
|
|
|
142
145
|
|
|
146
|
+
class Token(BaseModel):
|
|
147
|
+
"""
|
|
148
|
+
The decoded ID token from SignInResult or RefreshTokenResult.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
issuer: str
|
|
152
|
+
email: str
|
|
153
|
+
subject: str
|
|
154
|
+
audience: str
|
|
155
|
+
authorized_party: str
|
|
156
|
+
expiration: int
|
|
157
|
+
issued_at: int
|
|
158
|
+
login_id: str # not to be confused with the user_id claim, the firebase id
|
|
159
|
+
roles: list[str]
|
|
160
|
+
login_name: str # not to be confused with the name claim, the name in firebase
|
|
161
|
+
|
|
162
|
+
|
|
143
163
|
def get_credentials(api_key: str, referer: str) -> Credentials:
|
|
144
164
|
credentials_path = get_credentials_path()
|
|
145
165
|
|
|
@@ -254,3 +274,47 @@ def sign_in(api_key: str, email: str, password: str) -> RawCredentials:
|
|
|
254
274
|
)
|
|
255
275
|
|
|
256
276
|
return credentials
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# decode_jwt will parse a JWT payload without verifying that it is cryptographically valid.
|
|
280
|
+
# Code is simplified from https://github.com/jpadilla/pyjwt
|
|
281
|
+
def decode_jwt(jwt: str) -> Token:
|
|
282
|
+
try:
|
|
283
|
+
signing_input, _ = jwt.rsplit(".", 1)
|
|
284
|
+
_, payload_segment = signing_input.split(".", 1)
|
|
285
|
+
except Exception as err:
|
|
286
|
+
raise Exception("Expected token with 3 segments") from err
|
|
287
|
+
|
|
288
|
+
try:
|
|
289
|
+
payload_decoded = base64url_decode(payload_segment)
|
|
290
|
+
except (TypeError, binascii.Error) as err:
|
|
291
|
+
raise Exception("Invalid payload padding") from err
|
|
292
|
+
|
|
293
|
+
try:
|
|
294
|
+
payload: dict[str, Any] = json.loads(payload_decoded)
|
|
295
|
+
except ValueError as e:
|
|
296
|
+
raise Exception(f"Invalid payload string: {e}") from e
|
|
297
|
+
|
|
298
|
+
return Token(
|
|
299
|
+
issuer=payload.get("iss", ""),
|
|
300
|
+
email=payload.get("email", ""),
|
|
301
|
+
subject=payload.get("sub", ""),
|
|
302
|
+
audience=payload.get("aud", ""),
|
|
303
|
+
authorized_party=payload.get("azp", ""),
|
|
304
|
+
expiration=payload.get("exp", 0),
|
|
305
|
+
issued_at=payload.get("iat", 0),
|
|
306
|
+
login_id=payload.get("login_id", ""),
|
|
307
|
+
roles=payload.get("roles", []),
|
|
308
|
+
login_name=payload.get("login_name", ""),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def base64url_decode(input: str) -> bytes:
|
|
313
|
+
input_bytes = input.encode("utf-8")
|
|
314
|
+
|
|
315
|
+
rem = len(input_bytes) % 4
|
|
316
|
+
|
|
317
|
+
if rem > 0:
|
|
318
|
+
input_bytes += b"=" * (4 - rem)
|
|
319
|
+
|
|
320
|
+
return base64.urlsafe_b64decode(input_bytes)
|
|
@@ -4,7 +4,6 @@ from typing import Annotated, Optional
|
|
|
4
4
|
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
6
|
from .client import PriceConfig
|
|
7
|
-
from .date import DateTime
|
|
8
7
|
from .fields import camel_case_model_config, field_name
|
|
9
8
|
from .response import ResponseError
|
|
10
9
|
|
|
@@ -464,8 +463,6 @@ class StepAndStatus(BaseModel):
|
|
|
464
463
|
class ClaimStatus(StepAndStatus):
|
|
465
464
|
model_config = camel_case_model_config
|
|
466
465
|
|
|
467
|
-
updated_by: Optional[str] = None
|
|
468
|
-
updated_at: Optional[DateTime] = None
|
|
469
466
|
pricing: Optional[Pricing] = None
|
|
470
467
|
error: Optional[ResponseError] = None
|
|
471
468
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|