Skip to content

Commit

Permalink
halfway
Browse files Browse the repository at this point in the history
  • Loading branch information
NodeJSmith committed Aug 13, 2024
1 parent 2c02c1f commit 970a519
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 200 deletions.
14 changes: 12 additions & 2 deletions examples/challenge_tracker_examples.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import asyncio
import json
import os

import stackprinter
from attr import asdict
from otf_api import Otf
from otf_api.api import c
from otf_api.models.responses import ChallengeType, EquipmentType

stackprinter.set_excepthook(style="darkbg2") # for jupyter notebooks try style='lightbg'

USERNAME = os.getenv("OTF_EMAIL")
PASSWORD = os.getenv("OTF_PASSWORD")
DEVICE_KEY = os.getenv("OTF_DEVICE_KEY")


async def main():
otf = Otf(USERNAME, PASSWORD)
otf = Otf(USERNAME, PASSWORD, device_key=DEVICE_KEY)

body_comp = await otf.get_body_composition_list()
print(json.dumps(c.unstructure(body_comp.data[0]), indent=4))

# challenge tracker content is an overview of the challenges OTF runs
# and your participation in them
Expand Down Expand Up @@ -53,7 +63,7 @@ async def main():
# challenge tracker details are detailed information about specific challenges
# this endpoint takes an equipment type and a challenge type as arguments
tread_challenge_details = await otf.get_challenge_tracker_detail(EquipmentType.Treadmill, ChallengeType.Other)
print(tread_challenge_details.details[0].model_dump_json(indent=4))
print(json.dumps(asdict(tread_challenge_details.details[0]), indent=4, default=str))

"""
{
Expand Down
16 changes: 14 additions & 2 deletions src/otf_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
from typing import Any

import aiohttp
import cattrs
import requests
from attrs import has
from cattrs.gen import make_dict_structure_fn
from cattrs.strategies import use_class_methods
from loguru import logger
from yarl import URL

Expand Down Expand Up @@ -46,6 +50,12 @@
WorkoutList,
)

c = cattrs.Converter()
c.register_structure_hook(str | float, lambda v, _: v)
c.register_structure_hook(datetime, lambda v, _: datetime.fromisoformat(v))
c.register_structure_hook_factory(has, lambda cl: make_dict_structure_fn(cl, c, _cattrs_use_alias=True))
use_class_methods(c, "_structure", "_unstructure")


class AlreadyBookedError(Exception):
pass
Expand Down Expand Up @@ -558,7 +568,9 @@ async def get_challenge_tracker_detail(

data = await self._default_request("GET", f"/challenges/v3/member/{self._member_id}/benchmarks", params=params)

return ChallengeTrackerDetailList(details=data["Dto"])
retval = c.structure({"details": data["Dto"]}, ChallengeTrackerDetailList)
return retval
# return ChallengeTrackerDetailList(details=data["Dto"])

async def get_challenge_tracker_participation(self, challenge_type_id: ChallengeType) -> typing.Any:
"""Get the member's participation in a challenge.
Expand Down Expand Up @@ -943,7 +955,7 @@ async def get_body_composition_list(self) -> BodyCompositionList:
"""
data = await self._default_request("GET", f"/member/members/{self._member_uuid}/body-composition")

return BodyCompositionList(data=data["data"])
return c.structure(data, BodyCompositionList)


def active_time_to_data_points(active_time: int) -> float:
Expand Down
3 changes: 2 additions & 1 deletion src/otf_api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def device_key(self) -> str | None:
@device_key.setter
def device_key(self, value: str | None):
if not value:
logger.info("Clearing device key")
if self._device_key:
logger.info("Clearing device key")
self._device_key = value
return

Expand Down
44 changes: 44 additions & 0 deletions src/otf_api/models/base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import inspect
import typing
from datetime import datetime
from enum import Enum
from logging import getLogger
from typing import Any, ClassVar, TypeVar

import attrs
import cattrs
import cattrs.strategies
from box import Box
from inflection import humanize
from pydantic import BaseModel, ConfigDict
Expand All @@ -14,6 +19,45 @@
from pydantic.main import IncEx

T = TypeVar("T", bound="OtfItemBase")
converter = cattrs.Converter()
converter.register_structure_hook(datetime, lambda v, _: datetime.fromisoformat(v))
converter.register_structure_hook_factory(
attrs.has, lambda cl: cattrs.gen.make_dict_structure_fn(cl, converter, _cattrs_use_alias=True)
)
cattrs.strategies.use_class_methods(converter, "_structure", "_unstructure")

logger = getLogger(__name__)


class AttrsMixin:
_attrs_converter: ClassVar[cattrs.Converter] = converter

def _unstructure(self):
data = attrs.asdict(self)

for f in attrs.fields(type(self)):
if f.metadata.get("exclude"):
data.pop(f.name, None)

return data

@classmethod
def _structure(cls, data: dict):
for f in attrs.fields(cls):
if attrs.has(f.type):
sub_data = cls._attrs_converter.structure(data, f.type)
data[f.alias] = sub_data
for k in attrs.fields(f.type):
data.pop(k.alias, None)
elif f.alias == "member_id":
data[f.alias] = str(data.pop(f.alias))

known_data = {k: v for k, v in data.items() if k in [f.alias for f in attrs.fields(cls)]}
unknown_data = {k: v for k, v in data.items() if k not in known_data}

logger.debug(f"Unknown data for {cls.__name__}: {unknown_data}")

return cls(**known_data)


class BetterDumperMixin:
Expand Down
Loading

0 comments on commit 970a519

Please sign in to comment.