Skip to content

Commit 6cef9e7

Browse files
authored
Merge pull request #73 from anomaly/alpha-8
alpha-8 urgent release
2 parents c324113 + ad014e1 commit 6cef9e7

File tree

16 files changed

+745
-620
lines changed

16 files changed

+745
-620
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ from gallagher import cc
4444
from gallagher.dto.summary import CardholderSummary
4545
from gallagher.cc.cardholders import Cardholder
4646

47+
# Optionally provide a client certificate and key
48+
cert_path = os.path.join(os.getcwd(), "client.pem")
49+
key_path = os.path.join(os.getcwd(), "client.key")
50+
4751
# Set the API key from the environment
4852
api_key = os.environ.get("GACC_API_KEY")
4953
cc.api_key = api_key

docs/docs/python-sdk.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ async def main():
297297
cc.api_key = api_key
298298

299299
# Used to control the event loop
300-
event = asyncio.Event()
301-
event.set()
300+
asyncio_event = asyncio.Event()
301+
asyncio_event.set()
302302

303303
async for updates in Alarms.follow(
304-
event=event,
304+
asyncio_event=asyncio_event,
305305
):
306306

307307
for update in updates.updates:
@@ -310,7 +310,7 @@ async def main():
310310
# Examples of stopping the loop if
311311
# we got no updates
312312
if len(updates.updates) == 0:
313-
event.clear()
313+
asyncio_event.clear()
314314

315315
if __name__ == "__main__":
316316
asyncio.run(main())

examples/alarm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ async def main():
1818
event.set()
1919

2020
async for updates in Alarms.follow(
21-
event=event,
21+
asyncio_event=event,
2222
):
2323

2424
for update in updates.updates:

examples/events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ async def main():
4949
event.set()
5050

5151
async for updates in Event.follow(
52-
event=event,
52+
asyncio_event=event,
5353
):
5454
for update_event in updates.events:
5555
print("Processing event")

gallagher/cc/alarms/events.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
class Event(APIEndpoint):
2424
"""Event
25-
26-
2725
2826
How updates differ from GET:
2927

gallagher/cc/core.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from datetime import datetime
2323
from dataclasses import dataclass
2424

25-
from asyncio import Event
25+
from asyncio import Event as AsyncioEvent # Used for signalling events
2626

2727
from http import HTTPStatus # Provides constants for HTTP status codes
2828

@@ -486,11 +486,15 @@ async def previous(cls, response):
486486
@classmethod
487487
async def follow(
488488
cls,
489-
event: Event,
489+
asyncio_event: AsyncioEvent, # Not to be confused with Gallagher event
490490
params: dict[str, Any] = {},
491491
):
492492
"""Fetches update and follows next to get the next set of results
493493
494+
parameters:
495+
- event: asyncio.Event object to signal when to stop
496+
- params: dictionary of parameters to pass to the endpoint
497+
494498
Long poll behaviour in the Gallagher API uses the following pattern:
495499
- The request will wait until there's a new set of changes
496500
- If no changes are detected in 30 seconds then the server returns
@@ -516,7 +520,7 @@ async def follow(
516520
verify=cls._ssl_context(),
517521
) as _httpx_async:
518522

519-
while event.is_set():
523+
while asyncio_event.is_set():
520524
try:
521525
response = await _httpx_async.get(
522526
f"{url}", # required to turn pydantic object to str

gallagher/const.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ class IP_ADDR:
2323
https://gallaghersecurity.github.io/commandcentre-cloud-api-gateway.html
2424
"""
2525

26-
CLOUD_GATEWAY_AU = ["3.106.1.6", "3.106.100.112"]
26+
CLOUD_GATEWAY_AU: list[str] = ["3.106.1.6", "3.106.100.112"]
2727

28-
CLOUD_GATEWAY_US = ["44.193.42.111", "3.209.194.103"]
28+
CLOUD_GATEWAY_US: list[str] = ["44.193.42.111", "3.209.194.103"]
2929

3030

3131
class TRANSPORT:

gallagher/decorators.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
""" Decorators for annotating functions for behaviours.
2+
3+
All decorators are defined here and are referenced across the codebase.
4+
Note that some of them reference the bootstrapped environment where
5+
information is discovered from the live Command Centre the instance
6+
is connected to.
7+
8+
See Also:
9+
https://github.com/anomaly/gallagher/issues/69
10+
"""
11+
12+
def deprecated(func):
13+
"""Decorator to indicate that a function is deprecated.
14+
15+
This decorator is used to indicate that a function is deprecated and
16+
should not be used. It will raise a warning when the function is called.
17+
18+
Args:
19+
func (Callable): The function to be deprecated.
20+
21+
Returns:
22+
Callable: The wrapped function.
23+
24+
Examples:
25+
>>> @deprecated
26+
... def old_function():
27+
... pass
28+
29+
"""
30+
import warnings
31+
import functools
32+
33+
@functools.wraps(func)
34+
def wrapper(*args, **kwargs):
35+
warnings.warn(
36+
f"Call to deprecated function {func.__name__}.",
37+
category=DeprecationWarning
38+
)
39+
return func(*args, **kwargs)
40+
41+
return wrapper
42+
43+
44+
def available(version_string):
45+
"""Decorator to indicate that a function is available in a specific version.
46+
47+
This decorator is used to indicate that a function is available in a specific
48+
version of the Command Centre API. It will raise an error if the function is
49+
called in a version that does not support it.
50+
51+
Args:
52+
version_string (str): The version string the function is available in.
53+
54+
Returns:
55+
Callable: The wrapped function.
56+
57+
Examples:
58+
>>> @available("1.0.0")
59+
... def new_function():
60+
... pass
61+
62+
"""
63+
import functools
64+
65+
def decorator(func):
66+
@functools.wraps(func)
67+
def wrapper(*args, **kwargs):
68+
from .cc.core import Capabilities
69+
70+
if Capabilities.CURRENT.version < version_string:
71+
raise RuntimeError(
72+
f"Function {func.__name__} is not available in version {Capabilities.CURRENT.version}."
73+
)
74+
75+
return func(*args, **kwargs)
76+
77+
return wrapper
78+
79+
return decorator

gallagher/dto/ref/cardholder.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
from ..utils import (
44
AppBaseModel,
5-
HrefMixin,
65
IdentityMixin,
76
OptionalHrefMixin,
87
)
98

109

1110
class CardholderRef(
1211
AppBaseModel,
13-
HrefMixin,
12+
OptionalHrefMixin,
1413
):
1514
"""Reference to a Cardholder"""
1615

gallagher/dto/summary/card_type.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from ..utils import (
44
AppBaseModel,
5-
IdentityMixin,
5+
OptionalIdentityMixin,
66
)
77

88
class CardExpiryTypeSummary(AppBaseModel):
@@ -11,7 +11,7 @@ class CardExpiryTypeSummary(AppBaseModel):
1111

1212
class CardSummary(
1313
AppBaseModel,
14-
IdentityMixin,
14+
OptionalIdentityMixin,
1515
):
1616
"""Card summary as sent by the Event objects
1717

0 commit comments

Comments
 (0)