cisco-eox-query 1.0.0__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.
- cisco_eox_query-1.0.0/.gitignore +18 -0
- cisco_eox_query-1.0.0/LICENSE +21 -0
- cisco_eox_query-1.0.0/PKG-INFO +171 -0
- cisco_eox_query-1.0.0/README.md +145 -0
- cisco_eox_query-1.0.0/SECURITY.md +28 -0
- cisco_eox_query-1.0.0/pyproject.toml +79 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/__init__.py +55 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/_base.py +279 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/cli.py +272 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/constants.py +29 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/examples.py +133 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/py.typed +0 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/v5/__init__.py +26 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/v5/client.py +221 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/v5/constants.py +43 -0
- cisco_eox_query-1.0.0/src/cisco_eox_query/v5/models.py +113 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dave Heckman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: cisco-eox-query
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python client for the Cisco End-of-Life (EOX) API
|
|
5
|
+
Project-URL: Homepage, https://github.com/dheckman-dev/cisco-eox-query
|
|
6
|
+
Project-URL: Repository, https://github.com/dheckman-dev/cisco-eox-query
|
|
7
|
+
Project-URL: Documentation, https://github.com/dheckman-dev/cisco-eox-query#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/dheckman-dev/cisco-eox-query/issues
|
|
9
|
+
Author-email: Dave Heckman <david@heckman.network>
|
|
10
|
+
Maintainer-email: Dave Heckman <david@heckman.network>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: cisco,end-of-life,end-of-support,eox,httpx,pydantic
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: httpx>=0.28.1
|
|
24
|
+
Requires-Dist: pydantic>=2.7
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# cisco-eox-query
|
|
28
|
+
|
|
29
|
+
Python client for the [Cisco End-of-Life (EOX) API](https://developer.cisco.com/docs/support-apis/eox).
|
|
30
|
+
|
|
31
|
+
Built on `httpx` for transport and `pydantic` for response models. This package
|
|
32
|
+
implements the Cisco EOX API v5 as described by
|
|
33
|
+
`Cisco-End-of-Life-EOX-v5_0.wadl`.
|
|
34
|
+
|
|
35
|
+

|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
## Versioning
|
|
39
|
+
|
|
40
|
+
Library major versions track the EOX API version:
|
|
41
|
+
|
|
42
|
+
| `cisco-eox-query` | EOX API | Status |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| 1.x | v5 | current |
|
|
45
|
+
| 2.x | v6 | future, when released |
|
|
46
|
+
|
|
47
|
+
The versioned implementation lives under `cisco_eox_query.v5`. The top-level
|
|
48
|
+
package re-exports the latest supported version for convenience.
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install cisco-eox-query
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Authentication
|
|
57
|
+
|
|
58
|
+
EOX is one of the Cisco Support APIs and requires a Smart Net Total Care (SNTC)
|
|
59
|
+
or Partner Support Service (PSS) entitlement. Register an application at the
|
|
60
|
+
[Cisco API Console](https://apiconsole.cisco.com/) to obtain a client ID and
|
|
61
|
+
client secret. The client exchanges them for a bearer token (client-credentials
|
|
62
|
+
grant) and refreshes it automatically before expiry.
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from cisco_eox_query import EOXClient
|
|
68
|
+
|
|
69
|
+
with EOXClient(client_id="...", client_secret="...") as client:
|
|
70
|
+
records = list(client.iter_product_ids(["WS-C2960X-48TS-L", "WIC-1T="]))
|
|
71
|
+
for record in records:
|
|
72
|
+
print(record.eol_product_id, record.last_date_of_support)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
All four WADL endpoints are exposed as `search_*` methods returning an
|
|
76
|
+
`EOXResponse` (with `records`, `pagination`, and optional `error`), plus
|
|
77
|
+
`iter_*` variants that follow pagination automatically:
|
|
78
|
+
|
|
79
|
+
| Endpoint | Method |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `EOXByDates/{pageIndex}/{startDate}/{endDate}` | `search_by_dates` / `iter_dates` |
|
|
82
|
+
| `EOXByProductID/{pageIndex}/{productIDs}` | `search_by_product_ids` / `iter_product_ids` |
|
|
83
|
+
| `EOXBySerialNumber/{pageIndex}/{serialNumbers}` | `search_by_serial_numbers` / `iter_serial_numbers` |
|
|
84
|
+
| `EOXBySWReleaseString/{pageIndex}` | `search_by_software_releases` / `iter_software_releases` |
|
|
85
|
+
|
|
86
|
+
The `iter_*` variants accept an optional `max_pages` keyword (default 1000) as
|
|
87
|
+
a safety valve against runaway pagination; if the API never reports a final
|
|
88
|
+
page, a `PaginationError` is raised instead of looping forever.
|
|
89
|
+
|
|
90
|
+
If you already hold a token:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
client = EOXClient(access_token="...")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Command line
|
|
97
|
+
|
|
98
|
+
The package installs an `eox-query` console script. Credentials may be passed
|
|
99
|
+
as flags or via `EOX_CLIENT_ID`, `EOX_CLIENT_SECRET`, and `EOX_ACCESS_TOKEN`
|
|
100
|
+
environment variables.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
eox-query --client-id ... --client-secret ... pid WS-C2960X-48TS-L WIC-1T=
|
|
104
|
+
eox-query --client-id ... --client-secret ... serial JAE11108ESH SAD11510738
|
|
105
|
+
eox-query --client-id ... --client-secret ... software 12.4\(15\)T,IOS
|
|
106
|
+
eox-query --client-id ... --client-secret ... dates 2011-01-01 2015-12-31 --attribs EO_SALES_DATE
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Run `eox-query --examples` for annotated usage examples, or
|
|
110
|
+
`eox-query <command> --examples` (e.g. `eox-query pid --examples`) for
|
|
111
|
+
command-specific examples. Examples are also embedded in `--help` output.
|
|
112
|
+
|
|
113
|
+
Logs go to stderr with the format `YYYY-MM-DD HH:MM:SS - SEVERITY - module - message`; queried records print to stdout so they can be piped. Diagnostics are silent by default and increase with `-v` (info) / `-vv` (debug).
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
eox-query -vv --client-id ... --client-secret ... pid WIC-1T=
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Library users get the same structured loggers (`cisco_eox_query._base`, `cisco_eox_query.v5.client`, ...) without any handler configuration.
|
|
120
|
+
|
|
121
|
+
## Rate limiting and retries
|
|
122
|
+
|
|
123
|
+
The EOX API is limited to 5 requests/second and 5000 requests/day. The client
|
|
124
|
+
handles this automatically:
|
|
125
|
+
|
|
126
|
+
- Requests are throttled to stay under the per-second limit (default 0.25s
|
|
127
|
+
between requests, configurable via `min_request_interval`).
|
|
128
|
+
- HTTP 429/408/425/5xx responses and transport errors are retried up to
|
|
129
|
+
`max_retries` times (default 3) with `retry_delay` seconds between attempts
|
|
130
|
+
(default 5s), honoring the server's `Retry-After` header (both delay-seconds
|
|
131
|
+
and RFC 7231 HTTP-date formats) when present.
|
|
132
|
+
- After retries are exhausted on a 429, a `RateLimitError` is raised; the CLI
|
|
133
|
+
prints a message about hitting the daily limit and exits with code 2.
|
|
134
|
+
- Non-retryable errors (e.g. HTTP 403) are raised immediately.
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from cisco_eox_query import EOXClient, RateLimitError
|
|
138
|
+
|
|
139
|
+
with EOXClient(client_id="...", client_secret="...", max_retries=5, retry_delay=2.0) as client:
|
|
140
|
+
try:
|
|
141
|
+
for record in client.iter_product_ids(["WIC-1T="]):
|
|
142
|
+
print(record.eol_product_id)
|
|
143
|
+
except RateLimitError as exc:
|
|
144
|
+
print(f"Hit the daily request limit: {exc}")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Error handling
|
|
148
|
+
|
|
149
|
+
- `EOXAPIError` — raised when a response contains an `EOXError` payload. Call
|
|
150
|
+
`response.raise_for_error()` on `search_*` results; the `iter_*` variants
|
|
151
|
+
raise automatically.
|
|
152
|
+
- `RetryError` — a request failed after exhausting all retries.
|
|
153
|
+
- `RateLimitError` — a rate-limited request failed after exhausting retries
|
|
154
|
+
(subclass of `RetryError`).
|
|
155
|
+
- `PaginationError` — pagination did not terminate within `max_pages`
|
|
156
|
+
(subclass of `RetryError`).
|
|
157
|
+
- `ValueError` — invalid input, a malformed JSON response body, or an
|
|
158
|
+
unexpected response shape (possible API schema change). The message includes
|
|
159
|
+
the request path and the first validation error.
|
|
160
|
+
|
|
161
|
+
The client tolerates common API quirks: a `null` `EOXRecord` is treated as an
|
|
162
|
+
empty result set, and a single record returned as a bare object (not wrapped
|
|
163
|
+
in a list) is accepted.
|
|
164
|
+
|
|
165
|
+
## Development
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
uv sync
|
|
169
|
+
uv run pytest
|
|
170
|
+
uv build
|
|
171
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# cisco-eox-query
|
|
2
|
+
|
|
3
|
+
Python client for the [Cisco End-of-Life (EOX) API](https://developer.cisco.com/docs/support-apis/eox).
|
|
4
|
+
|
|
5
|
+
Built on `httpx` for transport and `pydantic` for response models. This package
|
|
6
|
+
implements the Cisco EOX API v5 as described by
|
|
7
|
+
`Cisco-End-of-Life-EOX-v5_0.wadl`.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
## Versioning
|
|
13
|
+
|
|
14
|
+
Library major versions track the EOX API version:
|
|
15
|
+
|
|
16
|
+
| `cisco-eox-query` | EOX API | Status |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| 1.x | v5 | current |
|
|
19
|
+
| 2.x | v6 | future, when released |
|
|
20
|
+
|
|
21
|
+
The versioned implementation lives under `cisco_eox_query.v5`. The top-level
|
|
22
|
+
package re-exports the latest supported version for convenience.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install cisco-eox-query
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Authentication
|
|
31
|
+
|
|
32
|
+
EOX is one of the Cisco Support APIs and requires a Smart Net Total Care (SNTC)
|
|
33
|
+
or Partner Support Service (PSS) entitlement. Register an application at the
|
|
34
|
+
[Cisco API Console](https://apiconsole.cisco.com/) to obtain a client ID and
|
|
35
|
+
client secret. The client exchanges them for a bearer token (client-credentials
|
|
36
|
+
grant) and refreshes it automatically before expiry.
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from cisco_eox_query import EOXClient
|
|
42
|
+
|
|
43
|
+
with EOXClient(client_id="...", client_secret="...") as client:
|
|
44
|
+
records = list(client.iter_product_ids(["WS-C2960X-48TS-L", "WIC-1T="]))
|
|
45
|
+
for record in records:
|
|
46
|
+
print(record.eol_product_id, record.last_date_of_support)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
All four WADL endpoints are exposed as `search_*` methods returning an
|
|
50
|
+
`EOXResponse` (with `records`, `pagination`, and optional `error`), plus
|
|
51
|
+
`iter_*` variants that follow pagination automatically:
|
|
52
|
+
|
|
53
|
+
| Endpoint | Method |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| `EOXByDates/{pageIndex}/{startDate}/{endDate}` | `search_by_dates` / `iter_dates` |
|
|
56
|
+
| `EOXByProductID/{pageIndex}/{productIDs}` | `search_by_product_ids` / `iter_product_ids` |
|
|
57
|
+
| `EOXBySerialNumber/{pageIndex}/{serialNumbers}` | `search_by_serial_numbers` / `iter_serial_numbers` |
|
|
58
|
+
| `EOXBySWReleaseString/{pageIndex}` | `search_by_software_releases` / `iter_software_releases` |
|
|
59
|
+
|
|
60
|
+
The `iter_*` variants accept an optional `max_pages` keyword (default 1000) as
|
|
61
|
+
a safety valve against runaway pagination; if the API never reports a final
|
|
62
|
+
page, a `PaginationError` is raised instead of looping forever.
|
|
63
|
+
|
|
64
|
+
If you already hold a token:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
client = EOXClient(access_token="...")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Command line
|
|
71
|
+
|
|
72
|
+
The package installs an `eox-query` console script. Credentials may be passed
|
|
73
|
+
as flags or via `EOX_CLIENT_ID`, `EOX_CLIENT_SECRET`, and `EOX_ACCESS_TOKEN`
|
|
74
|
+
environment variables.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
eox-query --client-id ... --client-secret ... pid WS-C2960X-48TS-L WIC-1T=
|
|
78
|
+
eox-query --client-id ... --client-secret ... serial JAE11108ESH SAD11510738
|
|
79
|
+
eox-query --client-id ... --client-secret ... software 12.4\(15\)T,IOS
|
|
80
|
+
eox-query --client-id ... --client-secret ... dates 2011-01-01 2015-12-31 --attribs EO_SALES_DATE
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Run `eox-query --examples` for annotated usage examples, or
|
|
84
|
+
`eox-query <command> --examples` (e.g. `eox-query pid --examples`) for
|
|
85
|
+
command-specific examples. Examples are also embedded in `--help` output.
|
|
86
|
+
|
|
87
|
+
Logs go to stderr with the format `YYYY-MM-DD HH:MM:SS - SEVERITY - module - message`; queried records print to stdout so they can be piped. Diagnostics are silent by default and increase with `-v` (info) / `-vv` (debug).
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
eox-query -vv --client-id ... --client-secret ... pid WIC-1T=
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Library users get the same structured loggers (`cisco_eox_query._base`, `cisco_eox_query.v5.client`, ...) without any handler configuration.
|
|
94
|
+
|
|
95
|
+
## Rate limiting and retries
|
|
96
|
+
|
|
97
|
+
The EOX API is limited to 5 requests/second and 5000 requests/day. The client
|
|
98
|
+
handles this automatically:
|
|
99
|
+
|
|
100
|
+
- Requests are throttled to stay under the per-second limit (default 0.25s
|
|
101
|
+
between requests, configurable via `min_request_interval`).
|
|
102
|
+
- HTTP 429/408/425/5xx responses and transport errors are retried up to
|
|
103
|
+
`max_retries` times (default 3) with `retry_delay` seconds between attempts
|
|
104
|
+
(default 5s), honoring the server's `Retry-After` header (both delay-seconds
|
|
105
|
+
and RFC 7231 HTTP-date formats) when present.
|
|
106
|
+
- After retries are exhausted on a 429, a `RateLimitError` is raised; the CLI
|
|
107
|
+
prints a message about hitting the daily limit and exits with code 2.
|
|
108
|
+
- Non-retryable errors (e.g. HTTP 403) are raised immediately.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from cisco_eox_query import EOXClient, RateLimitError
|
|
112
|
+
|
|
113
|
+
with EOXClient(client_id="...", client_secret="...", max_retries=5, retry_delay=2.0) as client:
|
|
114
|
+
try:
|
|
115
|
+
for record in client.iter_product_ids(["WIC-1T="]):
|
|
116
|
+
print(record.eol_product_id)
|
|
117
|
+
except RateLimitError as exc:
|
|
118
|
+
print(f"Hit the daily request limit: {exc}")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Error handling
|
|
122
|
+
|
|
123
|
+
- `EOXAPIError` — raised when a response contains an `EOXError` payload. Call
|
|
124
|
+
`response.raise_for_error()` on `search_*` results; the `iter_*` variants
|
|
125
|
+
raise automatically.
|
|
126
|
+
- `RetryError` — a request failed after exhausting all retries.
|
|
127
|
+
- `RateLimitError` — a rate-limited request failed after exhausting retries
|
|
128
|
+
(subclass of `RetryError`).
|
|
129
|
+
- `PaginationError` — pagination did not terminate within `max_pages`
|
|
130
|
+
(subclass of `RetryError`).
|
|
131
|
+
- `ValueError` — invalid input, a malformed JSON response body, or an
|
|
132
|
+
unexpected response shape (possible API schema change). The message includes
|
|
133
|
+
the request path and the first validation error.
|
|
134
|
+
|
|
135
|
+
The client tolerates common API quirks: a `null` `EOXRecord` is treated as an
|
|
136
|
+
empty result set, and a single record returned as a bare object (not wrapped
|
|
137
|
+
in a list) is accepted.
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
uv sync
|
|
143
|
+
uv run pytest
|
|
144
|
+
uv build
|
|
145
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
Only the latest 1.x release receives security fixes.
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| ------- | --------- |
|
|
9
|
+
| latest 1.x | Yes |
|
|
10
|
+
| older 1.x | No |
|
|
11
|
+
|
|
12
|
+
## Reporting a Vulnerability
|
|
13
|
+
|
|
14
|
+
Please do **not** open a public issue for a security vulnerability.
|
|
15
|
+
|
|
16
|
+
Instead, report it privately via one of:
|
|
17
|
+
|
|
18
|
+
- **GitHub private security advisory:** <https://github.com/dheckman-dev/cisco-eox-query/security/advisories/new>
|
|
19
|
+
- **Email:** [david@heckman.network](mailto:david@heckman.network)
|
|
20
|
+
|
|
21
|
+
We will acknowledge receipt within **48 hours** and work toward coordinated disclosure, generally publishing a fix and advisory within 90 days or as agreed with the reporter.
|
|
22
|
+
|
|
23
|
+
## Security Considerations for Users
|
|
24
|
+
|
|
25
|
+
- **Credentials:** Cisco EOX API credentials (`client_id`/`client_secret`) must be supplied at runtime via environment variables (`EOX_CLIENT_ID`, `EOX_CLIENT_SECRET`, `EOX_ACCESS_TOKEN`) or constructor arguments. Never hard-code or commit credentials.
|
|
26
|
+
- **TLS:** All traffic to the Cisco API is over HTTPS. The client does not disable TLS certificate verification.
|
|
27
|
+
- **Network posture:** The package only makes outbound requests to the Cisco EOX API endpoints. It does not accept inbound connections.
|
|
28
|
+
- **Dependencies:** Dependencies are pinned via `uv.lock`. Keep the package updated to receive dependency security fixes.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cisco-eox-query"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Python client for the Cisco End-of-Life (EOX) API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Dave Heckman", email="david@heckman.network"},
|
|
12
|
+
]
|
|
13
|
+
maintainers = [
|
|
14
|
+
{ name = "Dave Heckman", email="david@heckman.network"},
|
|
15
|
+
]
|
|
16
|
+
requires-python = ">=3.11"
|
|
17
|
+
license = "MIT"
|
|
18
|
+
keywords = ["cisco", "eox", "end-of-life", "end-of-support", "httpx", "pydantic"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Programming Language :: Python :: 3.14",
|
|
26
|
+
"License :: OSI Approved :: MIT License",
|
|
27
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"httpx>=0.28.1",
|
|
31
|
+
"pydantic>=2.7",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
eox-query = "cisco_eox_query.cli:main"
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/dheckman-dev/cisco-eox-query"
|
|
39
|
+
Repository = "https://github.com/dheckman-dev/cisco-eox-query"
|
|
40
|
+
Documentation = "https://github.com/dheckman-dev/cisco-eox-query#readme"
|
|
41
|
+
Issues = "https://github.com/dheckman-dev/cisco-eox-query/issues"
|
|
42
|
+
|
|
43
|
+
[dependency-groups]
|
|
44
|
+
dev = [
|
|
45
|
+
"pytest>=8.0",
|
|
46
|
+
"pytest-cov>=4.0",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["src/cisco_eox_query"]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.sdist]
|
|
53
|
+
exclude = [
|
|
54
|
+
"/.github",
|
|
55
|
+
"/.envrc",
|
|
56
|
+
"/.gitignore",
|
|
57
|
+
"/.pytest_cache",
|
|
58
|
+
"/.python-version",
|
|
59
|
+
"/.tox",
|
|
60
|
+
"/.venv",
|
|
61
|
+
"/.coverage",
|
|
62
|
+
"/coverage.xml",
|
|
63
|
+
"/dist",
|
|
64
|
+
"/tests",
|
|
65
|
+
"/tox.ini",
|
|
66
|
+
"/uv.lock",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
pythonpath = ["src"]
|
|
72
|
+
|
|
73
|
+
[tool.coverage.run]
|
|
74
|
+
source = ["cisco_eox_query"]
|
|
75
|
+
branch = true
|
|
76
|
+
|
|
77
|
+
[tool.coverage.report]
|
|
78
|
+
fail_under = 80
|
|
79
|
+
show_missing = true
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Client for the Cisco End-of-Life (EOX) API.
|
|
2
|
+
|
|
3
|
+
Versioning
|
|
4
|
+
----------
|
|
5
|
+
Library major versions track the EOX API version:
|
|
6
|
+
|
|
7
|
+
- ``cisco-eox-query`` 1.x implements the EOX API **v5**.
|
|
8
|
+
- ``cisco-eox-query`` 2.x will implement the EOX API **v6** (when released).
|
|
9
|
+
|
|
10
|
+
The versioned implementation lives in :mod:`cisco_eox_query.v5`; this module
|
|
11
|
+
re-exports it as the default. Pin an explicit version with::
|
|
12
|
+
|
|
13
|
+
from cisco_eox_query.v5 import EOXClient
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
19
|
+
|
|
20
|
+
from cisco_eox_query._base import PaginationError, RateLimitError, RetryError
|
|
21
|
+
from cisco_eox_query.v5 import (
|
|
22
|
+
EOX_ATTRIBS,
|
|
23
|
+
OS_TYPES,
|
|
24
|
+
EOXAPIError,
|
|
25
|
+
EOXClient,
|
|
26
|
+
EOXErrorInfo,
|
|
27
|
+
EOXRecord,
|
|
28
|
+
EOXResponse,
|
|
29
|
+
MigrationDetails,
|
|
30
|
+
PaginationResponseRecord,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
__version__ = version("cisco-eox-query")
|
|
35
|
+
except PackageNotFoundError:
|
|
36
|
+
__version__ = "1.0.0"
|
|
37
|
+
|
|
38
|
+
SUPPORTED_API_VERSION = 5
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"EOXClient",
|
|
42
|
+
"EOXRecord",
|
|
43
|
+
"EOXResponse",
|
|
44
|
+
"EOXErrorInfo",
|
|
45
|
+
"EOXAPIError",
|
|
46
|
+
"MigrationDetails",
|
|
47
|
+
"PaginationResponseRecord",
|
|
48
|
+
"RetryError",
|
|
49
|
+
"RateLimitError",
|
|
50
|
+
"PaginationError",
|
|
51
|
+
"EOX_ATTRIBS",
|
|
52
|
+
"OS_TYPES",
|
|
53
|
+
"SUPPORTED_API_VERSION",
|
|
54
|
+
"__version__",
|
|
55
|
+
]
|