diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2c1727..0a5b56e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: ci on: [push] jobs: compile: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -13,17 +13,32 @@ jobs: python-version: 3.7 - name: Bootstrap poetry run: | - curl -sSL https://install.python-poetry.org | python - -y + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 - name: Install dependencies run: poetry install - name: Compile run: poetry run mypy . + test: + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@v3 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.7 + - name: Bootstrap poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 + - name: Install dependencies + run: poetry install + - name: Test + run: poetry run pytest . publish: - needs: [ compile ] + needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-latest - + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -33,7 +48,7 @@ jobs: python-version: 3.7 - name: Bootstrap poetry run: | - curl -sSL https://install.python-poetry.org | python - -y + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 - name: Install dependencies run: poetry install - name: Publish to pypi @@ -42,4 +57,4 @@ jobs: poetry --no-interaction -v publish --build --repository remote --username "$PYPI_USERNAME" --password "$PYPI_PASSWORD" env: PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} - PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} \ No newline at end of file + PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} diff --git a/pyproject.toml b/pyproject.toml index c84f57d..f868b0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ - [tool.poetry] name = "fern-metriport" -version = "0.0.4" +version = "0.1.2" description = "" +readme = "README.md" authors = [] packages = [ { include = "metriport", from = "src"} @@ -10,13 +10,12 @@ packages = [ [tool.poetry.dependencies] python = "^3.7" -httpx = "0.23.3" +httpx = ">=0.21.2" pydantic = "^1.9.2" -types-backports = "0.1.3" -backports-cached_property = "1.0.2" [tool.poetry.dev-dependencies] mypy = "0.971" +pytest = "^7.4.0" [build-system] requires = ["poetry-core"] diff --git a/src/metriport/__init__.py b/src/metriport/__init__.py index b5a07c0..c9ca725 100644 --- a/src/metriport/__init__.py +++ b/src/metriport/__init__.py @@ -1,25 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from .environment import MercoaEnvironment -from .resources import ( - CodeableConcept, - Coding, - Document, - DownloadDocumentResponse, - GetDocumentsResponse, - QueryStatus, - TriggerDocumentsQueryResponse, - document, -) +from .resources import Address, UsState, commons, devices, medical +from .environment import MetriportEnvironment -__all__ = [ - "CodeableConcept", - "Coding", - "Document", - "DownloadDocumentResponse", - "GetDocumentsResponse", - "MercoaEnvironment", - "QueryStatus", - "TriggerDocumentsQueryResponse", - "document", -] +__all__ = ["Address", "MetriportEnvironment", "UsState", "commons", "devices", "medical"] diff --git a/src/metriport/client.py b/src/metriport/client.py index a2e22ff..3cc4bae 100644 --- a/src/metriport/client.py +++ b/src/metriport/client.py @@ -1,26 +1,55 @@ # This file was auto-generated by Fern from our API Definition. -from backports.cached_property import cached_property - -from .environment import MercoaEnvironment -from .resources.document.client import AsyncDocumentClient, DocumentClient - - -class Mercoa: - def __init__(self, *, environment: MercoaEnvironment = MercoaEnvironment.PRODUCTION, api_key: str): - self._environment = environment - self.api_key = api_key - - @cached_property - def document(self) -> DocumentClient: - return DocumentClient(environment=self._environment, api_key=self.api_key) - - -class AsyncMercoa: - def __init__(self, *, environment: MercoaEnvironment = MercoaEnvironment.PRODUCTION, api_key: str): - self._environment = environment - self.api_key = api_key - - @cached_property - def document(self) -> AsyncDocumentClient: - return AsyncDocumentClient(environment=self._environment, api_key=self.api_key) +import typing + +import httpx + +from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .environment import MetriportEnvironment +from .resources.devices.client import AsyncDevicesClient, DevicesClient +from .resources.medical.client import AsyncMedicalClient, MedicalClient + + +class Metriport: + def __init__( + self, + *, + base_url: typing.Optional[str] = None, + environment: MetriportEnvironment = MetriportEnvironment.PRODUCTION, + api_key: str, + timeout: typing.Optional[float] = 60 + ): + self._client_wrapper = SyncClientWrapper( + base_url=_get_base_url(base_url=base_url, environment=environment), + api_key=api_key, + httpx_client=httpx.Client(timeout=timeout), + ) + self.devices = DevicesClient(client_wrapper=self._client_wrapper) + self.medical = MedicalClient(client_wrapper=self._client_wrapper) + + +class AsyncMetriport: + def __init__( + self, + *, + base_url: typing.Optional[str] = None, + environment: MetriportEnvironment = MetriportEnvironment.PRODUCTION, + api_key: str, + timeout: typing.Optional[float] = 60 + ): + self._client_wrapper = AsyncClientWrapper( + base_url=_get_base_url(base_url=base_url, environment=environment), + api_key=api_key, + httpx_client=httpx.AsyncClient(timeout=timeout), + ) + self.devices = AsyncDevicesClient(client_wrapper=self._client_wrapper) + self.medical = AsyncMedicalClient(client_wrapper=self._client_wrapper) + + +def _get_base_url(*, base_url: typing.Optional[str] = None, environment: MetriportEnvironment) -> str: + if base_url is not None: + return base_url + elif environment is not None: + return environment.value + else: + raise Exception("Please pass in either base_url or environment to construct the client") diff --git a/src/metriport/core/__init__.py b/src/metriport/core/__init__.py index b213a1a..2414955 100644 --- a/src/metriport/core/__init__.py +++ b/src/metriport/core/__init__.py @@ -1,8 +1,17 @@ # This file was auto-generated by Fern from our API Definition. from .api_error import ApiError +from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper from .datetime_utils import serialize_datetime from .jsonable_encoder import jsonable_encoder -from .remove_none_from_headers import remove_none_from_headers +from .remove_none_from_dict import remove_none_from_dict -__all__ = ["ApiError", "jsonable_encoder", "remove_none_from_headers", "serialize_datetime"] +__all__ = [ + "ApiError", + "AsyncClientWrapper", + "BaseClientWrapper", + "SyncClientWrapper", + "jsonable_encoder", + "remove_none_from_dict", + "serialize_datetime", +] diff --git a/src/metriport/core/client_wrapper.py b/src/metriport/core/client_wrapper.py new file mode 100644 index 0000000..73f58da --- /dev/null +++ b/src/metriport/core/client_wrapper.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import httpx + + +class BaseClientWrapper: + def __init__(self, *, api_key: str, base_url: str): + self.api_key = api_key + self._base_url = base_url + + def get_headers(self) -> typing.Dict[str, str]: + headers: typing.Dict[str, str] = { + "X-Fern-Language": "Python", + "X-Fern-SDK-Name": "fern-metriport", + "X-Fern-SDK-Version": "0.1.2", + } + headers["X-API-Key"] = self.api_key + return headers + + def get_base_url(self) -> str: + return self._base_url + + +class SyncClientWrapper(BaseClientWrapper): + def __init__(self, *, api_key: str, base_url: str, httpx_client: httpx.Client): + super().__init__(api_key=api_key, base_url=base_url) + self.httpx_client = httpx_client + + +class AsyncClientWrapper(BaseClientWrapper): + def __init__(self, *, api_key: str, base_url: str, httpx_client: httpx.AsyncClient): + super().__init__(api_key=api_key, base_url=base_url) + self.httpx_client = httpx_client diff --git a/src/metriport/core/jsonable_encoder.py b/src/metriport/core/jsonable_encoder.py index ed5a43e..5c3cfac 100644 --- a/src/metriport/core/jsonable_encoder.py +++ b/src/metriport/core/jsonable_encoder.py @@ -9,6 +9,7 @@ """ import dataclasses +import datetime as dt from collections import defaultdict from enum import Enum from pathlib import PurePath @@ -18,6 +19,8 @@ from pydantic import BaseModel from pydantic.json import ENCODERS_BY_TYPE +from .datetime_utils import serialize_datetime + SetIntStr = Set[Union[int, str]] DictIntStrAny = Dict[Union[int, str], Any] @@ -60,6 +63,10 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] return str(obj) if isinstance(obj, (str, int, float, type(None))): return obj + if isinstance(obj, dt.date): + return str(obj) + if isinstance(obj, dt.datetime): + return serialize_datetime(obj) if isinstance(obj, dict): encoded_dict = {} allowed_keys = set(obj.keys()) diff --git a/src/metriport/core/remove_none_from_dict.py b/src/metriport/core/remove_none_from_dict.py new file mode 100644 index 0000000..2da30f7 --- /dev/null +++ b/src/metriport/core/remove_none_from_dict.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Optional + + +def remove_none_from_dict(original: Dict[str, Optional[Any]]) -> Dict[str, Any]: + new: Dict[str, Any] = {} + for key, value in original.items(): + if value is not None: + new[key] = value + return new diff --git a/src/metriport/core/remove_none_from_headers.py b/src/metriport/core/remove_none_from_headers.py deleted file mode 100644 index 21a44ca..0000000 --- a/src/metriport/core/remove_none_from_headers.py +++ /dev/null @@ -1,11 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from typing import Dict, Optional - - -def remove_none_from_headers(headers: Dict[str, Optional[str]]) -> Dict[str, str]: - new_headers: Dict[str, str] = {} - for header_key, header_value in headers.items(): - if header_value is not None: - new_headers[header_key] = header_value - return new_headers diff --git a/src/metriport/environment.py b/src/metriport/environment.py index 75ddc8d..fba28f6 100644 --- a/src/metriport/environment.py +++ b/src/metriport/environment.py @@ -3,6 +3,5 @@ import enum -class MercoaEnvironment(enum.Enum): - PRODUCTION = "https://api.metriport.com" - SANDBOX = "https://api.sandbox.metriport.com" +class MetriportEnvironment(enum.Enum): + PRODUCTION = "https://api.metriport.com/medical/v1" diff --git a/src/metriport/resources/__init__.py b/src/metriport/resources/__init__.py index 66ce54b..4c92ed3 100644 --- a/src/metriport/resources/__init__.py +++ b/src/metriport/resources/__init__.py @@ -1,23 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from . import document -from .document import ( - CodeableConcept, - Coding, - Document, - DownloadDocumentResponse, - GetDocumentsResponse, - QueryStatus, - TriggerDocumentsQueryResponse, -) +from . import commons, devices, medical +from .commons import Address, UsState -__all__ = [ - "CodeableConcept", - "Coding", - "Document", - "DownloadDocumentResponse", - "GetDocumentsResponse", - "QueryStatus", - "TriggerDocumentsQueryResponse", - "document", -] +__all__ = ["Address", "UsState", "commons", "devices", "medical"] diff --git a/src/metriport/resources/commons/__init__.py b/src/metriport/resources/commons/__init__.py new file mode 100644 index 0000000..3dde2fa --- /dev/null +++ b/src/metriport/resources/commons/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import Address, UsState + +__all__ = ["Address", "UsState"] diff --git a/src/metriport/resources/commons/types/__init__.py b/src/metriport/resources/commons/types/__init__.py new file mode 100644 index 0000000..c77c365 --- /dev/null +++ b/src/metriport/resources/commons/types/__init__.py @@ -0,0 +1,6 @@ +# This file was auto-generated by Fern from our API Definition. + +from .address import Address +from .us_state import UsState + +__all__ = ["Address", "UsState"] diff --git a/src/metriport/resources/commons/types/address.py b/src/metriport/resources/commons/types/address.py new file mode 100644 index 0000000..621384e --- /dev/null +++ b/src/metriport/resources/commons/types/address.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .us_state import UsState + + +class Address(pydantic.BaseModel): + address_line_1: str = pydantic.Field(alias="addressLine1", description="The address.") + address_line_2: typing.Optional[str] = pydantic.Field( + alias="addressLine2", description="The address details, for example `#4451`" + ) + city: str = pydantic.Field(description="The city.") + state: UsState = pydantic.Field(description="The 2 letter state acronym, for example `CA`") + zip: str = pydantic.Field(description="Zip must be a string consisting of 5 numbers.") + country: str = pydantic.Field(description="Defaults to “USA”") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/commons/types/us_state.py b/src/metriport/resources/commons/types/us_state.py new file mode 100644 index 0000000..4c32989 --- /dev/null +++ b/src/metriport/resources/commons/types/us_state.py @@ -0,0 +1,217 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class UsState(str, enum.Enum): + AL = "AL" + AK = "AK" + AZ = "AZ" + AR = "AR" + CA = "CA" + CO = "CO" + CT = "CT" + DE = "DE" + DC = "DC" + FL = "FL" + GA = "GA" + HI = "HI" + ID = "ID" + IL = "IL" + IN = "IN" + IA = "IA" + KS = "KS" + KY = "KY" + LA = "LA" + ME = "ME" + MD = "MD" + MA = "MA" + MI = "MI" + MN = "MN" + MS = "MS" + MO = "MO" + MT = "MT" + NE = "NE" + NV = "NV" + NH = "NH" + NJ = "NJ" + NM = "NM" + NY = "NY" + NC = "NC" + ND = "ND" + OH = "OH" + OK = "OK" + OR = "OR" + PA = "PA" + RI = "RI" + SC = "SC" + SD = "SD" + TN = "TN" + TX = "TX" + UT = "UT" + VT = "VT" + VA = "VA" + WA = "WA" + WV = "WV" + WI = "WI" + WY = "WY" + + def visit( + self, + al: typing.Callable[[], T_Result], + ak: typing.Callable[[], T_Result], + az: typing.Callable[[], T_Result], + ar: typing.Callable[[], T_Result], + ca: typing.Callable[[], T_Result], + co: typing.Callable[[], T_Result], + ct: typing.Callable[[], T_Result], + de: typing.Callable[[], T_Result], + dc: typing.Callable[[], T_Result], + fl: typing.Callable[[], T_Result], + ga: typing.Callable[[], T_Result], + hi: typing.Callable[[], T_Result], + id: typing.Callable[[], T_Result], + il: typing.Callable[[], T_Result], + in_: typing.Callable[[], T_Result], + ia: typing.Callable[[], T_Result], + ks: typing.Callable[[], T_Result], + ky: typing.Callable[[], T_Result], + la: typing.Callable[[], T_Result], + me: typing.Callable[[], T_Result], + md: typing.Callable[[], T_Result], + ma: typing.Callable[[], T_Result], + mi: typing.Callable[[], T_Result], + mn: typing.Callable[[], T_Result], + ms: typing.Callable[[], T_Result], + mo: typing.Callable[[], T_Result], + mt: typing.Callable[[], T_Result], + ne: typing.Callable[[], T_Result], + nv: typing.Callable[[], T_Result], + nh: typing.Callable[[], T_Result], + nj: typing.Callable[[], T_Result], + nm: typing.Callable[[], T_Result], + ny: typing.Callable[[], T_Result], + nc: typing.Callable[[], T_Result], + nd: typing.Callable[[], T_Result], + oh: typing.Callable[[], T_Result], + ok: typing.Callable[[], T_Result], + or_: typing.Callable[[], T_Result], + pa: typing.Callable[[], T_Result], + ri: typing.Callable[[], T_Result], + sc: typing.Callable[[], T_Result], + sd: typing.Callable[[], T_Result], + tn: typing.Callable[[], T_Result], + tx: typing.Callable[[], T_Result], + ut: typing.Callable[[], T_Result], + vt: typing.Callable[[], T_Result], + va: typing.Callable[[], T_Result], + wa: typing.Callable[[], T_Result], + wv: typing.Callable[[], T_Result], + wi: typing.Callable[[], T_Result], + wy: typing.Callable[[], T_Result], + ) -> T_Result: + if self is UsState.AL: + return al() + if self is UsState.AK: + return ak() + if self is UsState.AZ: + return az() + if self is UsState.AR: + return ar() + if self is UsState.CA: + return ca() + if self is UsState.CO: + return co() + if self is UsState.CT: + return ct() + if self is UsState.DE: + return de() + if self is UsState.DC: + return dc() + if self is UsState.FL: + return fl() + if self is UsState.GA: + return ga() + if self is UsState.HI: + return hi() + if self is UsState.ID: + return id() + if self is UsState.IL: + return il() + if self is UsState.IN: + return in_() + if self is UsState.IA: + return ia() + if self is UsState.KS: + return ks() + if self is UsState.KY: + return ky() + if self is UsState.LA: + return la() + if self is UsState.ME: + return me() + if self is UsState.MD: + return md() + if self is UsState.MA: + return ma() + if self is UsState.MI: + return mi() + if self is UsState.MN: + return mn() + if self is UsState.MS: + return ms() + if self is UsState.MO: + return mo() + if self is UsState.MT: + return mt() + if self is UsState.NE: + return ne() + if self is UsState.NV: + return nv() + if self is UsState.NH: + return nh() + if self is UsState.NJ: + return nj() + if self is UsState.NM: + return nm() + if self is UsState.NY: + return ny() + if self is UsState.NC: + return nc() + if self is UsState.ND: + return nd() + if self is UsState.OH: + return oh() + if self is UsState.OK: + return ok() + if self is UsState.OR: + return or_() + if self is UsState.PA: + return pa() + if self is UsState.RI: + return ri() + if self is UsState.SC: + return sc() + if self is UsState.SD: + return sd() + if self is UsState.TN: + return tn() + if self is UsState.TX: + return tx() + if self is UsState.UT: + return ut() + if self is UsState.VT: + return vt() + if self is UsState.VA: + return va() + if self is UsState.WA: + return wa() + if self is UsState.WV: + return wv() + if self is UsState.WI: + return wi() + if self is UsState.WY: + return wy() diff --git a/src/metriport/resources/devices/__init__.py b/src/metriport/resources/devices/__init__.py new file mode 100644 index 0000000..77e8dcc --- /dev/null +++ b/src/metriport/resources/devices/__init__.py @@ -0,0 +1,99 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + Activity, + ActivityDurations, + ActivityLog, + ActivityMovement, + ActivitySummary, + Aminos, + Biometrics, + BloodOxygen, + Body, + ConnectedUserInfo, + Duration, + Elevation, + EnergyExpenditure, + Food, + HeartRate, + HeartRateVariability, + HeartRateVariabilityMeasurement, + LatLon, + Location, + Macros, + Metadata, + MetriportData, + Micros, + Nutrition, + NutritionFacts, + ProviderSource, + Respiration, + Sample, + Sex, + Sleep, + SleepBiometrics, + SleepDurations, + SourceInfo, + SourceType, + Speed, + Temperature, + TemperatureMeasurement, + User, +) +from .resources import ( + ConnectTokenResponse, + ConnectedProvidersResponse, + DeleteUserResponse, + MetriportUserIdResponse, + RevokeAccessToProviderResponse, + connect, + users, +) + +__all__ = [ + "Activity", + "ActivityDurations", + "ActivityLog", + "ActivityMovement", + "ActivitySummary", + "Aminos", + "Biometrics", + "BloodOxygen", + "Body", + "ConnectTokenResponse", + "ConnectedProvidersResponse", + "ConnectedUserInfo", + "DeleteUserResponse", + "Duration", + "Elevation", + "EnergyExpenditure", + "Food", + "HeartRate", + "HeartRateVariability", + "HeartRateVariabilityMeasurement", + "LatLon", + "Location", + "Macros", + "Metadata", + "MetriportData", + "MetriportUserIdResponse", + "Micros", + "Nutrition", + "NutritionFacts", + "ProviderSource", + "Respiration", + "RevokeAccessToProviderResponse", + "Sample", + "Sex", + "Sleep", + "SleepBiometrics", + "SleepDurations", + "SourceInfo", + "SourceType", + "Speed", + "Temperature", + "TemperatureMeasurement", + "User", + "connect", + "users", +] diff --git a/src/metriport/resources/devices/client.py b/src/metriport/resources/devices/client.py new file mode 100644 index 0000000..8678a9d --- /dev/null +++ b/src/metriport/resources/devices/client.py @@ -0,0 +1,514 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.remove_none_from_dict import remove_none_from_dict +from .resources.connect.client import AsyncConnectClient, ConnectClient +from .resources.users.client import AsyncUsersClient, UsersClient +from .types.activity import Activity +from .types.biometrics import Biometrics +from .types.body import Body +from .types.connected_user_info import ConnectedUserInfo +from .types.nutrition import Nutrition +from .types.sleep import Sleep +from .types.user import User + + +class DevicesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + self.connect = ConnectClient(client_wrapper=self._client_wrapper) + self.users = UsersClient(client_wrapper=self._client_wrapper) + + def get_activity_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Activity]: + """ + Returns activity data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "activity"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Activity], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_biometrics_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Biometrics]: + """ + Returns biometrics data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "biometrics"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Biometrics], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_body_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Body]: + """ + Returns body data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "body"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Body], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_nutrition_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Nutrition]: + """ + Returns nutrition data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "nutrition"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Nutrition], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_sleep_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Sleep]: + """ + Returns sleep data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sleep"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Sleep], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_user_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[User]: + """ + Returns user info from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[User], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_connected_users(self) -> typing.List[ConnectedUserInfo]: + """ + Returns a list of users with their IDs and connected providers. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[ConnectedUserInfo], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncDevicesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + self.connect = AsyncConnectClient(client_wrapper=self._client_wrapper) + self.users = AsyncUsersClient(client_wrapper=self._client_wrapper) + + async def get_activity_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Activity]: + """ + Returns activity data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "activity"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Activity], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_biometrics_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Biometrics]: + """ + Returns biometrics data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "biometrics"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Biometrics], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_body_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Body]: + """ + Returns body data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "body"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Body], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_nutrition_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Nutrition]: + """ + Returns nutrition data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "nutrition"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Nutrition], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_sleep_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[Sleep]: + """ + Returns sleep data from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sleep"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[Sleep], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_user_data(self, *, user_id: str, date: str, timezone_id: str) -> typing.List[User]: + """ + Returns user info from all of the specified users' connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - date: str. Day for which to pull the data. Formatted YYYY-MM-DD. + + For simplicity, all queries assume the UTC timezone for the + specified date starting at 00:00 to 23:59 - unless otherwise + specified by the timezoneId parameter. + + - timezone_id: str. Timezone ID to use for the specified date. If not specified, + the UTC timezone is used. For example this can be valid timezones + like `America/Los_Angeles` or `Europe/Kiev`. + + Valid timezones can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + + Support for this parameter is under development, and currently only supported for the Google Fit provider. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user"), + params=remove_none_from_dict({"userId": user_id, "date": date, "timezoneId": timezone_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[User], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_connected_users(self) -> typing.List[ConnectedUserInfo]: + """ + Returns a list of users with their IDs and connected providers. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[ConnectedUserInfo], _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/devices/resources/__init__.py b/src/metriport/resources/devices/resources/__init__.py new file mode 100644 index 0000000..1d79c85 --- /dev/null +++ b/src/metriport/resources/devices/resources/__init__.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from . import connect, users +from .users import ( + ConnectTokenResponse, + ConnectedProvidersResponse, + DeleteUserResponse, + MetriportUserIdResponse, + RevokeAccessToProviderResponse, +) + +__all__ = [ + "ConnectTokenResponse", + "ConnectedProvidersResponse", + "DeleteUserResponse", + "MetriportUserIdResponse", + "RevokeAccessToProviderResponse", + "connect", + "users", +] diff --git a/src/metriport/resources/devices/resources/connect/__init__.py b/src/metriport/resources/devices/resources/connect/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/src/metriport/resources/devices/resources/connect/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/src/metriport/resources/devices/resources/connect/client.py b/src/metriport/resources/devices/resources/connect/client.py new file mode 100644 index 0000000..2515ebc --- /dev/null +++ b/src/metriport/resources/devices/resources/connect/client.py @@ -0,0 +1,82 @@ +# This file was auto-generated by Fern from our API Definition. + +import urllib.parse +from json.decoder import JSONDecodeError + +import typing_extensions + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.remove_none_from_dict import remove_none_from_dict + + +class ConnectClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def connect_rpm_provider( + self, provider: typing_extensions.Literal["tenovi"], *, token: str, device_user_id: str, device_ids: str + ) -> None: + """ + Connects the user to remote patient monitoring (RPM) device(s) for the specified provider. + + Parameters: + - provider: typing_extensions.Literal["tenovi"]. An RPM device provider. Currently, `tenovi` is supported. + + - token: str. The user ID you identify this user with in your app. + + - device_user_id: str. The provider’s user ID for which the RPM device(s) are provisioned. + + - device_ids: str. A comma-separated string of the user’s devices IDs to connect to. For example: `1234-0001,5678-0002`. + + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"connect/rpm/{provider}"), + params=remove_none_from_dict({"token": token, "deviceUserId": device_user_id, "deviceIds": device_ids}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncConnectClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def connect_rpm_provider( + self, provider: typing_extensions.Literal["tenovi"], *, token: str, device_user_id: str, device_ids: str + ) -> None: + """ + Connects the user to remote patient monitoring (RPM) device(s) for the specified provider. + + Parameters: + - provider: typing_extensions.Literal["tenovi"]. An RPM device provider. Currently, `tenovi` is supported. + + - token: str. The user ID you identify this user with in your app. + + - device_user_id: str. The provider’s user ID for which the RPM device(s) are provisioned. + + - device_ids: str. A comma-separated string of the user’s devices IDs to connect to. For example: `1234-0001,5678-0002`. + + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"connect/rpm/{provider}"), + params=remove_none_from_dict({"token": token, "deviceUserId": device_user_id, "deviceIds": device_ids}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/devices/resources/users/__init__.py b/src/metriport/resources/devices/resources/users/__init__.py new file mode 100644 index 0000000..396b485 --- /dev/null +++ b/src/metriport/resources/devices/resources/users/__init__.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + ConnectTokenResponse, + ConnectedProvidersResponse, + DeleteUserResponse, + MetriportUserIdResponse, + RevokeAccessToProviderResponse, +) + +__all__ = [ + "ConnectTokenResponse", + "ConnectedProvidersResponse", + "DeleteUserResponse", + "MetriportUserIdResponse", + "RevokeAccessToProviderResponse", +] diff --git a/src/metriport/resources/devices/resources/users/client.py b/src/metriport/resources/devices/resources/users/client.py new file mode 100644 index 0000000..a6dd7b3 --- /dev/null +++ b/src/metriport/resources/devices/resources/users/client.py @@ -0,0 +1,245 @@ +# This file was auto-generated by Fern from our API Definition. + +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.remove_none_from_dict import remove_none_from_dict +from .types.connect_token_response import ConnectTokenResponse +from .types.connected_providers_response import ConnectedProvidersResponse +from .types.delete_user_response import DeleteUserResponse +from .types.metriport_user_id_response import MetriportUserIdResponse +from .types.revoke_access_to_provider_response import RevokeAccessToProviderResponse + + +class UsersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_metriport_user_id(self, *, app_user_id: str) -> MetriportUserIdResponse: + """ + For your specified user ID, returns a Metriport user ID to be used in subsequent requests. + + Parameters: + - app_user_id: str. The user ID you identify this user with in your app. + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user"), + params=remove_none_from_dict({"appUserId": app_user_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(MetriportUserIdResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_connect_token(self, *, user_id: str) -> ConnectTokenResponse: + """ + Returns a token to be used in a Metriport Connect session. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user/connect/token"), + params=remove_none_from_dict({"userId": user_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ConnectTokenResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_connected_providers(self, user_id: str) -> ConnectedProvidersResponse: + """ + Returns the specified user's connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"user/{user_id}/connected-providers"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ConnectedProvidersResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def revoke_access_to_provider(self, user_id: str, *, provider: str) -> RevokeAccessToProviderResponse: + """ + Revokes the access token for a given provider. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - provider: str. The provider you would like to revoke access to. + """ + _response = self._client_wrapper.httpx_client.request( + "DELETE", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"user/{user_id}/revoke"), + params=remove_none_from_dict({"provider": provider}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(RevokeAccessToProviderResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete(self, user_id: str) -> DeleteUserResponse: + """ + Revokes access tokens for all providers and deletes the user. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + """ + _response = self._client_wrapper.httpx_client.request( + "DELETE", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"user/{user_id}"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DeleteUserResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncUsersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_metriport_user_id(self, *, app_user_id: str) -> MetriportUserIdResponse: + """ + For your specified user ID, returns a Metriport user ID to be used in subsequent requests. + + Parameters: + - app_user_id: str. The user ID you identify this user with in your app. + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user"), + params=remove_none_from_dict({"appUserId": app_user_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(MetriportUserIdResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_connect_token(self, *, user_id: str) -> ConnectTokenResponse: + """ + Returns a token to be used in a Metriport Connect session. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "user/connect/token"), + params=remove_none_from_dict({"userId": user_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ConnectTokenResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_connected_providers(self, user_id: str) -> ConnectedProvidersResponse: + """ + Returns the specified user's connected providers. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"user/{user_id}/connected-providers"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ConnectedProvidersResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def revoke_access_to_provider(self, user_id: str, *, provider: str) -> RevokeAccessToProviderResponse: + """ + Revokes the access token for a given provider. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + + - provider: str. The provider you would like to revoke access to. + """ + _response = await self._client_wrapper.httpx_client.request( + "DELETE", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"user/{user_id}/revoke"), + params=remove_none_from_dict({"provider": provider}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(RevokeAccessToProviderResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete(self, user_id: str) -> DeleteUserResponse: + """ + Revokes access tokens for all providers and deletes the user. + + Parameters: + - user_id: str. The Metriport user ID to create a session token for. + """ + _response = await self._client_wrapper.httpx_client.request( + "DELETE", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"user/{user_id}"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DeleteUserResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/devices/resources/users/types/__init__.py b/src/metriport/resources/devices/resources/users/types/__init__.py new file mode 100644 index 0000000..2f0958f --- /dev/null +++ b/src/metriport/resources/devices/resources/users/types/__init__.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +from .connect_token_response import ConnectTokenResponse +from .connected_providers_response import ConnectedProvidersResponse +from .delete_user_response import DeleteUserResponse +from .metriport_user_id_response import MetriportUserIdResponse +from .revoke_access_to_provider_response import RevokeAccessToProviderResponse + +__all__ = [ + "ConnectTokenResponse", + "ConnectedProvidersResponse", + "DeleteUserResponse", + "MetriportUserIdResponse", + "RevokeAccessToProviderResponse", +] diff --git a/src/metriport/resources/devices/resources/users/types/connect_token_response.py b/src/metriport/resources/devices/resources/users/types/connect_token_response.py new file mode 100644 index 0000000..87343ae --- /dev/null +++ b/src/metriport/resources/devices/resources/users/types/connect_token_response.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class ConnectTokenResponse(pydantic.BaseModel): + token: str = pydantic.Field( + description=( + "The temporary token to allow the specified user to access \n" + "the Metriport Connect widget.\n" + "\n" + "The token will expire 10 minutes after it is created, and \n" + "can be reused for the duration of the session.\n" + ) + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/resources/users/types/connected_providers_response.py b/src/metriport/resources/devices/resources/users/types/connected_providers_response.py new file mode 100644 index 0000000..bc989b9 --- /dev/null +++ b/src/metriport/resources/devices/resources/users/types/connected_providers_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class ConnectedProvidersResponse(pydantic.BaseModel): + connected_providers: typing.List[str] = pydantic.Field(alias="connectedProviders") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/resources/users/types/delete_user_response.py b/src/metriport/resources/devices/resources/users/types/delete_user_response.py new file mode 100644 index 0000000..b4e967d --- /dev/null +++ b/src/metriport/resources/devices/resources/users/types/delete_user_response.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class DeleteUserResponse(pydantic.BaseModel): + message: str = pydantic.Field(description="Feedback on successful user deletion.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/resources/users/types/metriport_user_id_response.py b/src/metriport/resources/devices/resources/users/types/metriport_user_id_response.py new file mode 100644 index 0000000..cacaefd --- /dev/null +++ b/src/metriport/resources/devices/resources/users/types/metriport_user_id_response.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class MetriportUserIdResponse(pydantic.BaseModel): + user_id: str = pydantic.Field( + alias="userId", description="The Metriport user ID to be used in subsequent requests for this user." + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/resources/users/types/revoke_access_to_provider_response.py b/src/metriport/resources/devices/resources/users/types/revoke_access_to_provider_response.py new file mode 100644 index 0000000..969a828 --- /dev/null +++ b/src/metriport/resources/devices/resources/users/types/revoke_access_to_provider_response.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class RevokeAccessToProviderResponse(pydantic.BaseModel): + message: str = pydantic.Field(description="Feedback on successful token revocation.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/__init__.py b/src/metriport/resources/devices/types/__init__.py new file mode 100644 index 0000000..6bb2209 --- /dev/null +++ b/src/metriport/resources/devices/types/__init__.py @@ -0,0 +1,81 @@ +# This file was auto-generated by Fern from our API Definition. + +from .activity import Activity +from .activity_durations import ActivityDurations +from .activity_log import ActivityLog +from .activity_movement import ActivityMovement +from .activity_summary import ActivitySummary +from .aminos import Aminos +from .biometrics import Biometrics +from .blood_oxygen import BloodOxygen +from .body import Body +from .connected_user_info import ConnectedUserInfo +from .duration import Duration +from .elevation import Elevation +from .energy_expenditure import EnergyExpenditure +from .food import Food +from .heart_rate import HeartRate +from .heart_rate_variability import HeartRateVariability +from .heart_rate_variability_measurement import HeartRateVariabilityMeasurement +from .lat_lon import LatLon +from .location import Location +from .macros import Macros +from .metadata import Metadata +from .metriport_data import MetriportData +from .micros import Micros +from .nutrition import Nutrition +from .nutrition_facts import NutritionFacts +from .provider_source import ProviderSource +from .respiration import Respiration +from .sample import Sample +from .sex import Sex +from .sleep import Sleep +from .sleep_biometrics import SleepBiometrics +from .sleep_durations import SleepDurations +from .source_info import SourceInfo +from .source_type import SourceType +from .speed import Speed +from .temperature import Temperature +from .temperature_measurement import TemperatureMeasurement +from .user import User + +__all__ = [ + "Activity", + "ActivityDurations", + "ActivityLog", + "ActivityMovement", + "ActivitySummary", + "Aminos", + "Biometrics", + "BloodOxygen", + "Body", + "ConnectedUserInfo", + "Duration", + "Elevation", + "EnergyExpenditure", + "Food", + "HeartRate", + "HeartRateVariability", + "HeartRateVariabilityMeasurement", + "LatLon", + "Location", + "Macros", + "Metadata", + "MetriportData", + "Micros", + "Nutrition", + "NutritionFacts", + "ProviderSource", + "Respiration", + "Sample", + "Sex", + "Sleep", + "SleepBiometrics", + "SleepDurations", + "SourceInfo", + "SourceType", + "Speed", + "Temperature", + "TemperatureMeasurement", + "User", +] diff --git a/src/metriport/resources/devices/types/activity.py b/src/metriport/resources/devices/types/activity.py new file mode 100644 index 0000000..b8a239e --- /dev/null +++ b/src/metriport/resources/devices/types/activity.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from .activity_log import ActivityLog +from .activity_summary import ActivitySummary +from .metriport_data import MetriportData + + +class Activity(MetriportData): + summary: typing.Optional[ActivitySummary] + activity_logs: typing.Optional[typing.List[ActivityLog]] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/activity_durations.py b/src/metriport/resources/devices/types/activity_durations.py new file mode 100644 index 0000000..f0b6acf --- /dev/null +++ b/src/metriport/resources/devices/types/activity_durations.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .duration import Duration + + +class ActivityDurations(pydantic.BaseModel): + active_seconds: typing.Optional[int] + intensity: typing.Optional[Duration] = pydantic.Field( + description="Also referred to as metabolic-equivalent minutes" + ) + strain: typing.Optional[Duration] = pydantic.Field(description="Also referred to as stress") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/activity_log.py b/src/metriport/resources/devices/types/activity_log.py new file mode 100644 index 0000000..0fcaf3b --- /dev/null +++ b/src/metriport/resources/devices/types/activity_log.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .activity_durations import ActivityDurations +from .activity_movement import ActivityMovement +from .biometrics import Biometrics +from .energy_expenditure import EnergyExpenditure +from .location import Location +from .metadata import Metadata + + +class ActivityLog(pydantic.BaseModel): + metadata: Metadata + name: typing.Optional[str] + type: typing.Optional[str] + start_time: typing.Optional[str] + end_time: typing.Optional[str] + durations: typing.Optional[ActivityDurations] + energy_expenditure: typing.Optional[EnergyExpenditure] + movement: typing.Optional[ActivityMovement] + location: typing.Optional[Location] + biometrics: typing.Optional[Biometrics] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/activity_movement.py b/src/metriport/resources/devices/types/activity_movement.py new file mode 100644 index 0000000..fd78b1b --- /dev/null +++ b/src/metriport/resources/devices/types/activity_movement.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .elevation import Elevation +from .speed import Speed + + +class ActivityMovement(pydantic.BaseModel): + steps_count: typing.Optional[int] + floors_count: typing.Optional[int] + elevation: typing.Optional[Elevation] + speed: typing.Optional[Speed] + avg_cadence: typing.Optional[int] + distance_meters: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/activity_summary.py b/src/metriport/resources/devices/types/activity_summary.py new file mode 100644 index 0000000..f32f5e7 --- /dev/null +++ b/src/metriport/resources/devices/types/activity_summary.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .activity_durations import ActivityDurations +from .biometrics import Biometrics +from .energy_expenditure import EnergyExpenditure + + +class ActivitySummary(pydantic.BaseModel): + durations: typing.Optional[ActivityDurations] + energy_expenditure: typing.Optional[EnergyExpenditure] + biometrics: typing.Optional[Biometrics] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/aminos.py b/src/metriport/resources/devices/types/aminos.py new file mode 100644 index 0000000..c7c8536 --- /dev/null +++ b/src/metriport/resources/devices/types/aminos.py @@ -0,0 +1,44 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class Aminos(pydantic.BaseModel): + alanine_g: typing.Optional[int] + arginine_g: typing.Optional[int] + asparagine_g: typing.Optional[int] + aspartic_acid_g: typing.Optional[int] + cysteine_g: typing.Optional[int] + glutamine_g: typing.Optional[int] + glutamic_acid_g: typing.Optional[int] + glycine_g: typing.Optional[int] + histidine_g: typing.Optional[int] + isoleucine_g: typing.Optional[int] + leucine_g: typing.Optional[int] + lysine_g: typing.Optional[int] + methionine_g: typing.Optional[int] + phenylalanine_g: typing.Optional[int] + proline_g: typing.Optional[int] + serine_g: typing.Optional[int] + threonine_g: typing.Optional[int] + tryptophan_g: typing.Optional[int] + tyrosine_g: typing.Optional[int] + valine_g: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/biometrics.py b/src/metriport/resources/devices/types/biometrics.py new file mode 100644 index 0000000..5470334 --- /dev/null +++ b/src/metriport/resources/devices/types/biometrics.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .heart_rate import HeartRate +from .heart_rate_variability import HeartRateVariability +from .respiration import Respiration + + +class Biometrics(pydantic.BaseModel): + heart_rate: typing.Optional[HeartRate] + hrv: typing.Optional[HeartRateVariability] + respiration: typing.Optional[Respiration] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/blood_oxygen.py b/src/metriport/resources/devices/types/blood_oxygen.py new file mode 100644 index 0000000..faa1200 --- /dev/null +++ b/src/metriport/resources/devices/types/blood_oxygen.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class BloodOxygen(pydantic.BaseModel): + min_pct: typing.Optional[float] + max_pct: typing.Optional[float] + avg_pct: typing.Optional[float] + std_dev: typing.Optional[float] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/body.py b/src/metriport/resources/devices/types/body.py new file mode 100644 index 0000000..90db006 --- /dev/null +++ b/src/metriport/resources/devices/types/body.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from .metriport_data import MetriportData +from .sample import Sample + + +class Body(MetriportData): + body_fat_pct: typing.Optional[float] + height_cm: typing.Optional[float] + weight_kg: typing.Optional[float] + bone_mass_kg: typing.Optional[float] + muscle_mass_kg: typing.Optional[float] + lean_mass_kg: typing.Optional[float] + max_possible_heart_rate_bpm: typing.Optional[float] + weight_samples_kg: typing.Optional[typing.List[Sample]] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/connected_user_info.py b/src/metriport/resources/devices/types/connected_user_info.py new file mode 100644 index 0000000..224fe17 --- /dev/null +++ b/src/metriport/resources/devices/types/connected_user_info.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class ConnectedUserInfo(pydantic.BaseModel): + metriport_user_id: str = pydantic.Field(alias="metriportUserId") + app_user_id: str = pydantic.Field(alias="appUserId") + connected_providers: typing.Optional[typing.List[str]] = pydantic.Field(alias="connectedProviders") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/duration.py b/src/metriport/resources/devices/types/duration.py new file mode 100644 index 0000000..d909403 --- /dev/null +++ b/src/metriport/resources/devices/types/duration.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class Duration(pydantic.BaseModel): + rest_seconds: typing.Optional[int] + very_low_seconds: typing.Optional[int] + low_seconds: typing.Optional[int] + med_seconds: typing.Optional[int] + high_seconds: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/document/types/trigger_documents_query_response.py b/src/metriport/resources/devices/types/elevation.py similarity index 76% rename from src/metriport/resources/document/types/trigger_documents_query_response.py rename to src/metriport/resources/devices/types/elevation.py index 1bfc6e3..8bf83f2 100644 --- a/src/metriport/resources/document/types/trigger_documents_query_response.py +++ b/src/metriport/resources/devices/types/elevation.py @@ -6,11 +6,12 @@ import pydantic from ....core.datetime_utils import serialize_datetime -from .query_status import QueryStatus -class TriggerDocumentsQueryResponse(pydantic.BaseModel): - query_status: QueryStatus = pydantic.Field(alias="queryStatus") +class Elevation(pydantic.BaseModel): + gain_meters: typing.Optional[int] + min_meters: typing.Optional[int] + max_meters: typing.Optional[int] def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} @@ -22,5 +23,5 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: class Config: frozen = True - allow_population_by_field_name = True + smart_union = True json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/energy_expenditure.py b/src/metriport/resources/devices/types/energy_expenditure.py new file mode 100644 index 0000000..7afe538 --- /dev/null +++ b/src/metriport/resources/devices/types/energy_expenditure.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class EnergyExpenditure(pydantic.BaseModel): + active_kcal: typing.Optional[int] + basal_metabolic_rate_kcal: typing.Optional[int] + total_watts: typing.Optional[int] + avg_watts: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/food.py b/src/metriport/resources/devices/types/food.py new file mode 100644 index 0000000..d26654d --- /dev/null +++ b/src/metriport/resources/devices/types/food.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .nutrition_facts import NutritionFacts + + +class Food(pydantic.BaseModel): + name: typing.Optional[str] + brand: typing.Optional[str] + amount: typing.Optional[float] + unit: typing.Optional[str] + nutrition_facts: typing.Optional[NutritionFacts] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/heart_rate.py b/src/metriport/resources/devices/types/heart_rate.py new file mode 100644 index 0000000..2a07148 --- /dev/null +++ b/src/metriport/resources/devices/types/heart_rate.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .sample import Sample + + +class HeartRate(pydantic.BaseModel): + min_bpm: typing.Optional[int] + max_bpm: typing.Optional[int] + avg_bpm: typing.Optional[int] + resting_bpm: typing.Optional[int] + samples_bpm: typing.Optional[typing.List[Sample]] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/heart_rate_variability.py b/src/metriport/resources/devices/types/heart_rate_variability.py new file mode 100644 index 0000000..201807a --- /dev/null +++ b/src/metriport/resources/devices/types/heart_rate_variability.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .heart_rate_variability_measurement import HeartRateVariabilityMeasurement + + +class HeartRateVariability(pydantic.BaseModel): + rmssd: typing.Optional[HeartRateVariabilityMeasurement] + sdnn: typing.Optional[HeartRateVariabilityMeasurement] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/heart_rate_variability_measurement.py b/src/metriport/resources/devices/types/heart_rate_variability_measurement.py new file mode 100644 index 0000000..80ca6a1 --- /dev/null +++ b/src/metriport/resources/devices/types/heart_rate_variability_measurement.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .sample import Sample + + +class HeartRateVariabilityMeasurement(pydantic.BaseModel): + avg_millis: typing.Optional[int] + samples_millis: typing.Optional[typing.List[Sample]] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/document/types/download_document_response.py b/src/metriport/resources/devices/types/lat_lon.py similarity index 88% rename from src/metriport/resources/document/types/download_document_response.py rename to src/metriport/resources/devices/types/lat_lon.py index be344f4..8b3e36d 100644 --- a/src/metriport/resources/document/types/download_document_response.py +++ b/src/metriport/resources/devices/types/lat_lon.py @@ -8,8 +8,9 @@ from ....core.datetime_utils import serialize_datetime -class DownloadDocumentResponse(pydantic.BaseModel): - url: str +class LatLon(pydantic.BaseModel): + lat: float + lon: float def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} @@ -21,4 +22,5 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: class Config: frozen = True + smart_union = True json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/location.py b/src/metriport/resources/devices/types/location.py new file mode 100644 index 0000000..f27245f --- /dev/null +++ b/src/metriport/resources/devices/types/location.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .lat_lon import LatLon + + +class Location(pydantic.BaseModel): + start_lat_lon_deg: typing.Optional[LatLon] + end_lat_lon_deg: typing.Optional[LatLon] + polystring: typing.Optional[str] + city: typing.Optional[str] + country: typing.Optional[str] + region: typing.Optional[str] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/macros.py b/src/metriport/resources/devices/types/macros.py new file mode 100644 index 0000000..fc6e0c9 --- /dev/null +++ b/src/metriport/resources/devices/types/macros.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class Macros(pydantic.BaseModel): + alcohol_g: typing.Optional[int] + carbs_g: typing.Optional[int] + cholesterol_mg: typing.Optional[int] + energy_kcal: typing.Optional[int] + fat_g: typing.Optional[int] + fiber_g: typing.Optional[int] + protein_g: typing.Optional[int] + sodium_mg: typing.Optional[int] + sugar_g: typing.Optional[int] + trans_fat_g: typing.Optional[int] + water_ml: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/metadata.py b/src/metriport/resources/devices/types/metadata.py new file mode 100644 index 0000000..97383a5 --- /dev/null +++ b/src/metriport/resources/devices/types/metadata.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .provider_source import ProviderSource +from .source_info import SourceInfo + + +class Metadata(pydantic.BaseModel): + date: str + hour: typing.Optional[str] + source: ProviderSource + data_source: typing.Optional[SourceInfo] + error: typing.Optional[str] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/document/types/coding.py b/src/metriport/resources/devices/types/metriport_data.py similarity index 84% rename from src/metriport/resources/document/types/coding.py rename to src/metriport/resources/devices/types/metriport_data.py index 963d795..5fac44c 100644 --- a/src/metriport/resources/document/types/coding.py +++ b/src/metriport/resources/devices/types/metriport_data.py @@ -6,12 +6,11 @@ import pydantic from ....core.datetime_utils import serialize_datetime +from .metadata import Metadata -class Coding(pydantic.BaseModel): - system: typing.Optional[str] - code: typing.Optional[str] - display: typing.Optional[str] +class MetriportData(pydantic.BaseModel): + metadata: Metadata def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} @@ -23,4 +22,5 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: class Config: frozen = True + smart_union = True json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/micros.py b/src/metriport/resources/devices/types/micros.py new file mode 100644 index 0000000..96187af --- /dev/null +++ b/src/metriport/resources/devices/types/micros.py @@ -0,0 +1,50 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class Micros(pydantic.BaseModel): + biotin_mg: typing.Optional[int] + caffeine_mg: typing.Optional[int] + calcium_mg: typing.Optional[int] + copper_mg: typing.Optional[int] + folate_mg: typing.Optional[int] + folic_acid_mg: typing.Optional[int] + iodine_mg: typing.Optional[int] + iron_mg: typing.Optional[int] + magnesium_mg: typing.Optional[int] + manganese_mg: typing.Optional[int] + phosphorus_mg: typing.Optional[int] + potassium_mg: typing.Optional[int] + selenium_mg: typing.Optional[int] + vitamin_a_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_A_mg") + vitamin_b_1_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_B1_mg") + vitamin_b_2_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_B2_mg") + vitamin_b_3_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_B3_mg") + vitamin_b_5_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_B5_mg") + vitamin_b_6_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_B6_mg") + vitamin_b_12_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_B12_mg") + vitamin_c_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_C_mg") + vitamin_d_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_D_mg") + vitamin_e_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_E_mg") + vitamin_k_mg: typing.Optional[int] = pydantic.Field(alias="vitamin_K_mg") + zinc_mg: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/document/types/get_documents_response.py b/src/metriport/resources/devices/types/nutrition.py similarity index 73% rename from src/metriport/resources/document/types/get_documents_response.py rename to src/metriport/resources/devices/types/nutrition.py index a5bf708..f6df0ab 100644 --- a/src/metriport/resources/document/types/get_documents_response.py +++ b/src/metriport/resources/devices/types/nutrition.py @@ -3,16 +3,15 @@ import datetime as dt import typing -import pydantic - from ....core.datetime_utils import serialize_datetime -from .document import Document -from .query_status import QueryStatus +from .food import Food +from .metriport_data import MetriportData +from .nutrition_facts import NutritionFacts -class GetDocumentsResponse(pydantic.BaseModel): - query_status: QueryStatus = pydantic.Field(alias="queryStatus") - documents: typing.List[Document] +class Nutrition(MetriportData): + summary: typing.Optional[NutritionFacts] + foods: typing.Optional[typing.List[Food]] def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} @@ -24,5 +23,6 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: class Config: frozen = True + smart_union = True allow_population_by_field_name = True json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/nutrition_facts.py b/src/metriport/resources/devices/types/nutrition_facts.py new file mode 100644 index 0000000..6f155b0 --- /dev/null +++ b/src/metriport/resources/devices/types/nutrition_facts.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .aminos import Aminos +from .macros import Macros +from .micros import Micros + + +class NutritionFacts(pydantic.BaseModel): + macros: typing.Optional[Macros] + micros: typing.Optional[Micros] + aminos: typing.Optional[Aminos] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/provider_source.py b/src/metriport/resources/devices/types/provider_source.py new file mode 100644 index 0000000..e0f209d --- /dev/null +++ b/src/metriport/resources/devices/types/provider_source.py @@ -0,0 +1,53 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ProviderSource(str, enum.Enum): + APPLE = "apple" + CRONOMETER = "cronometer" + DEXCOM = "dexcom" + FITBIT = "fitbit" + GARMIN = "garmin" + GOOGLE = "google" + OURA = "oura" + TENOVI = "tenovi" + WHOOP = "whoop" + WITHINGS = "withings" + + def visit( + self, + apple: typing.Callable[[], T_Result], + cronometer: typing.Callable[[], T_Result], + dexcom: typing.Callable[[], T_Result], + fitbit: typing.Callable[[], T_Result], + garmin: typing.Callable[[], T_Result], + google: typing.Callable[[], T_Result], + oura: typing.Callable[[], T_Result], + tenovi: typing.Callable[[], T_Result], + whoop: typing.Callable[[], T_Result], + withings: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ProviderSource.APPLE: + return apple() + if self is ProviderSource.CRONOMETER: + return cronometer() + if self is ProviderSource.DEXCOM: + return dexcom() + if self is ProviderSource.FITBIT: + return fitbit() + if self is ProviderSource.GARMIN: + return garmin() + if self is ProviderSource.GOOGLE: + return google() + if self is ProviderSource.OURA: + return oura() + if self is ProviderSource.TENOVI: + return tenovi() + if self is ProviderSource.WHOOP: + return whoop() + if self is ProviderSource.WITHINGS: + return withings() diff --git a/src/metriport/resources/devices/types/respiration.py b/src/metriport/resources/devices/types/respiration.py new file mode 100644 index 0000000..f12c74a --- /dev/null +++ b/src/metriport/resources/devices/types/respiration.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .blood_oxygen import BloodOxygen +from .sample import Sample + + +class Respiration(pydantic.BaseModel): + vo_2_max: typing.Optional[int] = pydantic.Field(alias="vo2_max") + spo_2: typing.Optional[BloodOxygen] = pydantic.Field(alias="spo2") + avg_breaths_per_minute: typing.Optional[int] + peak_flow_l_min: typing.Optional[int] = pydantic.Field(alias="peak_flow_L_min") + forced_volume_l: typing.Optional[int] = pydantic.Field(alias="forced_volume_L") + samples_breaths_per_minute: typing.Optional[typing.List[Sample]] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/sample.py b/src/metriport/resources/devices/types/sample.py new file mode 100644 index 0000000..f716b08 --- /dev/null +++ b/src/metriport/resources/devices/types/sample.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .source_info import SourceInfo + + +class Sample(pydantic.BaseModel): + time: str + value: int + std_dev: typing.Optional[float] + data_source: typing.Optional[SourceInfo] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/sex.py b/src/metriport/resources/devices/types/sex.py new file mode 100644 index 0000000..da4a4d7 --- /dev/null +++ b/src/metriport/resources/devices/types/sex.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class Sex(str, enum.Enum): + MALE = "male" + FEMALE = "female" + + def visit(self, male: typing.Callable[[], T_Result], female: typing.Callable[[], T_Result]) -> T_Result: + if self is Sex.MALE: + return male() + if self is Sex.FEMALE: + return female() diff --git a/src/metriport/resources/devices/types/sleep.py b/src/metriport/resources/devices/types/sleep.py new file mode 100644 index 0000000..b13fcd0 --- /dev/null +++ b/src/metriport/resources/devices/types/sleep.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from .metriport_data import MetriportData +from .sleep_biometrics import SleepBiometrics +from .sleep_durations import SleepDurations + + +class Sleep(MetriportData): + start_time: typing.Optional[str] + end_time: typing.Optional[str] + durations: typing.Optional[SleepDurations] + biometrics: typing.Optional[SleepBiometrics] + wakeup_frequency: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/sleep_biometrics.py b/src/metriport/resources/devices/types/sleep_biometrics.py new file mode 100644 index 0000000..483564f --- /dev/null +++ b/src/metriport/resources/devices/types/sleep_biometrics.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .heart_rate import HeartRate +from .heart_rate_variability import HeartRateVariability +from .respiration import Respiration +from .temperature import Temperature + + +class SleepBiometrics(pydantic.BaseModel): + heart_rate: typing.Optional[HeartRate] + hrv: typing.Optional[HeartRateVariability] + respiration: typing.Optional[Respiration] + temperature: typing.Optional[Temperature] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/sleep_durations.py b/src/metriport/resources/devices/types/sleep_durations.py new file mode 100644 index 0000000..201847c --- /dev/null +++ b/src/metriport/resources/devices/types/sleep_durations.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime + + +class SleepDurations(pydantic.BaseModel): + total_seconds: typing.Optional[int] + awake_seconds: typing.Optional[int] + deep_seconds: typing.Optional[int] + rem_seconds: typing.Optional[int] + light_seconds: typing.Optional[int] + in_bed_seconds: typing.Optional[int] + time_to_fall_asleep_seconds: typing.Optional[int] + no_data_seconds: typing.Optional[int] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/source_info.py b/src/metriport/resources/devices/types/source_info.py new file mode 100644 index 0000000..344075c --- /dev/null +++ b/src/metriport/resources/devices/types/source_info.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .source_type import SourceType + + +class SourceInfo(pydantic.BaseModel): + source_type: typing.Optional[SourceType] + id: typing.Optional[str] + name: typing.Optional[str] + type: typing.Optional[str] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/source_type.py b/src/metriport/resources/devices/types/source_type.py new file mode 100644 index 0000000..9202f05 --- /dev/null +++ b/src/metriport/resources/devices/types/source_type.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class SourceType(str, enum.Enum): + MANUAL = "MANUAL_ENTRY" + DEVICE = "DEVICE" + + def visit(self, manual: typing.Callable[[], T_Result], device: typing.Callable[[], T_Result]) -> T_Result: + if self is SourceType.MANUAL: + return manual() + if self is SourceType.DEVICE: + return device() diff --git a/src/metriport/resources/document/types/codeable_concept.py b/src/metriport/resources/devices/types/speed.py similarity index 82% rename from src/metriport/resources/document/types/codeable_concept.py rename to src/metriport/resources/devices/types/speed.py index 0849fa4..b2eaf5f 100644 --- a/src/metriport/resources/document/types/codeable_concept.py +++ b/src/metriport/resources/devices/types/speed.py @@ -6,12 +6,11 @@ import pydantic from ....core.datetime_utils import serialize_datetime -from .coding import Coding -class CodeableConcept(pydantic.BaseModel): - coding: typing.Optional[typing.List[Coding]] - text: typing.Optional[str] +class Speed(pydantic.BaseModel): + max_km_h: typing.Optional[float] + avg_km_h: typing.Optional[float] def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} @@ -23,4 +22,5 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: class Config: frozen = True + smart_union = True json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/temperature.py b/src/metriport/resources/devices/types/temperature.py new file mode 100644 index 0000000..19f90ed --- /dev/null +++ b/src/metriport/resources/devices/types/temperature.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .temperature_measurement import TemperatureMeasurement + + +class Temperature(pydantic.BaseModel): + core: typing.Optional[TemperatureMeasurement] + delta_celcius: typing.Optional[float] + skin: typing.Optional[TemperatureMeasurement] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/devices/types/temperature_measurement.py b/src/metriport/resources/devices/types/temperature_measurement.py new file mode 100644 index 0000000..c9b1d87 --- /dev/null +++ b/src/metriport/resources/devices/types/temperature_measurement.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .sample import Sample + + +class TemperatureMeasurement(pydantic.BaseModel): + avg_celcius: typing.Optional[float] + samples_celcius: typing.Optional[typing.List[Sample]] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/document/types/document.py b/src/metriport/resources/devices/types/user.py similarity index 60% rename from src/metriport/resources/document/types/document.py rename to src/metriport/resources/devices/types/user.py index 971ad1e..97aa58e 100644 --- a/src/metriport/resources/document/types/document.py +++ b/src/metriport/resources/devices/types/user.py @@ -6,19 +6,20 @@ import pydantic from ....core.datetime_utils import serialize_datetime -from .codeable_concept import CodeableConcept +from .metriport_data import MetriportData +from .sex import Sex -class Document(pydantic.BaseModel): - id: str - file_name: str = pydantic.Field(alias="fileName") - location: str - description: typing.Optional[str] - status: typing.Optional[str] - indexed: typing.Optional[dt.datetime] - mime_type: typing.Optional[str] = pydantic.Field(alias="mimeType") - size: typing.Optional[int] = pydantic.Field(description=("size of document in bytes\n")) - type: typing.Optional[CodeableConcept] +class User(MetriportData): + age: typing.Optional[int] + first_name: typing.Optional[str] + last_name: typing.Optional[str] + city: typing.Optional[str] + country: typing.Optional[str] + date_of_birth: typing.Optional[str] + email: typing.Optional[str] + region: typing.Optional[str] = pydantic.Field(description="can be state, province, etc") + sex: typing.Optional[Sex] def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} @@ -30,5 +31,6 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: class Config: frozen = True + smart_union = True allow_population_by_field_name = True json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/document/__init__.py b/src/metriport/resources/document/__init__.py deleted file mode 100644 index 3f07208..0000000 --- a/src/metriport/resources/document/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import ( - CodeableConcept, - Coding, - Document, - DownloadDocumentResponse, - GetDocumentsResponse, - QueryStatus, - TriggerDocumentsQueryResponse, -) - -__all__ = [ - "CodeableConcept", - "Coding", - "Document", - "DownloadDocumentResponse", - "GetDocumentsResponse", - "QueryStatus", - "TriggerDocumentsQueryResponse", -] diff --git a/src/metriport/resources/document/client.py b/src/metriport/resources/document/client.py deleted file mode 100644 index cab8be8..0000000 --- a/src/metriport/resources/document/client.py +++ /dev/null @@ -1,124 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -import urllib.parse -from json.decoder import JSONDecodeError - -import httpx -import pydantic - -from ...core.api_error import ApiError -from ...core.remove_none_from_headers import remove_none_from_headers -from ...environment import MercoaEnvironment -from .types.download_document_response import DownloadDocumentResponse -from .types.get_documents_response import GetDocumentsResponse -from .types.trigger_documents_query_response import TriggerDocumentsQueryResponse - - -class DocumentClient: - def __init__(self, *, environment: MercoaEnvironment = MercoaEnvironment.PRODUCTION, api_key: str): - self._environment = environment - self.api_key = api_key - - def get( - self, *, patient_id: str, facility_id: str, force_query: typing.Optional[str] = None - ) -> GetDocumentsResponse: - _response = httpx.request( - "GET", - urllib.parse.urljoin(f"{self._environment.value}/", "medical/v1/document"), - params={"patientId": patient_id, "facilityId": facility_id, "forceQuery": force_query}, - headers=remove_none_from_headers({"X-API-Key": self.api_key}), - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(GetDocumentsResponse, _response.json()) # type: ignore - try: - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def trigger_query(self, *, patient_id: str, facility_id: str) -> TriggerDocumentsQueryResponse: - _response = httpx.request( - "POST", - urllib.parse.urljoin(f"{self._environment.value}/", "medical/v1/document/query"), - params={"patientId": patient_id, "facilityId": facility_id}, - headers=remove_none_from_headers({"X-API-Key": self.api_key}), - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(TriggerDocumentsQueryResponse, _response.json()) # type: ignore - try: - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def download(self, *, file_name: str) -> DownloadDocumentResponse: - _response = httpx.request( - "POST", - urllib.parse.urljoin(f"{self._environment.value}/", "medical/v1/document/downloadUrl"), - params={"fileName": file_name}, - headers=remove_none_from_headers({"X-API-Key": self.api_key}), - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(DownloadDocumentResponse, _response.json()) # type: ignore - try: - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncDocumentClient: - def __init__(self, *, environment: MercoaEnvironment = MercoaEnvironment.PRODUCTION, api_key: str): - self._environment = environment - self.api_key = api_key - - async def get( - self, *, patient_id: str, facility_id: str, force_query: typing.Optional[str] = None - ) -> GetDocumentsResponse: - async with httpx.AsyncClient() as _client: - _response = await _client.request( - "GET", - urllib.parse.urljoin(f"{self._environment.value}/", "medical/v1/document"), - params={"patientId": patient_id, "facilityId": facility_id, "forceQuery": force_query}, - headers=remove_none_from_headers({"X-API-Key": self.api_key}), - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(GetDocumentsResponse, _response.json()) # type: ignore - try: - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def trigger_query(self, *, patient_id: str, facility_id: str) -> TriggerDocumentsQueryResponse: - async with httpx.AsyncClient() as _client: - _response = await _client.request( - "POST", - urllib.parse.urljoin(f"{self._environment.value}/", "medical/v1/document/query"), - params={"patientId": patient_id, "facilityId": facility_id}, - headers=remove_none_from_headers({"X-API-Key": self.api_key}), - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(TriggerDocumentsQueryResponse, _response.json()) # type: ignore - try: - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def download(self, *, file_name: str) -> DownloadDocumentResponse: - async with httpx.AsyncClient() as _client: - _response = await _client.request( - "POST", - urllib.parse.urljoin(f"{self._environment.value}/", "medical/v1/document/downloadUrl"), - params={"fileName": file_name}, - headers=remove_none_from_headers({"X-API-Key": self.api_key}), - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(DownloadDocumentResponse, _response.json()) # type: ignore - try: - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/document/types/__init__.py b/src/metriport/resources/document/types/__init__.py deleted file mode 100644 index 87b9118..0000000 --- a/src/metriport/resources/document/types/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .codeable_concept import CodeableConcept -from .coding import Coding -from .document import Document -from .download_document_response import DownloadDocumentResponse -from .get_documents_response import GetDocumentsResponse -from .query_status import QueryStatus -from .trigger_documents_query_response import TriggerDocumentsQueryResponse - -__all__ = [ - "CodeableConcept", - "Coding", - "Document", - "DownloadDocumentResponse", - "GetDocumentsResponse", - "QueryStatus", - "TriggerDocumentsQueryResponse", -] diff --git a/src/metriport/resources/document/types/query_status.py b/src/metriport/resources/document/types/query_status.py deleted file mode 100644 index 1ef6cad..0000000 --- a/src/metriport/resources/document/types/query_status.py +++ /dev/null @@ -1,17 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class QueryStatus(str, enum.Enum): - PROCESSING = "processing" - COMPLETED = "completed" - - def visit(self, processing: typing.Callable[[], T_Result], completed: typing.Callable[[], T_Result]) -> T_Result: - if self is QueryStatus.PROCESSING: - return processing() - if self is QueryStatus.COMPLETED: - return completed() diff --git a/src/metriport/resources/medical/__init__.py b/src/metriport/resources/medical/__init__.py new file mode 100644 index 0000000..1971135 --- /dev/null +++ b/src/metriport/resources/medical/__init__.py @@ -0,0 +1,85 @@ +# This file was auto-generated by Fern from our API Definition. + +from .resources import ( + Addresses, + BaseFacility, + BaseOrganization, + BasePatient, + CodeableConcept, + Coding, + ConsolidatedCountResponse, + Contact, + Contacts, + ConversionType, + DocumentQuery, + DocumentQueryStatus, + DocumentReference, + DocumentUrl, + DriversLicense, + Facility, + FacilityId, + Filter, + GetConsolidatedQueryStatusResponse, + ListDocumentsResponse, + ListFacilitiesResponse, + ListPatientsResponse, + OrgType, + Organization, + Patient, + PatientConsolidatedDataStatus, + Period, + PersonalIdentifier, + PersonalIdentifier_DriversLicense, + Progress, + ResourceTypeForConsolidation, + ResourcesSearchableByPatient, + ResourcesSearchableBySubject, + StartConsolidatedQueryResponse, + document, + facility, + fhir, + organization, + patient, +) + +__all__ = [ + "Addresses", + "BaseFacility", + "BaseOrganization", + "BasePatient", + "CodeableConcept", + "Coding", + "ConsolidatedCountResponse", + "Contact", + "Contacts", + "ConversionType", + "DocumentQuery", + "DocumentQueryStatus", + "DocumentReference", + "DocumentUrl", + "DriversLicense", + "Facility", + "FacilityId", + "Filter", + "GetConsolidatedQueryStatusResponse", + "ListDocumentsResponse", + "ListFacilitiesResponse", + "ListPatientsResponse", + "OrgType", + "Organization", + "Patient", + "PatientConsolidatedDataStatus", + "Period", + "PersonalIdentifier", + "PersonalIdentifier_DriversLicense", + "Progress", + "ResourceTypeForConsolidation", + "ResourcesSearchableByPatient", + "ResourcesSearchableBySubject", + "StartConsolidatedQueryResponse", + "document", + "facility", + "fhir", + "organization", + "patient", +] diff --git a/src/metriport/resources/medical/client.py b/src/metriport/resources/medical/client.py new file mode 100644 index 0000000..4bf19eb --- /dev/null +++ b/src/metriport/resources/medical/client.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .resources.document.client import AsyncDocumentClient, DocumentClient +from .resources.facility.client import AsyncFacilityClient, FacilityClient +from .resources.fhir.client import AsyncFhirClient, FhirClient +from .resources.organization.client import AsyncOrganizationClient, OrganizationClient +from .resources.patient.client import AsyncPatientClient, PatientClient + + +class MedicalClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + self.document = DocumentClient(client_wrapper=self._client_wrapper) + self.facility = FacilityClient(client_wrapper=self._client_wrapper) + self.fhir = FhirClient(client_wrapper=self._client_wrapper) + self.organization = OrganizationClient(client_wrapper=self._client_wrapper) + self.patient = PatientClient(client_wrapper=self._client_wrapper) + + +class AsyncMedicalClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + self.document = AsyncDocumentClient(client_wrapper=self._client_wrapper) + self.facility = AsyncFacilityClient(client_wrapper=self._client_wrapper) + self.fhir = AsyncFhirClient(client_wrapper=self._client_wrapper) + self.organization = AsyncOrganizationClient(client_wrapper=self._client_wrapper) + self.patient = AsyncPatientClient(client_wrapper=self._client_wrapper) diff --git a/src/metriport/resources/medical/resources/__init__.py b/src/metriport/resources/medical/resources/__init__.py new file mode 100644 index 0000000..4c9c457 --- /dev/null +++ b/src/metriport/resources/medical/resources/__init__.py @@ -0,0 +1,81 @@ +# This file was auto-generated by Fern from our API Definition. + +from . import document, facility, fhir, organization, patient +from .document import ( + CodeableConcept, + Coding, + ConversionType, + DocumentQuery, + DocumentQueryStatus, + DocumentReference, + DocumentUrl, + ListDocumentsResponse, + Progress, +) +from .facility import BaseFacility, Facility, ListFacilitiesResponse +from .fhir import ( + ConsolidatedCountResponse, + Filter, + GetConsolidatedQueryStatusResponse, + PatientConsolidatedDataStatus, + ResourceTypeForConsolidation, + ResourcesSearchableByPatient, + ResourcesSearchableBySubject, + StartConsolidatedQueryResponse, +) +from .organization import BaseOrganization, OrgType, Organization +from .patient import ( + Addresses, + BasePatient, + Contact, + Contacts, + DriversLicense, + FacilityId, + ListPatientsResponse, + Patient, + Period, + PersonalIdentifier, + PersonalIdentifier_DriversLicense, +) + +__all__ = [ + "Addresses", + "BaseFacility", + "BaseOrganization", + "BasePatient", + "CodeableConcept", + "Coding", + "ConsolidatedCountResponse", + "Contact", + "Contacts", + "ConversionType", + "DocumentQuery", + "DocumentQueryStatus", + "DocumentReference", + "DocumentUrl", + "DriversLicense", + "Facility", + "FacilityId", + "Filter", + "GetConsolidatedQueryStatusResponse", + "ListDocumentsResponse", + "ListFacilitiesResponse", + "ListPatientsResponse", + "OrgType", + "Organization", + "Patient", + "PatientConsolidatedDataStatus", + "Period", + "PersonalIdentifier", + "PersonalIdentifier_DriversLicense", + "Progress", + "ResourceTypeForConsolidation", + "ResourcesSearchableByPatient", + "ResourcesSearchableBySubject", + "StartConsolidatedQueryResponse", + "document", + "facility", + "fhir", + "organization", + "patient", +] diff --git a/src/metriport/resources/medical/resources/document/__init__.py b/src/metriport/resources/medical/resources/document/__init__.py new file mode 100644 index 0000000..208489c --- /dev/null +++ b/src/metriport/resources/medical/resources/document/__init__.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + CodeableConcept, + Coding, + ConversionType, + DocumentQuery, + DocumentQueryStatus, + DocumentReference, + DocumentUrl, + ListDocumentsResponse, + Progress, +) + +__all__ = [ + "CodeableConcept", + "Coding", + "ConversionType", + "DocumentQuery", + "DocumentQueryStatus", + "DocumentReference", + "DocumentUrl", + "ListDocumentsResponse", + "Progress", +] diff --git a/src/metriport/resources/medical/resources/document/client.py b/src/metriport/resources/medical/resources/document/client.py new file mode 100644 index 0000000..f5e72af --- /dev/null +++ b/src/metriport/resources/medical/resources/document/client.py @@ -0,0 +1,293 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.remove_none_from_dict import remove_none_from_dict +from .types.conversion_type import ConversionType +from .types.document_query import DocumentQuery +from .types.document_url import DocumentUrl +from .types.list_documents_response import ListDocumentsResponse + + +class DocumentClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def start_query(self, *, patient_id: str, facility_id: str) -> DocumentQuery: + """ + Triggers a document query for the specified patient across HIEs. + + When executed, this endpoint triggers an asynchronous document query across HIEs. + This is a two step process where the documents will first be downloaded from + the respective HIE and, if they are C-CDA/XML, then converted to FHIR. + + Each process (download, conversion) will contain its own `total` and `status` + as well as the count for `successful` operations and `errors`. + + When the asynchronous document query finishes, it stores new/updated document + references for future requests and updates the status of download to `completed`. + Meanwhile, in the background, files will be converted and the convert count will be + incremented. Once all documents have been converted it too will be marked as `completed`. + + If there's no document to be converted, the total will be set to zero and + the status to `completed`. + + Parameters: + - patient_id: str. The ID of the Patient for which to list available Documents. + + - facility_id: str. The ID of the Facility where the patient is receiving care. + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document/query"), + params=remove_none_from_dict({"patientId": patient_id, "facilityId": facility_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DocumentQuery, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_query_status(self, *, patient_id: str) -> DocumentQuery: + """ + Returns the document query status for the specified patient. + Can be used in to check the progress when the final status + of the document query is taking longer than expected. + See more on [Start Document Query](/medical-api/api-reference/document/start-document-query). + + Parameters: + - patient_id: str. The ID of the Patient for which to list available Documents. + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document/query"), + params=remove_none_from_dict({"patientId": patient_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DocumentQuery, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list( + self, + *, + patient_id: str, + facility_id: str, + date_from: typing.Optional[str] = None, + date_to: typing.Optional[str] = None, + ) -> ListDocumentsResponse: + """ + Lists all Documents that can be retrieved for a Patient. + This endpoint returns the document references available + at Metriport which are associated with the given Patient. + + To start a new document query, see the [Start Document Query endpoint](/api-reference/medical/document/start-query). + + Parameters: + - patient_id: str. The ID of the Patient for which to list available Documents. + + - facility_id: str. The ID of the Facility where the patient is receiving care. + + - date_from: typing.Optional[str]. The start date (inclusive) for which to filter returned documents - formatted `YYYY-MM-DD` as per ISO 8601. If not provided, no start date filter will be applied. + + - date_to: typing.Optional[str]. The end date (inclusive) for which to filter returned documents - formatted `YYYY-MM-DD` as per ISO 8601. If not provided, no end date filter will be applied. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document"), + params=remove_none_from_dict( + {"patientId": patient_id, "facilityId": facility_id, "dateFrom": date_from, "dateTo": date_to} + ), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ListDocumentsResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_url(self, *, file_name: str, conversion_type: typing.Optional[ConversionType] = None) -> DocumentUrl: + """ + Gets a presigned URL for downloading the specified document. + This endpoint returns a URL which you can use to download + the specified document and/or convert using the file name + provided from the [List Documents](/api-reference/medical/document/list) endpoint. + + Parameters: + - file_name: str. The file name of the document + + - conversion_type: typing.Optional[ConversionType]. The doc type to convert to. Either `html` or `pdf`. + This parameter should only be used for converting XML/CDA files. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document/downloadUrl"), + params=remove_none_from_dict({"fileName": file_name, "conversionType": conversion_type}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DocumentUrl, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncDocumentClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def start_query(self, *, patient_id: str, facility_id: str) -> DocumentQuery: + """ + Triggers a document query for the specified patient across HIEs. + + When executed, this endpoint triggers an asynchronous document query across HIEs. + This is a two step process where the documents will first be downloaded from + the respective HIE and, if they are C-CDA/XML, then converted to FHIR. + + Each process (download, conversion) will contain its own `total` and `status` + as well as the count for `successful` operations and `errors`. + + When the asynchronous document query finishes, it stores new/updated document + references for future requests and updates the status of download to `completed`. + Meanwhile, in the background, files will be converted and the convert count will be + incremented. Once all documents have been converted it too will be marked as `completed`. + + If there's no document to be converted, the total will be set to zero and + the status to `completed`. + + Parameters: + - patient_id: str. The ID of the Patient for which to list available Documents. + + - facility_id: str. The ID of the Facility where the patient is receiving care. + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document/query"), + params=remove_none_from_dict({"patientId": patient_id, "facilityId": facility_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DocumentQuery, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_query_status(self, *, patient_id: str) -> DocumentQuery: + """ + Returns the document query status for the specified patient. + Can be used in to check the progress when the final status + of the document query is taking longer than expected. + See more on [Start Document Query](/medical-api/api-reference/document/start-document-query). + + Parameters: + - patient_id: str. The ID of the Patient for which to list available Documents. + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document/query"), + params=remove_none_from_dict({"patientId": patient_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DocumentQuery, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list( + self, + *, + patient_id: str, + facility_id: str, + date_from: typing.Optional[str] = None, + date_to: typing.Optional[str] = None, + ) -> ListDocumentsResponse: + """ + Lists all Documents that can be retrieved for a Patient. + This endpoint returns the document references available + at Metriport which are associated with the given Patient. + + To start a new document query, see the [Start Document Query endpoint](/api-reference/medical/document/start-query). + + Parameters: + - patient_id: str. The ID of the Patient for which to list available Documents. + + - facility_id: str. The ID of the Facility where the patient is receiving care. + + - date_from: typing.Optional[str]. The start date (inclusive) for which to filter returned documents - formatted `YYYY-MM-DD` as per ISO 8601. If not provided, no start date filter will be applied. + + - date_to: typing.Optional[str]. The end date (inclusive) for which to filter returned documents - formatted `YYYY-MM-DD` as per ISO 8601. If not provided, no end date filter will be applied. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document"), + params=remove_none_from_dict( + {"patientId": patient_id, "facilityId": facility_id, "dateFrom": date_from, "dateTo": date_to} + ), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ListDocumentsResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_url(self, *, file_name: str, conversion_type: typing.Optional[ConversionType] = None) -> DocumentUrl: + """ + Gets a presigned URL for downloading the specified document. + This endpoint returns a URL which you can use to download + the specified document and/or convert using the file name + provided from the [List Documents](/api-reference/medical/document/list) endpoint. + + Parameters: + - file_name: str. The file name of the document + + - conversion_type: typing.Optional[ConversionType]. The doc type to convert to. Either `html` or `pdf`. + This parameter should only be used for converting XML/CDA files. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/document/downloadUrl"), + params=remove_none_from_dict({"fileName": file_name, "conversionType": conversion_type}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(DocumentUrl, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/medical/resources/document/types/__init__.py b/src/metriport/resources/medical/resources/document/types/__init__.py new file mode 100644 index 0000000..1b0c0ca --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/__init__.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from .codeable_concept import CodeableConcept +from .coding import Coding +from .conversion_type import ConversionType +from .document_query import DocumentQuery +from .document_query_status import DocumentQueryStatus +from .document_reference import DocumentReference +from .document_url import DocumentUrl +from .list_documents_response import ListDocumentsResponse +from .progress import Progress + +__all__ = [ + "CodeableConcept", + "Coding", + "ConversionType", + "DocumentQuery", + "DocumentQueryStatus", + "DocumentReference", + "DocumentUrl", + "ListDocumentsResponse", + "Progress", +] diff --git a/src/metriport/resources/medical/resources/document/types/codeable_concept.py b/src/metriport/resources/medical/resources/document/types/codeable_concept.py new file mode 100644 index 0000000..a5319ee --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/codeable_concept.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .coding import Coding + + +class CodeableConcept(pydantic.BaseModel): + coding: typing.Optional[typing.List[Coding]] = pydantic.Field( + description="Array containing the coding defined by a terminology system." + ) + text: typing.Optional[str] = pydantic.Field(description="Plain text representation of the concept.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/document/types/coding.py b/src/metriport/resources/medical/resources/document/types/coding.py new file mode 100644 index 0000000..9c6437c --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/coding.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class Coding(pydantic.BaseModel): + system: typing.Optional[str] = pydantic.Field(description="Identity of the terminology system.") + code: typing.Optional[str] = pydantic.Field(description="Symbol in syntax defined by the system.") + display: typing.Optional[str] = pydantic.Field(description="Representation defined by the system.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/document/types/conversion_type.py b/src/metriport/resources/medical/resources/document/types/conversion_type.py new file mode 100644 index 0000000..d7eb702 --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/conversion_type.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ConversionType(str, enum.Enum): + HTML = "html" + PDF = "pdf" + + def visit(self, html: typing.Callable[[], T_Result], pdf: typing.Callable[[], T_Result]) -> T_Result: + if self is ConversionType.HTML: + return html() + if self is ConversionType.PDF: + return pdf() diff --git a/src/metriport/resources/medical/resources/document/types/document_query.py b/src/metriport/resources/medical/resources/document/types/document_query.py new file mode 100644 index 0000000..db42852 --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/document_query.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .progress import Progress + + +class DocumentQuery(pydantic.BaseModel): + download: typing.Optional[Progress] + convert: typing.Optional[Progress] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/document/types/document_query_status.py b/src/metriport/resources/medical/resources/document/types/document_query_status.py new file mode 100644 index 0000000..bfac289 --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/document_query_status.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class DocumentQueryStatus(str, enum.Enum): + PROCESSING = "processing" + COMPLETED = "completed" + FAILED = "failed" + + def visit( + self, + processing: typing.Callable[[], T_Result], + completed: typing.Callable[[], T_Result], + failed: typing.Callable[[], T_Result], + ) -> T_Result: + if self is DocumentQueryStatus.PROCESSING: + return processing() + if self is DocumentQueryStatus.COMPLETED: + return completed() + if self is DocumentQueryStatus.FAILED: + return failed() diff --git a/src/metriport/resources/medical/resources/document/types/document_reference.py b/src/metriport/resources/medical/resources/document/types/document_reference.py new file mode 100644 index 0000000..573fcdf --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/document_reference.py @@ -0,0 +1,43 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .codeable_concept import CodeableConcept + + +class DocumentReference(pydantic.BaseModel): + id: str = pydantic.Field(description="The Document ID.") + file_name: str = pydantic.Field(alias="fileName", description="Name of the file.") + location: str = pydantic.Field(description="URL that can be used to retrieve the Document.") + description: typing.Optional[str] = pydantic.Field(description="Human-readable description of the Document.") + status: typing.Optional[str] = pydantic.Field( + description="Can be one of `current`, `superceded`, or `entered in error`." + ) + indexed: typing.Optional[dt.datetime] = pydantic.Field( + description="When this Document reference was created - formatted to ISO 8601." + ) + mime_type: typing.Optional[str] = pydantic.Field( + alias="mimeType", description="Document MIME type - usually `application/xml`, or `application/pdf`." + ) + size: typing.Optional[int] = pydantic.Field(description="Size of the Document in bytes.") + type: typing.Optional[CodeableConcept] = pydantic.Field( + description="What kind of document this is (LOINC if possible)." + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/document/types/document_url.py b/src/metriport/resources/medical/resources/document/types/document_url.py new file mode 100644 index 0000000..f3bb0b1 --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/document_url.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class DocumentUrl(pydantic.BaseModel): + """ + A json object containing the URL will be returned. + """ + + url: typing.Optional[str] = pydantic.Field(description="The presigned URL.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/document/types/list_documents_response.py b/src/metriport/resources/medical/resources/document/types/list_documents_response.py new file mode 100644 index 0000000..cd15c54 --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/list_documents_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .document_reference import DocumentReference + + +class ListDocumentsResponse(pydantic.BaseModel): + documents: typing.List[DocumentReference] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/document/types/progress.py b/src/metriport/resources/medical/resources/document/types/progress.py new file mode 100644 index 0000000..85bd6e5 --- /dev/null +++ b/src/metriport/resources/medical/resources/document/types/progress.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .document_query_status import DocumentQueryStatus + + +class Progress(pydantic.BaseModel): + status: DocumentQueryStatus = pydantic.Field(description="The status of querying document references across HIEs.") + total: typing.Optional[int] = pydantic.Field(description="The total number of documents to be queried.") + successful: typing.Optional[int] = pydantic.Field(description="The number of documents successfully downloaded.") + errors: typing.Optional[int] = pydantic.Field(description="The number of documents that failed to download.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/facility/__init__.py b/src/metriport/resources/medical/resources/facility/__init__.py new file mode 100644 index 0000000..47a3eae --- /dev/null +++ b/src/metriport/resources/medical/resources/facility/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import BaseFacility, Facility, ListFacilitiesResponse + +__all__ = ["BaseFacility", "Facility", "ListFacilitiesResponse"] diff --git a/src/metriport/resources/medical/resources/facility/client.py b/src/metriport/resources/medical/resources/facility/client.py new file mode 100644 index 0000000..098448b --- /dev/null +++ b/src/metriport/resources/medical/resources/facility/client.py @@ -0,0 +1,197 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.jsonable_encoder import jsonable_encoder +from .types.base_facility import BaseFacility +from .types.facility import Facility +from .types.list_facilities_response import ListFacilitiesResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class FacilityClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create(self, *, request: BaseFacility) -> Facility: + """ + Creates a Facility in Metriport where your patients receive care. + + Parameters: + - request: BaseFacility. + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "facility"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Facility, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get(self, id: str) -> Facility: + """ + Get a Facility in Metriport where your patients receive care. + + Parameters: + - id: str. The ID assigned to this Facility. This ID will be used to uniquely identify this Facility in medical documents. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"facility/{id}"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Facility, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update(self, id: str, *, request: BaseFacility) -> Facility: + """ + Updates a Facility in Metriport where your patients receive care. + + Parameters: + - id: str. The ID of the Facility. + + - request: BaseFacility. + """ + _response = self._client_wrapper.httpx_client.request( + "PUT", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"facility/{id}"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Facility, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list(self) -> ListFacilitiesResponse: + """ + Lists all of your Facilities. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "facility"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ListFacilitiesResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncFacilityClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create(self, *, request: BaseFacility) -> Facility: + """ + Creates a Facility in Metriport where your patients receive care. + + Parameters: + - request: BaseFacility. + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "facility"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Facility, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get(self, id: str) -> Facility: + """ + Get a Facility in Metriport where your patients receive care. + + Parameters: + - id: str. The ID assigned to this Facility. This ID will be used to uniquely identify this Facility in medical documents. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"facility/{id}"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Facility, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update(self, id: str, *, request: BaseFacility) -> Facility: + """ + Updates a Facility in Metriport where your patients receive care. + + Parameters: + - id: str. The ID of the Facility. + + - request: BaseFacility. + """ + _response = await self._client_wrapper.httpx_client.request( + "PUT", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"facility/{id}"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Facility, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list(self) -> ListFacilitiesResponse: + """ + Lists all of your Facilities. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "facility"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ListFacilitiesResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/medical/resources/facility/types/__init__.py b/src/metriport/resources/medical/resources/facility/types/__init__.py new file mode 100644 index 0000000..879fc73 --- /dev/null +++ b/src/metriport/resources/medical/resources/facility/types/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +from .base_facility import BaseFacility +from .facility import Facility +from .list_facilities_response import ListFacilitiesResponse + +__all__ = ["BaseFacility", "Facility", "ListFacilitiesResponse"] diff --git a/src/metriport/resources/medical/resources/facility/types/base_facility.py b/src/metriport/resources/medical/resources/facility/types/base_facility.py new file mode 100644 index 0000000..f19d616 --- /dev/null +++ b/src/metriport/resources/medical/resources/facility/types/base_facility.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .....commons.types.address import Address + + +class BaseFacility(pydantic.BaseModel): + name: str = pydantic.Field( + description="The name of your Facility. This is the actual address where a patient will receive care (can be virtual) - for example `Care Facility, LLC`." + ) + npi: str = pydantic.Field( + description="The 10 digit National Provider Identifier (NPI) that will be used to make requests on behalf of the Facility." + ) + tin: typing.Optional[str] = pydantic.Field(description="The Taxpayer Identification Number (TIN) of the Facility.") + active: typing.Optional[bool] = pydantic.Field( + description="Whether or not this Facility is currently active - this is usually `true`." + ) + address: Address + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/facility/types/facility.py b/src/metriport/resources/medical/resources/facility/types/facility.py new file mode 100644 index 0000000..f87e1f5 --- /dev/null +++ b/src/metriport/resources/medical/resources/facility/types/facility.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .base_facility import BaseFacility + + +class Facility(BaseFacility): + id: str = pydantic.Field( + description="The ID assigned to this Facility. This ID will be used to uniquely identify this Facility in medical documents." + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/facility/types/list_facilities_response.py b/src/metriport/resources/medical/resources/facility/types/list_facilities_response.py new file mode 100644 index 0000000..c9731e9 --- /dev/null +++ b/src/metriport/resources/medical/resources/facility/types/list_facilities_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .facility import Facility + + +class ListFacilitiesResponse(pydantic.BaseModel): + facilities: typing.List[Facility] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/fhir/__init__.py b/src/metriport/resources/medical/resources/fhir/__init__.py new file mode 100644 index 0000000..2777ee9 --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/__init__.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + ConsolidatedCountResponse, + Filter, + GetConsolidatedQueryStatusResponse, + PatientConsolidatedDataStatus, + ResourceTypeForConsolidation, + ResourcesSearchableByPatient, + ResourcesSearchableBySubject, + StartConsolidatedQueryResponse, +) + +__all__ = [ + "ConsolidatedCountResponse", + "Filter", + "GetConsolidatedQueryStatusResponse", + "PatientConsolidatedDataStatus", + "ResourceTypeForConsolidation", + "ResourcesSearchableByPatient", + "ResourcesSearchableBySubject", + "StartConsolidatedQueryResponse", +] diff --git a/src/metriport/resources/medical/resources/fhir/client.py b/src/metriport/resources/medical/resources/fhir/client.py new file mode 100644 index 0000000..ccdfd03 --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/client.py @@ -0,0 +1,230 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.remove_none_from_dict import remove_none_from_dict +from .types.consolidated_count_response import ConsolidatedCountResponse +from .types.get_consolidated_query_status_response import GetConsolidatedQueryStatusResponse +from .types.start_consolidated_query_response import StartConsolidatedQueryResponse + + +class FhirClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def start_consolidated_query( + self, + id: str, + *, + resources: typing.Optional[str] = None, + date_from: typing.Optional[str] = None, + date_to: typing.Optional[str] = None, + ) -> StartConsolidatedQueryResponse: + """ + Trigger a consolidated data query for the given patient + + Parameters: + - id: str. The ID of the Patient. + + - resources: typing.Optional[str]. A comma separated, case sensitive list of resources to be returned. + If none are provided all resources will be included. + + - date_from: typing.Optional[str]. The start date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no start date filter will be applied. + + - date_to: typing.Optional[str]. The end date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no end date filter will be applied. + + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}/consolidated/query"), + params=remove_none_from_dict({"resources": resources, "dateFrom": date_from, "dateTo": date_to}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(StartConsolidatedQueryResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_consolidated_query_status(self, id: str) -> GetConsolidatedQueryStatusResponse: + """ + Get the status of querying for patient's consolidated data. + + Parameters: + - id: str. The ID of the Patient + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}/consolidated/query"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(GetConsolidatedQueryStatusResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def count_patient_data( + self, + id: str, + *, + resources: typing.Optional[str] = None, + date_from: typing.Optional[str] = None, + date_to: typing.Optional[str] = None, + ) -> ConsolidatedCountResponse: + """ + Get a count of a Patient's data per resource. + + Parameters: + - id: str. The ID of the Patient + + - resources: typing.Optional[str]. A comma separated, case sensitive list of resources to be returned. + If none are provided all resources will be included. + + - date_from: typing.Optional[str]. The start date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no start date filter will be applied. + + - date_to: typing.Optional[str]. The end date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no end date filter will be applied. + + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}/consolidated/count"), + params=remove_none_from_dict({"resources": resources, "dateFrom": date_from, "dateTo": date_to}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ConsolidatedCountResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncFhirClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def start_consolidated_query( + self, + id: str, + *, + resources: typing.Optional[str] = None, + date_from: typing.Optional[str] = None, + date_to: typing.Optional[str] = None, + ) -> StartConsolidatedQueryResponse: + """ + Trigger a consolidated data query for the given patient + + Parameters: + - id: str. The ID of the Patient. + + - resources: typing.Optional[str]. A comma separated, case sensitive list of resources to be returned. + If none are provided all resources will be included. + + - date_from: typing.Optional[str]. The start date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no start date filter will be applied. + + - date_to: typing.Optional[str]. The end date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no end date filter will be applied. + + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}/consolidated/query"), + params=remove_none_from_dict({"resources": resources, "dateFrom": date_from, "dateTo": date_to}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(StartConsolidatedQueryResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_consolidated_query_status(self, id: str) -> GetConsolidatedQueryStatusResponse: + """ + Get the status of querying for patient's consolidated data. + + Parameters: + - id: str. The ID of the Patient + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}/consolidated/query"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(GetConsolidatedQueryStatusResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def count_patient_data( + self, + id: str, + *, + resources: typing.Optional[str] = None, + date_from: typing.Optional[str] = None, + date_to: typing.Optional[str] = None, + ) -> ConsolidatedCountResponse: + """ + Get a count of a Patient's data per resource. + + Parameters: + - id: str. The ID of the Patient + + - resources: typing.Optional[str]. A comma separated, case sensitive list of resources to be returned. + If none are provided all resources will be included. + + - date_from: typing.Optional[str]. The start date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no start date filter will be applied. + + - date_to: typing.Optional[str]. The end date (inclusive) for which to filter returned resources - + formatted `YYYY-MM-DD` as per ISO 8601. If not provided, + no end date filter will be applied. + + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}/consolidated/count"), + params=remove_none_from_dict({"resources": resources, "dateFrom": date_from, "dateTo": date_to}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ConsolidatedCountResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/medical/resources/fhir/types/__init__.py b/src/metriport/resources/medical/resources/fhir/types/__init__.py new file mode 100644 index 0000000..4a250bd --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/__init__.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +from .resources_searchable_by_subject import ResourcesSearchableBySubject +from .resources_searchable_by_patient import ResourcesSearchableByPatient +from .consolidated_count_response import ConsolidatedCountResponse +from .filter import Filter +from .get_consolidated_query_status_response import GetConsolidatedQueryStatusResponse +from .patient_consolidated_data_status import PatientConsolidatedDataStatus +from .resource_type_for_consolidation import ResourceTypeForConsolidation +from .start_consolidated_query_response import StartConsolidatedQueryResponse + +__all__ = [ + "ConsolidatedCountResponse", + "Filter", + "GetConsolidatedQueryStatusResponse", + "PatientConsolidatedDataStatus", + "ResourceTypeForConsolidation", + "ResourcesSearchableByPatient", + "ResourcesSearchableBySubject", + "StartConsolidatedQueryResponse", +] diff --git a/src/metriport/resources/medical/resources/fhir/types/consolidated_count_response.py b/src/metriport/resources/medical/resources/fhir/types/consolidated_count_response.py new file mode 100644 index 0000000..a95473f --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/consolidated_count_response.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .filter import Filter + + +class ConsolidatedCountResponse(pydantic.BaseModel): + total: int = pydantic.Field(description="The sum of all resource type count.") + resources: typing.Dict[str, int] = pydantic.Field( + description=( + "Object containing resource types as properties and the amount of entries for\n" + "the resource as the value (integer). Only resource types with amount \n" + "of entries higher than one are included.\n" + ) + ) + filter: Filter = pydantic.Field(description="The filters used to perform this operation.") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/fhir/types/filter.py b/src/metriport/resources/medical/resources/fhir/types/filter.py new file mode 100644 index 0000000..c4aebb3 --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/filter.py @@ -0,0 +1,46 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class Filter(pydantic.BaseModel): + resources: str = pydantic.Field( + description=( + "Comma-separated list of resource types. If not specified on the \n" "request, this will be `all`.\n" + ) + ) + date_from: typing.Optional[str] = pydantic.Field( + alias="dateFrom", + description=( + "The start date (inclusive) for which to filter returned resources - \n" + "formatted `YYYY-MM-DD` as per ISO 8601. If not provided, \n" + "no start date filter will be applied.\n" + ), + ) + date_to: typing.Optional[str] = pydantic.Field( + alias="dateTo", + description=( + "The end date (inclusive) for which to filter returned resources - \n" + "formatted `YYYY-MM-DD` as per ISO 8601. If not provided,\n" + " no end date filter will be applied.\n" + ), + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/fhir/types/get_consolidated_query_status_response.py b/src/metriport/resources/medical/resources/fhir/types/get_consolidated_query_status_response.py new file mode 100644 index 0000000..bd96b4c --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/get_consolidated_query_status_response.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .patient_consolidated_data_status import PatientConsolidatedDataStatus + + +class GetConsolidatedQueryStatusResponse(pydantic.BaseModel): + status: PatientConsolidatedDataStatus + message: typing.Optional[str] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/fhir/types/patient_consolidated_data_status.py b/src/metriport/resources/medical/resources/fhir/types/patient_consolidated_data_status.py new file mode 100644 index 0000000..5f1c2b5 --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/patient_consolidated_data_status.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class PatientConsolidatedDataStatus(str, enum.Enum): + PROCESSING = "processing" + COMPLETED = "completed" + FAILED = "failed" + + def visit( + self, + processing: typing.Callable[[], T_Result], + completed: typing.Callable[[], T_Result], + failed: typing.Callable[[], T_Result], + ) -> T_Result: + if self is PatientConsolidatedDataStatus.PROCESSING: + return processing() + if self is PatientConsolidatedDataStatus.COMPLETED: + return completed() + if self is PatientConsolidatedDataStatus.FAILED: + return failed() diff --git a/src/metriport/resources/medical/resources/fhir/types/resource_type_for_consolidation.py b/src/metriport/resources/medical/resources/fhir/types/resource_type_for_consolidation.py new file mode 100644 index 0000000..ca197cb --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/resource_type_for_consolidation.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .resources_searchable_by_patient import ResourcesSearchableByPatient +from .resources_searchable_by_subject import ResourcesSearchableBySubject + +ResourceTypeForConsolidation = typing.Union[ResourcesSearchableByPatient, ResourcesSearchableBySubject] diff --git a/src/metriport/resources/medical/resources/fhir/types/resources_searchable_by_patient.py b/src/metriport/resources/medical/resources/fhir/types/resources_searchable_by_patient.py new file mode 100644 index 0000000..f12bc8e --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/resources_searchable_by_patient.py @@ -0,0 +1,261 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ResourcesSearchableByPatient(str, enum.Enum): + ACCOUNT = "Account" + ALLERGY_INTOLERANCE = "AllergyIntolerance" + APPOINTMENT = "Appointment" + APPOINTMENT_RESPONSE = "AppointmentResponse" + AUDIT_EVENT = "AuditEvent" + BASIC = "Basic" + BODY_STRUCTURE = "BodyStructure" + CARE_PLAN = "CarePlan" + CARE_TEAM = "CareTeam" + CHARGE_ITEM = "ChargeItem" + CLAIM = "Claim" + CLAIM_RESPONSE = "ClaimResponse" + CLINICAL_IMPRESSION = "ClinicalImpression" + COMMUNICATION = "Communication" + COMMUNICATION_REQUEST = "CommunicationRequest" + COMPOSITION = "Composition" + CONDITION = "Condition" + CONSENT = "Consent" + CONTRACT = "Contract" + COVERAGE = "Coverage" + COVERAGE_ELIGIBILITY_REQUEST = "CoverageEligibilityRequest" + COVERAGE_ELIGIBILITY_RESPONSE = "CoverageEligibilityResponse" + DETECTED_ISSUE = "DetectedIssue" + DEVICE = "Device" + DEVICE_REQUEST = "DeviceRequest" + DEVICE_USE_STATEMENT = "DeviceUseStatement" + DIAGNOSTIC_REPORT = "DiagnosticReport" + DOCUMENT_MANIFEST = "DocumentManifest" + DOCUMENT_REFERENCE = "DocumentReference" + ENCOUNTER = "Encounter" + ENROLLMENT_REQUEST = "EnrollmentRequest" + EPISODE_OF_CARE = "EpisodeOfCare" + EXPLANATION_OF_BENEFIT = "ExplanationOfBenefit" + FAMILY_MEMBER_HISTORY = "FamilyMemberHistory" + FLAG = "Flag" + GOAL = "Goal" + GUIDANCE_RESPONSE = "GuidanceResponse" + IMAGING_STUDY = "ImagingStudy" + IMMUNIZATION = "Immunization" + IMMUNIZATION_EVALUATION = "ImmunizationEvaluation" + IMMUNIZATION_RECOMMENDATION = "ImmunizationRecommendation" + INVOICE = "Invoice" + LIST = "List" + MEASURE_REPORT = "MeasureReport" + MEDIA = "Media" + MEDICATION_ADMINISTRATION = "MedicationAdministration" + MEDICATION_DISPENSE = "MedicationDispense" + MEDICATION_REQUEST = "MedicationRequest" + MEDICATION_STATEMENT = "MedicationStatement" + MOLECULAR_SEQUENCE = "MolecularSequence" + NUTRITION_ORDER = "NutritionOrder" + OBSERVATION = "Observation" + PERSON = "Person" + PROCEDURE = "Procedure" + PROVENANCE = "Provenance" + QUESTIONNAIRE_RESPONSE = "QuestionnaireResponse" + RELATED_PERSON = "RelatedPerson" + REQUEST_GROUP = "RequestGroup" + RESEARCH_SUBJECT = "ResearchSubject" + RISK_ASSESSMENT = "RiskAssessment" + SERVICE_REQUEST = "ServiceRequest" + SPECIMEN = "Specimen" + + def visit( + self, + account: typing.Callable[[], T_Result], + allergy_intolerance: typing.Callable[[], T_Result], + appointment: typing.Callable[[], T_Result], + appointment_response: typing.Callable[[], T_Result], + audit_event: typing.Callable[[], T_Result], + basic: typing.Callable[[], T_Result], + body_structure: typing.Callable[[], T_Result], + care_plan: typing.Callable[[], T_Result], + care_team: typing.Callable[[], T_Result], + charge_item: typing.Callable[[], T_Result], + claim: typing.Callable[[], T_Result], + claim_response: typing.Callable[[], T_Result], + clinical_impression: typing.Callable[[], T_Result], + communication: typing.Callable[[], T_Result], + communication_request: typing.Callable[[], T_Result], + composition: typing.Callable[[], T_Result], + condition: typing.Callable[[], T_Result], + consent: typing.Callable[[], T_Result], + contract: typing.Callable[[], T_Result], + coverage: typing.Callable[[], T_Result], + coverage_eligibility_request: typing.Callable[[], T_Result], + coverage_eligibility_response: typing.Callable[[], T_Result], + detected_issue: typing.Callable[[], T_Result], + device: typing.Callable[[], T_Result], + device_request: typing.Callable[[], T_Result], + device_use_statement: typing.Callable[[], T_Result], + diagnostic_report: typing.Callable[[], T_Result], + document_manifest: typing.Callable[[], T_Result], + document_reference: typing.Callable[[], T_Result], + encounter: typing.Callable[[], T_Result], + enrollment_request: typing.Callable[[], T_Result], + episode_of_care: typing.Callable[[], T_Result], + explanation_of_benefit: typing.Callable[[], T_Result], + family_member_history: typing.Callable[[], T_Result], + flag: typing.Callable[[], T_Result], + goal: typing.Callable[[], T_Result], + guidance_response: typing.Callable[[], T_Result], + imaging_study: typing.Callable[[], T_Result], + immunization: typing.Callable[[], T_Result], + immunization_evaluation: typing.Callable[[], T_Result], + immunization_recommendation: typing.Callable[[], T_Result], + invoice: typing.Callable[[], T_Result], + list: typing.Callable[[], T_Result], + measure_report: typing.Callable[[], T_Result], + media: typing.Callable[[], T_Result], + medication_administration: typing.Callable[[], T_Result], + medication_dispense: typing.Callable[[], T_Result], + medication_request: typing.Callable[[], T_Result], + medication_statement: typing.Callable[[], T_Result], + molecular_sequence: typing.Callable[[], T_Result], + nutrition_order: typing.Callable[[], T_Result], + observation: typing.Callable[[], T_Result], + person: typing.Callable[[], T_Result], + procedure: typing.Callable[[], T_Result], + provenance: typing.Callable[[], T_Result], + questionnaire_response: typing.Callable[[], T_Result], + related_person: typing.Callable[[], T_Result], + request_group: typing.Callable[[], T_Result], + research_subject: typing.Callable[[], T_Result], + risk_assessment: typing.Callable[[], T_Result], + service_request: typing.Callable[[], T_Result], + specimen: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ResourcesSearchableByPatient.ACCOUNT: + return account() + if self is ResourcesSearchableByPatient.ALLERGY_INTOLERANCE: + return allergy_intolerance() + if self is ResourcesSearchableByPatient.APPOINTMENT: + return appointment() + if self is ResourcesSearchableByPatient.APPOINTMENT_RESPONSE: + return appointment_response() + if self is ResourcesSearchableByPatient.AUDIT_EVENT: + return audit_event() + if self is ResourcesSearchableByPatient.BASIC: + return basic() + if self is ResourcesSearchableByPatient.BODY_STRUCTURE: + return body_structure() + if self is ResourcesSearchableByPatient.CARE_PLAN: + return care_plan() + if self is ResourcesSearchableByPatient.CARE_TEAM: + return care_team() + if self is ResourcesSearchableByPatient.CHARGE_ITEM: + return charge_item() + if self is ResourcesSearchableByPatient.CLAIM: + return claim() + if self is ResourcesSearchableByPatient.CLAIM_RESPONSE: + return claim_response() + if self is ResourcesSearchableByPatient.CLINICAL_IMPRESSION: + return clinical_impression() + if self is ResourcesSearchableByPatient.COMMUNICATION: + return communication() + if self is ResourcesSearchableByPatient.COMMUNICATION_REQUEST: + return communication_request() + if self is ResourcesSearchableByPatient.COMPOSITION: + return composition() + if self is ResourcesSearchableByPatient.CONDITION: + return condition() + if self is ResourcesSearchableByPatient.CONSENT: + return consent() + if self is ResourcesSearchableByPatient.CONTRACT: + return contract() + if self is ResourcesSearchableByPatient.COVERAGE: + return coverage() + if self is ResourcesSearchableByPatient.COVERAGE_ELIGIBILITY_REQUEST: + return coverage_eligibility_request() + if self is ResourcesSearchableByPatient.COVERAGE_ELIGIBILITY_RESPONSE: + return coverage_eligibility_response() + if self is ResourcesSearchableByPatient.DETECTED_ISSUE: + return detected_issue() + if self is ResourcesSearchableByPatient.DEVICE: + return device() + if self is ResourcesSearchableByPatient.DEVICE_REQUEST: + return device_request() + if self is ResourcesSearchableByPatient.DEVICE_USE_STATEMENT: + return device_use_statement() + if self is ResourcesSearchableByPatient.DIAGNOSTIC_REPORT: + return diagnostic_report() + if self is ResourcesSearchableByPatient.DOCUMENT_MANIFEST: + return document_manifest() + if self is ResourcesSearchableByPatient.DOCUMENT_REFERENCE: + return document_reference() + if self is ResourcesSearchableByPatient.ENCOUNTER: + return encounter() + if self is ResourcesSearchableByPatient.ENROLLMENT_REQUEST: + return enrollment_request() + if self is ResourcesSearchableByPatient.EPISODE_OF_CARE: + return episode_of_care() + if self is ResourcesSearchableByPatient.EXPLANATION_OF_BENEFIT: + return explanation_of_benefit() + if self is ResourcesSearchableByPatient.FAMILY_MEMBER_HISTORY: + return family_member_history() + if self is ResourcesSearchableByPatient.FLAG: + return flag() + if self is ResourcesSearchableByPatient.GOAL: + return goal() + if self is ResourcesSearchableByPatient.GUIDANCE_RESPONSE: + return guidance_response() + if self is ResourcesSearchableByPatient.IMAGING_STUDY: + return imaging_study() + if self is ResourcesSearchableByPatient.IMMUNIZATION: + return immunization() + if self is ResourcesSearchableByPatient.IMMUNIZATION_EVALUATION: + return immunization_evaluation() + if self is ResourcesSearchableByPatient.IMMUNIZATION_RECOMMENDATION: + return immunization_recommendation() + if self is ResourcesSearchableByPatient.INVOICE: + return invoice() + if self is ResourcesSearchableByPatient.LIST: + return list() + if self is ResourcesSearchableByPatient.MEASURE_REPORT: + return measure_report() + if self is ResourcesSearchableByPatient.MEDIA: + return media() + if self is ResourcesSearchableByPatient.MEDICATION_ADMINISTRATION: + return medication_administration() + if self is ResourcesSearchableByPatient.MEDICATION_DISPENSE: + return medication_dispense() + if self is ResourcesSearchableByPatient.MEDICATION_REQUEST: + return medication_request() + if self is ResourcesSearchableByPatient.MEDICATION_STATEMENT: + return medication_statement() + if self is ResourcesSearchableByPatient.MOLECULAR_SEQUENCE: + return molecular_sequence() + if self is ResourcesSearchableByPatient.NUTRITION_ORDER: + return nutrition_order() + if self is ResourcesSearchableByPatient.OBSERVATION: + return observation() + if self is ResourcesSearchableByPatient.PERSON: + return person() + if self is ResourcesSearchableByPatient.PROCEDURE: + return procedure() + if self is ResourcesSearchableByPatient.PROVENANCE: + return provenance() + if self is ResourcesSearchableByPatient.QUESTIONNAIRE_RESPONSE: + return questionnaire_response() + if self is ResourcesSearchableByPatient.RELATED_PERSON: + return related_person() + if self is ResourcesSearchableByPatient.REQUEST_GROUP: + return request_group() + if self is ResourcesSearchableByPatient.RESEARCH_SUBJECT: + return research_subject() + if self is ResourcesSearchableByPatient.RISK_ASSESSMENT: + return risk_assessment() + if self is ResourcesSearchableByPatient.SERVICE_REQUEST: + return service_request() + if self is ResourcesSearchableByPatient.SPECIMEN: + return specimen() diff --git a/src/metriport/resources/medical/resources/fhir/types/resources_searchable_by_subject.py b/src/metriport/resources/medical/resources/fhir/types/resources_searchable_by_subject.py new file mode 100644 index 0000000..4f791a0 --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/resources_searchable_by_subject.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ResourcesSearchableBySubject(str, enum.Enum): + ADVERSE_EVENT = "AdverseEvent" + TASK = "Task" + + def visit(self, adverse_event: typing.Callable[[], T_Result], task: typing.Callable[[], T_Result]) -> T_Result: + if self is ResourcesSearchableBySubject.ADVERSE_EVENT: + return adverse_event() + if self is ResourcesSearchableBySubject.TASK: + return task() diff --git a/src/metriport/resources/medical/resources/fhir/types/start_consolidated_query_response.py b/src/metriport/resources/medical/resources/fhir/types/start_consolidated_query_response.py new file mode 100644 index 0000000..0a14a20 --- /dev/null +++ b/src/metriport/resources/medical/resources/fhir/types/start_consolidated_query_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .patient_consolidated_data_status import PatientConsolidatedDataStatus + + +class StartConsolidatedQueryResponse(pydantic.BaseModel): + status: PatientConsolidatedDataStatus + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/organization/__init__.py b/src/metriport/resources/medical/resources/organization/__init__.py new file mode 100644 index 0000000..d338135 --- /dev/null +++ b/src/metriport/resources/medical/resources/organization/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import BaseOrganization, OrgType, Organization + +__all__ = ["BaseOrganization", "OrgType", "Organization"] diff --git a/src/metriport/resources/medical/resources/organization/client.py b/src/metriport/resources/medical/resources/organization/client.py new file mode 100644 index 0000000..e66d067 --- /dev/null +++ b/src/metriport/resources/medical/resources/organization/client.py @@ -0,0 +1,154 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.jsonable_encoder import jsonable_encoder +from .types.base_organization import BaseOrganization +from .types.organization import Organization + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class OrganizationClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create(self, *, request: BaseOrganization) -> Organization: + """ + Registers your Organization in Metriport. + + Parameters: + - request: BaseOrganization. + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "organization"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Organization, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get(self) -> Organization: + """ + Gets the Organization representing your legal corporate entity. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "organization"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Organization, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update(self, id: str, *, request: BaseOrganization) -> Organization: + """ + Updates your Organization's details. + + Parameters: + - id: str. The ID of your organization. + + - request: BaseOrganization. + """ + _response = self._client_wrapper.httpx_client.request( + "PUT", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"organization/{id}"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Organization, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncOrganizationClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create(self, *, request: BaseOrganization) -> Organization: + """ + Registers your Organization in Metriport. + + Parameters: + - request: BaseOrganization. + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "organization"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Organization, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get(self) -> Organization: + """ + Gets the Organization representing your legal corporate entity. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "organization"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Organization, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update(self, id: str, *, request: BaseOrganization) -> Organization: + """ + Updates your Organization's details. + + Parameters: + - id: str. The ID of your organization. + + - request: BaseOrganization. + """ + _response = await self._client_wrapper.httpx_client.request( + "PUT", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"organization/{id}"), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Organization, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/medical/resources/organization/types/__init__.py b/src/metriport/resources/medical/resources/organization/types/__init__.py new file mode 100644 index 0000000..d342826 --- /dev/null +++ b/src/metriport/resources/medical/resources/organization/types/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +from .base_organization import BaseOrganization +from .org_type import OrgType +from .organization import Organization + +__all__ = ["BaseOrganization", "OrgType", "Organization"] diff --git a/src/metriport/resources/medical/resources/organization/types/base_organization.py b/src/metriport/resources/medical/resources/organization/types/base_organization.py new file mode 100644 index 0000000..ea7a417 --- /dev/null +++ b/src/metriport/resources/medical/resources/organization/types/base_organization.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .....commons.types.address import Address +from .org_type import OrgType + + +class BaseOrganization(pydantic.BaseModel): + name: str = pydantic.Field( + description=( + "The name of your organization. \n" + "This is usually your legal corporate entity name - \n" + "for example `Metriport Inc.`.\n" + ) + ) + type: OrgType = pydantic.Field(description="The type of your organization.") + location: Address + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/organization/types/org_type.py b/src/metriport/resources/medical/resources/organization/types/org_type.py new file mode 100644 index 0000000..550e6e5 --- /dev/null +++ b/src/metriport/resources/medical/resources/organization/types/org_type.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class OrgType(str, enum.Enum): + ACUTE_CARE = "acuteCare" + AMBULATORY = "ambulatory" + HOSPITAL = "hospital" + LAB_SYSTEMS = "labSystems" + PHARMACY = "pharmacy" + POST_ACUTE_CARE = "postAcuteCare" + + def visit( + self, + acute_care: typing.Callable[[], T_Result], + ambulatory: typing.Callable[[], T_Result], + hospital: typing.Callable[[], T_Result], + lab_systems: typing.Callable[[], T_Result], + pharmacy: typing.Callable[[], T_Result], + post_acute_care: typing.Callable[[], T_Result], + ) -> T_Result: + if self is OrgType.ACUTE_CARE: + return acute_care() + if self is OrgType.AMBULATORY: + return ambulatory() + if self is OrgType.HOSPITAL: + return hospital() + if self is OrgType.LAB_SYSTEMS: + return lab_systems() + if self is OrgType.PHARMACY: + return pharmacy() + if self is OrgType.POST_ACUTE_CARE: + return post_acute_care() diff --git a/src/metriport/resources/medical/resources/organization/types/organization.py b/src/metriport/resources/medical/resources/organization/types/organization.py new file mode 100644 index 0000000..486c09f --- /dev/null +++ b/src/metriport/resources/medical/resources/organization/types/organization.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .base_organization import BaseOrganization + + +class Organization(BaseOrganization): + id: str = pydantic.Field( + description=( + "The ID assigned to your organization. \n" + "This ID will be used to uniquely identify your organization in medical documents.\n" + ) + ) + e_tag: typing.Optional[str] = pydantic.Field(alias="eTag") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/__init__.py b/src/metriport/resources/medical/resources/patient/__init__.py new file mode 100644 index 0000000..aa91c2e --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/__init__.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + Addresses, + BasePatient, + Contact, + Contacts, + DriversLicense, + FacilityId, + ListPatientsResponse, + Patient, + Period, + PersonalIdentifier, + PersonalIdentifier_DriversLicense, +) + +__all__ = [ + "Addresses", + "BasePatient", + "Contact", + "Contacts", + "DriversLicense", + "FacilityId", + "ListPatientsResponse", + "Patient", + "Period", + "PersonalIdentifier", + "PersonalIdentifier_DriversLicense", +] diff --git a/src/metriport/resources/medical/resources/patient/client.py b/src/metriport/resources/medical/resources/patient/client.py new file mode 100644 index 0000000..0022b92 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/client.py @@ -0,0 +1,276 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import urllib.parse +from json.decoder import JSONDecodeError + +import pydantic + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.jsonable_encoder import jsonable_encoder +from .....core.remove_none_from_dict import remove_none_from_dict +from .types.base_patient import BasePatient +from .types.list_patients_response import ListPatientsResponse +from .types.patient import Patient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class PatientClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create(self, *, facility_id: str, request: BasePatient) -> Patient: + """ + Creates a Patient in Metriport for the specified Facility where the patient is receiving care. + + The more demographic info you can provide about a Patient, + the higher chances Metriport will be able to find a match. + For example, nicknames, old addresses, multiple phone numbers, + a pre-marital last name, etc. + + Parameters: + - facility_id: str. The ID of the Facility where the Patient is receiving care. + + - request: BasePatient. + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "patient"), + params=remove_none_from_dict({"facilityId": facility_id}), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get(self, id: str) -> Patient: + """ + Get a Patient + + Parameters: + - id: str. The ID of the Patient. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update(self, id: str, *, facility_id: str, request: BasePatient) -> Patient: + """ + Updates the specified Patient. + + Parameters: + - id: str. The ID of the Patient to update. + + - facility_id: str. The ID of the Facility where the patient is receiving care. + + - request: BasePatient. + """ + _response = self._client_wrapper.httpx_client.request( + "PUT", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}"), + params=remove_none_from_dict({"facilityId": facility_id}), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list(self, *, facility_id: typing.Optional[str] = None) -> ListPatientsResponse: + """ + Lists all Patients receiving care at the specified Facility. + + Parameters: + - facility_id: typing.Optional[str]. The ID of the Facility where the patient is receiving care. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "patient"), + params=remove_none_from_dict({"facilityId": facility_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ListPatientsResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete(self, id: str, *, facility_id: typing.Optional[str] = None) -> None: + """ + Removes the specified Patient. + + Parameters: + - id: str. The ID of the Patient to delete. + + - facility_id: typing.Optional[str]. The ID of the Facility where the patient is receiving care. + """ + _response = self._client_wrapper.httpx_client.request( + "DELETE", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}"), + params=remove_none_from_dict({"facilityId": facility_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncPatientClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create(self, *, facility_id: str, request: BasePatient) -> Patient: + """ + Creates a Patient in Metriport for the specified Facility where the patient is receiving care. + + The more demographic info you can provide about a Patient, + the higher chances Metriport will be able to find a match. + For example, nicknames, old addresses, multiple phone numbers, + a pre-marital last name, etc. + + Parameters: + - facility_id: str. The ID of the Facility where the Patient is receiving care. + + - request: BasePatient. + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "patient"), + params=remove_none_from_dict({"facilityId": facility_id}), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get(self, id: str) -> Patient: + """ + Get a Patient + + Parameters: + - id: str. The ID of the Patient. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}"), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update(self, id: str, *, facility_id: str, request: BasePatient) -> Patient: + """ + Updates the specified Patient. + + Parameters: + - id: str. The ID of the Patient to update. + + - facility_id: str. The ID of the Facility where the patient is receiving care. + + - request: BasePatient. + """ + _response = await self._client_wrapper.httpx_client.request( + "PUT", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}"), + params=remove_none_from_dict({"facilityId": facility_id}), + json=jsonable_encoder(request), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list(self, *, facility_id: typing.Optional[str] = None) -> ListPatientsResponse: + """ + Lists all Patients receiving care at the specified Facility. + + Parameters: + - facility_id: typing.Optional[str]. The ID of the Facility where the patient is receiving care. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "patient"), + params=remove_none_from_dict({"facilityId": facility_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ListPatientsResponse, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete(self, id: str, *, facility_id: typing.Optional[str] = None) -> None: + """ + Removes the specified Patient. + + Parameters: + - id: str. The ID of the Patient to delete. + + - facility_id: typing.Optional[str]. The ID of the Facility where the patient is receiving care. + """ + _response = await self._client_wrapper.httpx_client.request( + "DELETE", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"patient/{id}"), + params=remove_none_from_dict({"facilityId": facility_id}), + headers=self._client_wrapper.get_headers(), + timeout=60, + ) + if 200 <= _response.status_code < 300: + return + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/resources/medical/resources/patient/types/__init__.py b/src/metriport/resources/medical/resources/patient/types/__init__.py new file mode 100644 index 0000000..3159dce --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/__init__.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from .addresses import Addresses +from .base_patient import BasePatient +from .contact import Contact +from .contacts import Contacts +from .drivers_license import DriversLicense +from .facility_id import FacilityId +from .list_patients_response import ListPatientsResponse +from .patient import Patient +from .period import Period +from .personal_identifier import PersonalIdentifier, PersonalIdentifier_DriversLicense + +__all__ = [ + "Addresses", + "BasePatient", + "Contact", + "Contacts", + "DriversLicense", + "FacilityId", + "ListPatientsResponse", + "Patient", + "Period", + "PersonalIdentifier", + "PersonalIdentifier_DriversLicense", +] diff --git a/src/metriport/resources/medical/resources/patient/types/addresses.py b/src/metriport/resources/medical/resources/patient/types/addresses.py new file mode 100644 index 0000000..baf45a3 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/addresses.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .....commons.types.address import Address + +Addresses = typing.Union[Address, typing.List[Address]] diff --git a/src/metriport/resources/medical/resources/patient/types/base_patient.py b/src/metriport/resources/medical/resources/patient/types/base_patient.py new file mode 100644 index 0000000..3e6f86e --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/base_patient.py @@ -0,0 +1,48 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .addresses import Addresses +from .contacts import Contacts +from .personal_identifier import PersonalIdentifier + + +class BasePatient(pydantic.BaseModel): + first_name: str = pydantic.Field( + alias="firstName", + description=( + "The Patient's first name(s). \n" + "You may provide a comma/space delimited string to specify \n" + "multiple first and last names. For example, the following inputs \n" + 'would be equivalent: "John,Jonathan" & "John Jonathan"\n' + ), + ) + last_name: str = pydantic.Field(alias="lastName", description="The Patient's last name(s).") + dob: str = pydantic.Field(description="The Patient's date of birth (DOB), formatted `YYYY-MM-DD` as per ISO 8601.") + gender_at_birth: str = pydantic.Field( + alias="genderAtBirth", description="The Patient's gender at birth, can be one of `M` or `F`." + ) + personal_identifiers: typing.Optional[typing.List[PersonalIdentifier]] = pydantic.Field( + alias="personalIdentifiers", + description=("An array of the Patient's personal IDs, such as a driver's license. \n" "May be empty.\n"), + ) + address: typing.Optional[Addresses] + contact: typing.Optional[Contacts] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/types/contact.py b/src/metriport/resources/medical/resources/patient/types/contact.py new file mode 100644 index 0000000..51a9938 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/contact.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .facility_id import FacilityId + + +class Contact(pydantic.BaseModel): + phone: typing.Optional[str] = pydantic.Field( + description="The Patient's 10 digit phone number, formatted `1234567899`." + ) + email: typing.Optional[str] = pydantic.Field(description="The Patient's email address.") + facility_ids: typing.List[FacilityId] = pydantic.Field( + alias="facilityIds", description="Array of the IDs of the Facilities where the Patient is receiving care." + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/types/contacts.py b/src/metriport/resources/medical/resources/patient/types/contacts.py new file mode 100644 index 0000000..4a13420 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/contacts.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .contact import Contact + +Contacts = typing.Union[Contact] diff --git a/src/metriport/resources/medical/resources/patient/types/drivers_license.py b/src/metriport/resources/medical/resources/patient/types/drivers_license.py new file mode 100644 index 0000000..4a484e7 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/drivers_license.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .....commons.types.us_state import UsState +from .period import Period + + +class DriversLicense(pydantic.BaseModel): + state: UsState = pydantic.Field( + description="The 2 letter state acronym where this ID was issued, for example `CA`." + ) + value: str = pydantic.Field(description="The ID number.") + assigner: typing.Optional[str] + period: typing.Optional[Period] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/types/facility_id.py b/src/metriport/resources/medical/resources/patient/types/facility_id.py new file mode 100644 index 0000000..f75ceb5 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/facility_id.py @@ -0,0 +1,3 @@ +# This file was auto-generated by Fern from our API Definition. + +FacilityId = str diff --git a/src/metriport/resources/medical/resources/patient/types/list_patients_response.py b/src/metriport/resources/medical/resources/patient/types/list_patients_response.py new file mode 100644 index 0000000..eb6e656 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/list_patients_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .patient import Patient + + +class ListPatientsResponse(pydantic.BaseModel): + patients: typing.List[Patient] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/types/patient.py b/src/metriport/resources/medical/resources/patient/types/patient.py new file mode 100644 index 0000000..cbe8013 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/patient.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime +from .base_patient import BasePatient + + +class Patient(BasePatient): + id: str = pydantic.Field( + description="The ID assigned to this Patient. This ID will be used to uniquely identify this Patient in medical documents." + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/types/period.py b/src/metriport/resources/medical/resources/patient/types/period.py new file mode 100644 index 0000000..3eacc4b --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/period.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ......core.datetime_utils import serialize_datetime + + +class Period(pydantic.BaseModel): + start: typing.Optional[str] + end: typing.Optional[str] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/metriport/resources/medical/resources/patient/types/personal_identifier.py b/src/metriport/resources/medical/resources/patient/types/personal_identifier.py new file mode 100644 index 0000000..61059d0 --- /dev/null +++ b/src/metriport/resources/medical/resources/patient/types/personal_identifier.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import typing_extensions + +from .drivers_license import DriversLicense + + +class PersonalIdentifier_DriversLicense(DriversLicense): + type: typing_extensions.Literal["driversLicense"] + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + + +PersonalIdentifier = typing.Union[PersonalIdentifier_DriversLicense] diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_client.py b/tests/test_client.py new file mode 100644 index 0000000..60a58e6 --- /dev/null +++ b/tests/test_client.py @@ -0,0 +1,6 @@ +import pytest + +# Get started with writing tests with pytest at https://docs.pytest.org +@pytest.mark.skip(reason="Unimplemented") +def test_client() -> None: + assert True == True