Skip to content

Commit

Permalink
Merge pull request #22 from anomaly/asyncio-migration
Browse files Browse the repository at this point in the history
Asyncio migration
  • Loading branch information
devraj authored Dec 18, 2023
2 parents cdaa0b2 + baaf841 commit ad51624
Show file tree
Hide file tree
Showing 26 changed files with 215 additions and 171 deletions.
2 changes: 1 addition & 1 deletion gallagher/cc/alarms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Alarms(
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.alarms.alarms,
dto_list=AlarmResponse,
Expand Down
2 changes: 1 addition & 1 deletion gallagher/cc/alarms/day_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class DayCategory(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.day_categories
.day_categories,
Expand Down
2 changes: 1 addition & 1 deletion gallagher/cc/alarms/divisions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Division(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.divisions.divisions,
dto_list=DivisionDetailResponse,
Expand Down
4 changes: 2 additions & 2 deletions gallagher/cc/alarms/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Event(
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.events.events,
dto_list=EventResponse,
Expand All @@ -39,7 +39,7 @@ class EventType(
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.events.event_groups,
dto_list=EventTypeResponse,
Expand Down
4 changes: 2 additions & 2 deletions gallagher/cc/alarms/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ItemsTypes(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.items.item_types,
dto_list=ItemTypesResponse,
Expand All @@ -39,7 +39,7 @@ class Item(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.items.items,
dto_list=ItemsSummaryResponse,
Expand Down
2 changes: 1 addition & 1 deletion gallagher/cc/alarms/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Schedule(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.schedules.schedules,
dto_list=ScheduleSummaryResponse,
Expand Down
2 changes: 1 addition & 1 deletion gallagher/cc/cardholders/card_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class CardType(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.card_types.card_types,
dto_list=CardTypeResponse,
Expand Down
4 changes: 2 additions & 2 deletions gallagher/cc/cardholders/cardholders.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ class Cardholder(APIEndpoint):
"""

@classmethod
def get_config(cls):
async def get_config(cls):
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.cardholders.cardholders,
dto_list=CardholderSummaryResponse,
dto_retrieve=CardholderDetail,
)

@classmethod
def search(cls, name: str, sort: str = "id", top: int = 100):
async def search(cls, name: str, sort: str = "id", top: int = 100):
pass
153 changes: 84 additions & 69 deletions gallagher/cc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class EndpointConfig:
# fields: list[str] = [] # Optional list of fields

@classmethod
def validate_endpoint(cls):
async def validate_endpoint(cls):
""" Check to see if the feature is licensed and available
Gallagher REST API is licensed per feature, if a feature is not
Expand Down Expand Up @@ -136,7 +136,7 @@ class APIEndpoint:
__config__ = None

@classmethod
def get_config(cls):
async def get_config(cls):
""" Returns the configuration for the endpoint
This method can be overridden by the child class to
Expand All @@ -145,7 +145,7 @@ def get_config(cls):
return None

@classmethod
def _discover(cls):
async def _discover(cls):
""" The Command Centre root API endpoint
Much of Gallagher's API documentation suggests that we don't
Expand Down Expand Up @@ -175,103 +175,114 @@ def _discover(cls):
# Auto-discovery of the API endpoints, this will
# be called as part of the bootstrapping process
from . import api_base
response = httpx.get(
api_base,
headers=get_authorization_headers(),
)

parsed_obj = DiscoveryResponse.model_validate(
response.json()
)

# Assign the capabilities to the class, this should
# result in the endpoint
#
# With the refactored initialisation of the pydantic
# models, the values for the unavailable endpoints
# should be set to None
Capabilities.CURRENT = parsed_obj

# Set this so the configuration is only discovered
# once per endpoint
#
# If we assign the __config__ variable in the class
# that inherits from this class, the instance of EndpointConfig
# will copy the None values from the Capabilities.CURRENT
# object, this primarily because Capabilities.CURRENT is
# an instance of a pyndatic object and all values are thus
# copied not referenced.
cls.__config__ = cls.get_config()
async with httpx.AsyncClient() as _httpx_async:
response = await _httpx_async.get(
api_base,
headers=get_authorization_headers(),
)

await _httpx_async.aclose()

parsed_obj = DiscoveryResponse.model_validate(
response.json()
)

# Assign the capabilities to the class, this should
# result in the endpoint
#
# With the refactored initialisation of the pydantic
# models, the values for the unavailable endpoints
# should be set to None
Capabilities.CURRENT = parsed_obj

# Set this so the configuration is only discovered
# once per endpoint
#
# If we assign the __config__ variable in the class
# that inherits from this class, the instance of EndpointConfig
# will copy the None values from the Capabilities.CURRENT
# object, this primarily because Capabilities.CURRENT is
# an instance of a pyndatic object and all values are thus
# copied not referenced.
cls.__config__ = await cls.get_config()

@classmethod
def list(cls, skip=0):
async def list(cls, skip=0):
""" For a list of objects for the given resource
Most resources can be searched which is exposed by this method.
Resources also allow pagination which can be controlled by the skip
"""
cls._discover()
await cls._discover()

async with httpx.AsyncClient() as _httpx_async:

response = httpx.get(
f'{cls.__config__.endpoint.href}',
headers=get_authorization_headers(),
)
response = await _httpx_async.get(
f'{cls.__config__.endpoint.href}',
headers=get_authorization_headers(),
)

parsed_obj = cls.__config__.dto_list.model_validate(
response.json()
)
await _httpx_async.aclose()

parsed_obj = cls.__config__.dto_list.model_validate(
response.json()
)

return parsed_obj
return parsed_obj

@classmethod
def retrieve(cls, id):
async def retrieve(cls, id):
""" Retrieve a single object for the given resource
Most objects have an ID which is numeral or UUID.
Each resource also provides a href and pagination for
children.
"""
cls._discover()
await cls._discover()

async with httpx.AsyncClient() as _httpx_async:

response = httpx.get(
f'{cls.__config__.endpoint.href}/{id}',
headers=get_authorization_headers(),
)
response = await _httpx_async.get(
f'{cls.__config__.endpoint.href}/{id}',
headers=get_authorization_headers(),
)

parsed_obj = cls.__config__.dto_retrieve.model_validate(
response.json()
)
await _httpx_async.aclose()

parsed_obj = cls.__config__.dto_retrieve.model_validate(
response.json()
)

return parsed_obj
return parsed_obj

@classmethod
def modify(cls):
async def modify(cls):
"""
"""
pass

@classmethod
def create(cls, **params):
async def create(cls, **params):
"""
"""
cls._discover()

@classmethod
def delete(cls):
async def delete(cls):
"""
"""
cls._discover()

@classmethod
def search(cls,
top: int = 100,
sort: str = 'id',
fields: str = 'defaults',
**kwargs
):
async def search(cls,
top: int = 100,
sort: str = 'id',
fields: str = 'defaults',
**kwargs
):
""" Search wrapper for most objects to dynamically search content
Each object has a set of fields that you can query for, most searches
Expand All @@ -283,7 +294,7 @@ def search(cls,
:param kwargs: Fields to search for
"""
cls._discover()
await cls._discover()

params = {
'top': top,
Expand All @@ -295,14 +306,18 @@ def search(cls,
# for each type of object that calls the base function
params.update(kwargs)

response = httpx.get(
f'{cls.__config__.endpoint.href}',
params=params,
headers=get_authorization_headers(),
)
async with httpx.AsyncClient() as _httpx_async:

response = await _httpx_async.get(
f'{cls.__config__.endpoint.href}',
params=params,
headers=get_authorization_headers(),
)

parsed_obj = cls.__config__.dto_list.model_validate(
response.json()
)
await _httpx_async.aclose()

parsed_obj = cls.__config__.dto_list.model_validate(
response.json()
)

return parsed_obj
return parsed_obj
4 changes: 2 additions & 2 deletions gallagher/cli/cardholders.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


@app.command("list")
def list():
async def list():
""" list all cardholders
"""
console = Console()
Expand All @@ -33,7 +33,7 @@ def list():


@app.command("get")
def get(id: int):
async def get(id: int):
""" get a cardholder by id
"""
cardholder = Cardholder.retrieve(id)
Expand Down
2 changes: 1 addition & 1 deletion gallagher/dto/cardholder.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def __rich_repr__(self):
"yes" if self.authorised else "no"
]

def __str__(self):
async def __str__(self):
return f"{self.id} {self.first_name} {self.last_name}"


Expand Down
2 changes: 1 addition & 1 deletion gallagher/dto/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ class DiscoveryResponse(
] = FeaturesDetail()

@property
def get_sem_ver(self):
async def get_sem_ver(self):
""" Get a SemVer tuple from the version string
"""
return self.version.split(".")
Loading

0 comments on commit ad51624

Please sign in to comment.