Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asyncio migration #22

Merged
merged 5 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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