pyixapi 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyixapi-0.2.0/pyixapi.egg-info → pyixapi-0.2.2}/PKG-INFO +9 -9
- {pyixapi-0.2.0 → pyixapi-0.2.2}/README.md +0 -2
- pyixapi-0.2.2/pyixapi/__init__.py +5 -0
- pyixapi-0.2.2/pyixapi/__main__.py +69 -0
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/api.py +23 -18
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/endpoint.py +15 -8
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/query.py +29 -16
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/response.py +6 -6
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/token.py +26 -18
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/util.py +1 -1
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/models.py +4 -12
- pyixapi-0.2.2/pyproject.toml +78 -0
- pyixapi-0.2.0/.github/FUNDING.yml +0 -4
- pyixapi-0.2.0/.github/dependabot.yml +0 -19
- pyixapi-0.2.0/.github/workflows/publish.yml +0 -29
- pyixapi-0.2.0/.github/workflows/tests.yml +0 -26
- pyixapi-0.2.0/.gitignore +0 -102
- pyixapi-0.2.0/PKG-INFO +0 -79
- pyixapi-0.2.0/docs/Makefile +0 -17
- pyixapi-0.2.0/docs/advanced.rst +0 -74
- pyixapi-0.2.0/docs/conf.py +0 -158
- pyixapi-0.2.0/docs/endpoint.rst +0 -5
- pyixapi-0.2.0/docs/index.rst +0 -29
- pyixapi-0.2.0/docs/request.rst +0 -8
- pyixapi-0.2.0/docs/response.rst +0 -8
- pyixapi-0.2.0/pyixapi/__init__.py +0 -11
- pyixapi-0.2.0/pyixapi.egg-info/SOURCES.txt +0 -38
- pyixapi-0.2.0/pyixapi.egg-info/dependency_links.txt +0 -1
- pyixapi-0.2.0/pyixapi.egg-info/not-zip-safe +0 -1
- pyixapi-0.2.0/pyixapi.egg-info/requires.txt +0 -2
- pyixapi-0.2.0/pyixapi.egg-info/top_level.txt +0 -1
- pyixapi-0.2.0/pyproject.toml +0 -8
- pyixapi-0.2.0/requirements-dev.txt +0 -2
- pyixapi-0.2.0/requirements.txt +0 -2
- pyixapi-0.2.0/setup.cfg +0 -4
- pyixapi-0.2.0/setup.py +0 -33
- pyixapi-0.2.0/tests/__init__.py +0 -0
- pyixapi-0.2.0/tests/fixtures/api/authenticate.json +0 -4
- pyixapi-0.2.0/tests/fixtures/api/refresh_authentication.json +0 -4
- pyixapi-0.2.0/tests/test_api.py +0 -86
- pyixapi-0.2.0/tests/util.py +0 -15
- {pyixapi-0.2.0 → pyixapi-0.2.2}/LICENSE +0 -0
- {pyixapi-0.2.0 → pyixapi-0.2.2}/pyixapi/core/__init__.py +0 -0
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyixapi
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary:
|
|
5
|
-
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Python API client library for IX-API
|
|
5
|
+
License: Apache-2.0
|
|
6
6
|
Author: Guillaume Mazoyer
|
|
7
7
|
Author-email: oss@mazoyer.eu
|
|
8
|
-
|
|
9
|
-
Keywords: ix-api,internet-exchange,peering
|
|
8
|
+
Requires-Python: >=3.8,<4.0
|
|
10
9
|
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier:
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.8
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Dist: PyJWT (>=2.4.0,<2.9)
|
|
18
|
+
Requires-Dist: requests (>=2.20.0,<3.0)
|
|
17
19
|
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
20
|
|
|
20
21
|
# pyixapi
|
|
21
22
|
|
|
@@ -30,8 +31,6 @@ Supported versions are:
|
|
|
30
31
|
|
|
31
32
|
To install run `pip install pyixapi`.
|
|
32
33
|
|
|
33
|
-
Alternatively, you can clone the repo and run `python setup.py install`.
|
|
34
|
-
|
|
35
34
|
## Quick Start
|
|
36
35
|
|
|
37
36
|
To begin, import pyixapi and instantiate the API.
|
|
@@ -77,3 +76,4 @@ DXDB:PAS:00008
|
|
|
77
76
|
```
|
|
78
77
|
|
|
79
78
|
Write queries are not implemented yet.
|
|
79
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from pyixapi import api
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def create_mac_address(ixapi, mac_address):
|
|
5
|
+
"""
|
|
6
|
+
Create a new MAC address in IX-API. If the MAC already exists, return it
|
|
7
|
+
without creation.
|
|
8
|
+
"""
|
|
9
|
+
# Make sure to have a consistent case
|
|
10
|
+
mac_address = str(mac_address).lower()
|
|
11
|
+
|
|
12
|
+
# Return existing object if MAC already exists
|
|
13
|
+
for mac in ixapi.macs.all():
|
|
14
|
+
if mac["address"] == mac_address:
|
|
15
|
+
return mac
|
|
16
|
+
|
|
17
|
+
return ixapi.macs.create(
|
|
18
|
+
address=mac_address, consuming_customer="2", managing_customer="2"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# ixapi = api(
|
|
23
|
+
# "https://api.de-cix.net/api/v1/",
|
|
24
|
+
# "-GnNlMD8hBuxSSUJmpbfUkss9dyOKfTV1SnZibNyyr4",
|
|
25
|
+
# "XKq8M6NVh5lCbPJ2Ml1h7V93QNIMsGVBfM6g2nRZF-E",
|
|
26
|
+
# )
|
|
27
|
+
|
|
28
|
+
ixapi = api(
|
|
29
|
+
"https://api.de-cix.net/api/v2/",
|
|
30
|
+
"lZJ_sV59gydj12RFATG4NaQFRI15iKRi9RC0oDqn2_A",
|
|
31
|
+
"Yt_RImR_ymuhx2r9YQXerh5q9EyE6TxaREjzmEQNr1o",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# ixapi = api(
|
|
35
|
+
# "http://localhost:8000/api/v1/",
|
|
36
|
+
# "c25f077c899694fc",
|
|
37
|
+
# "zZm-hzDIR5BZUhn5ULo4-_BQyx39ayRRn_0HFaSNDShqunrTiNY4a6n0Bnjqg62F-NsywRLvn3Dt3pRXWRgS1A",
|
|
38
|
+
# )
|
|
39
|
+
|
|
40
|
+
authentication = ixapi.authenticate()
|
|
41
|
+
print(authentication)
|
|
42
|
+
|
|
43
|
+
print(f"IX-API is at version {ixapi.version}")
|
|
44
|
+
|
|
45
|
+
authentication = ixapi.authenticate()
|
|
46
|
+
print(authentication)
|
|
47
|
+
|
|
48
|
+
print([i for i in ixapi.accounts.all()])
|
|
49
|
+
|
|
50
|
+
# for i in ixapi.ips.all():
|
|
51
|
+
# print(f"{i.ip} - {i.network}")
|
|
52
|
+
# print(ixapi.network_service_configs.get("DXDB:PAS:509177"))
|
|
53
|
+
|
|
54
|
+
# for i in ixapi.ports.all():
|
|
55
|
+
# print(i)
|
|
56
|
+
|
|
57
|
+
# print(len(ixapi.network_services.filter(consuming_customer="DXDB:CUST:1348")))
|
|
58
|
+
# print(len(ixapi.network_services.all()))
|
|
59
|
+
|
|
60
|
+
# mac = create_mac_address(ixapi, "e4:f7:ad:58:87:ff")
|
|
61
|
+
|
|
62
|
+
# for i in ixapi.macs.all():
|
|
63
|
+
# print(dict(i))
|
|
64
|
+
|
|
65
|
+
# for i in ixapi.network_service_configs.all():
|
|
66
|
+
# # i.macs = [mac]
|
|
67
|
+
# # print(i.save())
|
|
68
|
+
# i.update({"macs": [mac]})
|
|
69
|
+
# print(dict(i))
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
import requests
|
|
2
4
|
|
|
3
5
|
from pyixapi.core.endpoint import Endpoint
|
|
@@ -24,13 +26,12 @@ from pyixapi.models import (
|
|
|
24
26
|
PoP,
|
|
25
27
|
Port,
|
|
26
28
|
PortReservation,
|
|
27
|
-
Product,
|
|
28
29
|
ProductOffering,
|
|
29
30
|
Role,
|
|
30
31
|
RoleAssignment,
|
|
31
32
|
)
|
|
32
33
|
|
|
33
|
-
__version__ = "0.2.
|
|
34
|
+
__version__ = "0.2.2"
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
class API(object):
|
|
@@ -43,13 +44,13 @@ class API(object):
|
|
|
43
44
|
|
|
44
45
|
def __init__(
|
|
45
46
|
self,
|
|
46
|
-
url,
|
|
47
|
-
key,
|
|
48
|
-
secret,
|
|
49
|
-
access_token="",
|
|
50
|
-
refresh_token="",
|
|
51
|
-
user_agent=f"pyixapi/{__version__}",
|
|
52
|
-
):
|
|
47
|
+
url: str,
|
|
48
|
+
key: str,
|
|
49
|
+
secret: str,
|
|
50
|
+
access_token: str = "",
|
|
51
|
+
refresh_token: str = "",
|
|
52
|
+
user_agent: str = f"pyixapi/{__version__}",
|
|
53
|
+
) -> None:
|
|
53
54
|
self.url = url.rstrip("/")
|
|
54
55
|
self.key = key
|
|
55
56
|
self.secret = secret
|
|
@@ -75,7 +76,6 @@ class API(object):
|
|
|
75
76
|
)
|
|
76
77
|
self.network_services = Endpoint(self, "network-services", model=NetworkService)
|
|
77
78
|
self.pops = Endpoint(self, "pops", model=PoP)
|
|
78
|
-
self.products = Endpoint(self, "products", model=Product)
|
|
79
79
|
# Version 2+
|
|
80
80
|
self.member_joining_rules = Endpoint(
|
|
81
81
|
self, "member-joining-rules", model=MemberJoiningRule
|
|
@@ -88,14 +88,11 @@ class API(object):
|
|
|
88
88
|
self.port_reservations = Endpoint(
|
|
89
89
|
self, "port-reservations", model=PortReservation
|
|
90
90
|
)
|
|
91
|
-
self.product_offerings = Endpoint(
|
|
92
|
-
self, "product-offerings", model=ProductOffering
|
|
93
|
-
)
|
|
94
91
|
self.roles = Endpoint(self, "roles", model=Role)
|
|
95
92
|
self.role_assignments = Endpoint(self, "role-assignments", model=RoleAssignment)
|
|
96
93
|
|
|
97
94
|
@property
|
|
98
|
-
def version(self):
|
|
95
|
+
def version(self) -> int:
|
|
99
96
|
"""
|
|
100
97
|
Get the API version of IX-API.
|
|
101
98
|
"""
|
|
@@ -104,12 +101,20 @@ class API(object):
|
|
|
104
101
|
).get_version()
|
|
105
102
|
|
|
106
103
|
@property
|
|
107
|
-
def accounts(self):
|
|
104
|
+
def accounts(self) -> Endpoint:
|
|
108
105
|
return Endpoint(
|
|
109
106
|
self, "customers" if self.version == 1 else "accounts", model=Account
|
|
110
107
|
)
|
|
111
108
|
|
|
112
|
-
|
|
109
|
+
@property
|
|
110
|
+
def product_offerings(self) -> Endpoint:
|
|
111
|
+
return Endpoint(
|
|
112
|
+
self,
|
|
113
|
+
"products" if self.version == 1 else "product-offerings",
|
|
114
|
+
model=ProductOffering,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def authenticate(self) -> Record:
|
|
113
118
|
"""
|
|
114
119
|
Authenticate and generate a pair of tokens.
|
|
115
120
|
|
|
@@ -136,7 +141,7 @@ class API(object):
|
|
|
136
141
|
|
|
137
142
|
return Record(r, self, self.auth)
|
|
138
143
|
|
|
139
|
-
def refresh_authentication(self):
|
|
144
|
+
def refresh_authentication(self) -> Record:
|
|
140
145
|
"""
|
|
141
146
|
Prolong authentication by refreshing the tokens pair.
|
|
142
147
|
"""
|
|
@@ -151,7 +156,7 @@ class API(object):
|
|
|
151
156
|
|
|
152
157
|
return Record(r, self, self.auth)
|
|
153
158
|
|
|
154
|
-
def health(self):
|
|
159
|
+
def health(self) -> dict[str, Any]:
|
|
155
160
|
"""
|
|
156
161
|
Get the health information from IX-API.
|
|
157
162
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
|
2
|
+
|
|
1
3
|
from pyixapi.core.query import Request, RequestError
|
|
2
4
|
from pyixapi.core.response import Record, RecordSet
|
|
3
5
|
from pyixapi.core.util import cat
|
|
4
6
|
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .api import API
|
|
9
|
+
|
|
5
10
|
|
|
6
|
-
class Endpoint
|
|
11
|
+
class Endpoint:
|
|
7
12
|
"""
|
|
8
13
|
Represent actions available on endpoints in the IX-API.
|
|
9
14
|
|
|
@@ -11,16 +16,16 @@ class Endpoint(object):
|
|
|
11
16
|
object.
|
|
12
17
|
"""
|
|
13
18
|
|
|
14
|
-
def __init__(self, api, name, model=None):
|
|
19
|
+
def __init__(self, api: "API", name: str, model: Optional[Record] = None) -> None:
|
|
15
20
|
self.return_obj = model if model else Record
|
|
16
21
|
self.api = api
|
|
17
22
|
self.url = cat(api.url, name)
|
|
18
23
|
self.name = name
|
|
19
24
|
|
|
20
|
-
def __str__(self):
|
|
25
|
+
def __str__(self) -> str:
|
|
21
26
|
return self.url
|
|
22
27
|
|
|
23
|
-
def all(self):
|
|
28
|
+
def all(self) -> RecordSet:
|
|
24
29
|
"""
|
|
25
30
|
Return all objects from an endpoint.
|
|
26
31
|
"""
|
|
@@ -31,7 +36,7 @@ class Endpoint(object):
|
|
|
31
36
|
)
|
|
32
37
|
return RecordSet(self, r)
|
|
33
38
|
|
|
34
|
-
def filter(self, *args, **kwargs):
|
|
39
|
+
def filter(self, *args, **kwargs) -> RecordSet:
|
|
35
40
|
"""
|
|
36
41
|
Query the list of a given endpoint. Also take named arguments that match the
|
|
37
42
|
usable filters on a given endpoint.
|
|
@@ -44,7 +49,7 @@ class Endpoint(object):
|
|
|
44
49
|
)
|
|
45
50
|
return RecordSet(self, r)
|
|
46
51
|
|
|
47
|
-
def get(self, *args, **kwargs):
|
|
52
|
+
def get(self, *args, **kwargs) -> Optional[Record]:
|
|
48
53
|
"""
|
|
49
54
|
Return a single object from an endpoint.
|
|
50
55
|
"""
|
|
@@ -62,7 +67,9 @@ class Endpoint(object):
|
|
|
62
67
|
try:
|
|
63
68
|
next(response)
|
|
64
69
|
raise ValueError(
|
|
65
|
-
"get() returned more than one result. Check that the kwarg(s)
|
|
70
|
+
"get() returned more than one result. Check that the kwarg(s) "
|
|
71
|
+
"passed are valid for this endpoint or use filter() or all() "
|
|
72
|
+
"instead."
|
|
66
73
|
)
|
|
67
74
|
except StopIteration:
|
|
68
75
|
return value
|
|
@@ -81,7 +88,7 @@ class Endpoint(object):
|
|
|
81
88
|
else:
|
|
82
89
|
raise e
|
|
83
90
|
|
|
84
|
-
def create(self, *args, **kwargs):
|
|
91
|
+
def create(self, *args, **kwargs) -> Record:
|
|
85
92
|
"""
|
|
86
93
|
Creates an object on an endpoint.
|
|
87
94
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from typing import Any, Optional
|
|
2
3
|
|
|
3
4
|
from pyixapi.core.util import cat
|
|
4
5
|
|
|
@@ -19,15 +20,21 @@ class RequestError(Exception):
|
|
|
19
20
|
)
|
|
20
21
|
else:
|
|
21
22
|
try:
|
|
22
|
-
self.message =
|
|
23
|
+
self.message = (
|
|
24
|
+
f"The request failed with code {r.status_code} "
|
|
25
|
+
f"{r.reason}: {r.json()}"
|
|
26
|
+
)
|
|
23
27
|
except ValueError:
|
|
24
|
-
self.message =
|
|
28
|
+
self.message = (
|
|
29
|
+
f"The request failed with code {r.status_code} "
|
|
30
|
+
f"{r.reason} but details were not found as JSON."
|
|
31
|
+
)
|
|
25
32
|
|
|
26
33
|
super(RequestError, self).__init__(r)
|
|
27
34
|
self.req = r
|
|
28
35
|
self.error = r.text
|
|
29
36
|
|
|
30
|
-
def __str__(self):
|
|
37
|
+
def __str__(self) -> str:
|
|
31
38
|
return self.message
|
|
32
39
|
|
|
33
40
|
|
|
@@ -38,7 +45,7 @@ class ContentError(Exception):
|
|
|
38
45
|
those cases.
|
|
39
46
|
"""
|
|
40
47
|
|
|
41
|
-
def __init__(self, req):
|
|
48
|
+
def __init__(self, req) -> None:
|
|
42
49
|
super(ContentError, self).__init__(req)
|
|
43
50
|
|
|
44
51
|
self.req = req
|
|
@@ -46,11 +53,11 @@ class ContentError(Exception):
|
|
|
46
53
|
"The server returned invalid (non-JSON) data. Maybe not an IX-API server?"
|
|
47
54
|
)
|
|
48
55
|
|
|
49
|
-
def __str__(self):
|
|
56
|
+
def __str__(self) -> str:
|
|
50
57
|
return self.error
|
|
51
58
|
|
|
52
59
|
|
|
53
|
-
class Request
|
|
60
|
+
class Request:
|
|
54
61
|
"""
|
|
55
62
|
Create requests to the IX-API.
|
|
56
63
|
|
|
@@ -74,7 +81,7 @@ class Request(object):
|
|
|
74
81
|
self.url = self.base if not key else cat(self.base, key)
|
|
75
82
|
self.user_agent = user_agent
|
|
76
83
|
|
|
77
|
-
def get_openapi(self):
|
|
84
|
+
def get_openapi(self) -> Any:
|
|
78
85
|
"""
|
|
79
86
|
Get the OpenAPI Spec.
|
|
80
87
|
"""
|
|
@@ -87,7 +94,7 @@ class Request(object):
|
|
|
87
94
|
else:
|
|
88
95
|
raise RequestError(req)
|
|
89
96
|
|
|
90
|
-
def get_version(self):
|
|
97
|
+
def get_version(self) -> int:
|
|
91
98
|
"""
|
|
92
99
|
Get the API version of IX-API.
|
|
93
100
|
|
|
@@ -101,7 +108,7 @@ class Request(object):
|
|
|
101
108
|
except RequestError:
|
|
102
109
|
return 1
|
|
103
110
|
|
|
104
|
-
def get_health(self):
|
|
111
|
+
def get_health(self) -> dict[str, Any]:
|
|
105
112
|
"""
|
|
106
113
|
Get the health from /api/health endpoint in IX-API.
|
|
107
114
|
"""
|
|
@@ -114,7 +121,13 @@ class Request(object):
|
|
|
114
121
|
else:
|
|
115
122
|
raise RequestError(r)
|
|
116
123
|
|
|
117
|
-
def _make_call(
|
|
124
|
+
def _make_call(
|
|
125
|
+
self,
|
|
126
|
+
verb: str = "get",
|
|
127
|
+
url_override: Optional[str] = None,
|
|
128
|
+
add_params: Optional[dict[str, Any]] = None,
|
|
129
|
+
data: Optional[Any] = None,
|
|
130
|
+
) -> Any:
|
|
118
131
|
if verb in ("post", "put") or verb == "delete" and data:
|
|
119
132
|
headers = {"Content-Type": "application/json;"}
|
|
120
133
|
else:
|
|
@@ -147,7 +160,7 @@ class Request(object):
|
|
|
147
160
|
else:
|
|
148
161
|
raise RequestError(r)
|
|
149
162
|
|
|
150
|
-
def get(self, add_params=None):
|
|
163
|
+
def get(self, add_params: Optional[dict[str, Any]] = None) -> Any:
|
|
151
164
|
"""
|
|
152
165
|
Make a GET request to IX-API.
|
|
153
166
|
|
|
@@ -166,7 +179,7 @@ class Request(object):
|
|
|
166
179
|
self.count = len(req)
|
|
167
180
|
yield req
|
|
168
181
|
|
|
169
|
-
def put(self, data):
|
|
182
|
+
def put(self, data: Any) -> Any:
|
|
170
183
|
"""
|
|
171
184
|
Make a PUT request to IX-API.
|
|
172
185
|
|
|
@@ -178,7 +191,7 @@ class Request(object):
|
|
|
178
191
|
"""
|
|
179
192
|
return self._make_call(verb="put", data=data)
|
|
180
193
|
|
|
181
|
-
def post(self, data):
|
|
194
|
+
def post(self, data: Any) -> Any:
|
|
182
195
|
"""
|
|
183
196
|
Make a POST request to IX-API.
|
|
184
197
|
|
|
@@ -190,7 +203,7 @@ class Request(object):
|
|
|
190
203
|
"""
|
|
191
204
|
return self._make_call(verb="post", data=data)
|
|
192
205
|
|
|
193
|
-
def delete(self, data=None):
|
|
206
|
+
def delete(self, data: Optional[Any] = None) -> Any:
|
|
194
207
|
"""
|
|
195
208
|
Make a DELETE request to IX-API.
|
|
196
209
|
|
|
@@ -204,7 +217,7 @@ class Request(object):
|
|
|
204
217
|
"""
|
|
205
218
|
return self._make_call(verb="delete", data=data)
|
|
206
219
|
|
|
207
|
-
def patch(self, data):
|
|
220
|
+
def patch(self, data: Any) -> Any:
|
|
208
221
|
"""
|
|
209
222
|
Make a PATCH request to IX-API.
|
|
210
223
|
|
|
@@ -216,7 +229,7 @@ class Request(object):
|
|
|
216
229
|
"""
|
|
217
230
|
return self._make_call(verb="patch", data=data)
|
|
218
231
|
|
|
219
|
-
def options(self):
|
|
232
|
+
def options(self) -> Any:
|
|
220
233
|
"""
|
|
221
234
|
Make an OPTIONS request to IX-API.
|
|
222
235
|
|
|
@@ -2,7 +2,7 @@ from pyixapi.core.query import Request
|
|
|
2
2
|
from pyixapi.core.util import Hashabledict
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
def get_return(lookup):
|
|
5
|
+
def get_return(lookup) -> int:
|
|
6
6
|
"""
|
|
7
7
|
Return simple representations for items passed to lookup.
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ def get_return(lookup):
|
|
|
15
15
|
return lookup
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class RecordSet
|
|
18
|
+
class RecordSet:
|
|
19
19
|
"""
|
|
20
20
|
Iterator containing :py:class:`.Record` objects.
|
|
21
21
|
|
|
@@ -52,13 +52,13 @@ class RecordSet(object):
|
|
|
52
52
|
>>>
|
|
53
53
|
"""
|
|
54
54
|
|
|
55
|
-
def __init__(self, endpoint, request, **kwargs):
|
|
55
|
+
def __init__(self, endpoint, request, **kwargs) -> None:
|
|
56
56
|
self.endpoint = endpoint
|
|
57
57
|
self.request = request
|
|
58
58
|
self.response = self.request.get()
|
|
59
59
|
self._response_cache = []
|
|
60
60
|
|
|
61
|
-
def __iter__(self):
|
|
61
|
+
def __iter__(self) -> "RecordSet":
|
|
62
62
|
return self
|
|
63
63
|
|
|
64
64
|
def __next__(self):
|
|
@@ -81,7 +81,7 @@ class RecordSet(object):
|
|
|
81
81
|
return self.request.count
|
|
82
82
|
|
|
83
83
|
|
|
84
|
-
class Record
|
|
84
|
+
class Record:
|
|
85
85
|
"""
|
|
86
86
|
Create Python objects from IX-API responses.
|
|
87
87
|
|
|
@@ -144,7 +144,7 @@ class Record(object):
|
|
|
144
144
|
|
|
145
145
|
url = None
|
|
146
146
|
|
|
147
|
-
def __init__(self, values, api, endpoint):
|
|
147
|
+
def __init__(self, values, api, endpoint) -> None:
|
|
148
148
|
self._full_cache = []
|
|
149
149
|
self._init_cache = []
|
|
150
150
|
self.api = api
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import warnings
|
|
2
|
+
from datetime import datetime, timezone
|
|
2
3
|
|
|
3
4
|
import jwt
|
|
4
5
|
|
|
@@ -11,7 +12,7 @@ class InvalidTokenException(Exception):
|
|
|
11
12
|
pass
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class Token
|
|
15
|
+
class Token:
|
|
15
16
|
"""
|
|
16
17
|
A token is at the core of the authentication mechanism of IX-API.
|
|
17
18
|
|
|
@@ -24,37 +25,43 @@ class Token(object):
|
|
|
24
25
|
continue using the API.
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
|
-
def __init__(self, token
|
|
28
|
-
self.encoded = token # Cache signed token data
|
|
29
|
-
self.
|
|
30
|
-
self.expires_at = expires_at
|
|
28
|
+
def __init__(self, token: str, expires_at: datetime) -> None:
|
|
29
|
+
self.encoded: str = token # Cache signed token data
|
|
30
|
+
self.expires_at: datetime = expires_at
|
|
31
31
|
|
|
32
|
-
def __str__(self):
|
|
32
|
+
def __str__(self) -> str:
|
|
33
33
|
return self.encoded
|
|
34
34
|
|
|
35
|
-
def __repr__(self):
|
|
36
|
-
return f"<Token
|
|
35
|
+
def __repr__(self) -> str:
|
|
36
|
+
return f"<Token ttl={self.ttl}s>"
|
|
37
37
|
|
|
38
38
|
@property
|
|
39
|
-
def
|
|
39
|
+
def issued_at(self) -> datetime:
|
|
40
|
+
warnings.warn(
|
|
41
|
+
"Property 'issued_at' is deprecated and value will always be set to now.",
|
|
42
|
+
DeprecationWarning,
|
|
43
|
+
)
|
|
44
|
+
return datetime.now(tz=timezone.utc)
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def ttl(self) -> int:
|
|
40
48
|
"""
|
|
41
49
|
TTL is the number of seconds, from now, before the token expires.
|
|
42
50
|
"""
|
|
43
|
-
seconds = (self.expires_at - datetime.now()).total_seconds()
|
|
51
|
+
seconds = (self.expires_at - datetime.now(timezone.utc)).total_seconds()
|
|
44
52
|
return max(0, seconds)
|
|
45
53
|
|
|
46
54
|
@property
|
|
47
|
-
def is_expired(self):
|
|
55
|
+
def is_expired(self) -> bool:
|
|
48
56
|
"""
|
|
49
57
|
Tell if a token is expired or not (TTL equals to 0).
|
|
50
58
|
"""
|
|
51
59
|
return self.ttl == 0
|
|
52
60
|
|
|
53
61
|
@classmethod
|
|
54
|
-
def from_jwt(cls, token):
|
|
62
|
+
def from_jwt(cls, token: str) -> "Token":
|
|
55
63
|
"""
|
|
56
|
-
Create a new token from a JWT, decoding it and caching
|
|
57
|
-
expiration times.
|
|
64
|
+
Create a new token from a JWT, decoding it and caching its expiration time.
|
|
58
65
|
|
|
59
66
|
:param token: (str) String containing the original encoded token which is the
|
|
60
67
|
result of a POST request to the authentication endpoint.
|
|
@@ -65,8 +72,9 @@ class Token(object):
|
|
|
65
72
|
raise TokenException(e)
|
|
66
73
|
|
|
67
74
|
try:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
return cls(
|
|
76
|
+
token=token,
|
|
77
|
+
expires_at=datetime.fromtimestamp(payload["exp"], tz=timezone.utc),
|
|
78
|
+
)
|
|
71
79
|
except Exception as e:
|
|
72
80
|
raise InvalidTokenException(e)
|
|
@@ -154,10 +154,11 @@ class PoP(Record):
|
|
|
154
154
|
return self.name
|
|
155
155
|
|
|
156
156
|
|
|
157
|
-
class
|
|
157
|
+
class ProductOffering(Record):
|
|
158
158
|
"""
|
|
159
|
-
A
|
|
160
|
-
|
|
159
|
+
A ProductOffering is an offer made by an exchange to be consumed by a client.
|
|
160
|
+
|
|
161
|
+
It is also referenced as "product" in IX-API v1.
|
|
161
162
|
"""
|
|
162
163
|
|
|
163
164
|
def __str__(self):
|
|
@@ -226,15 +227,6 @@ class PortReservation(Record):
|
|
|
226
227
|
return self.id
|
|
227
228
|
|
|
228
229
|
|
|
229
|
-
class ProductOffering(Record):
|
|
230
|
-
"""
|
|
231
|
-
A ProductOffering is an offer made by an exchange to be consumed by a client.
|
|
232
|
-
"""
|
|
233
|
-
|
|
234
|
-
def __str__(self):
|
|
235
|
-
return self.name
|
|
236
|
-
|
|
237
|
-
|
|
238
230
|
class Role(Record):
|
|
239
231
|
"""
|
|
240
232
|
A Role enables a Contact to act for a specific purpose.
|