Skip to content

Commit 55edc0d

Browse files
Added support for Python 3.12 and removed support for insecure versions of Python
* Added Python 3.12 to test suite * Removed support for Python 3.7. Per Python maintainers, 3.7 is EOL and no longer receiving security updates * Excluded additional files that need not trigger tests. * Optimized error checking and introduced common.py enabling method extractions for common code. * Minor import optimizations * Minor linting fixes * Fixed missing NETWORK_DELETE_RETRY_WAIT_TIME argument in meraki/__init__.py * Minor syntactical improvements for README.md
1 parent 3b883ec commit 55edc0d

7 files changed

Lines changed: 73 additions & 58 deletions

File tree

.github/workflows/test-library.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,24 @@ on:
88
- 'main'
99
- 'release'
1010
paths-ignore:
11-
- '.github/workflows/**'
11+
- '.github/**'
12+
- 'examples/**'
13+
- 'meraki/aio/**'
14+
- 'notebooks/**'
15+
- 'README.md'
16+
- 'LICENSE'
17+
- 'setup.py'
1218
pull_request:
1319
branches:
1420
- 'main'
21+
paths-ignore:
22+
- '.github/**'
23+
- 'examples/**'
24+
- 'meraki/aio/**'
25+
- 'notebooks/**'
26+
- 'README.md'
27+
- 'LICENSE'
28+
- 'setup.py'
1529
workflow_dispatch:
1630

1731

@@ -22,7 +36,7 @@ jobs:
2236
strategy:
2337
fail-fast: false
2438
matrix:
25-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
39+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
2640

2741
steps:
2842
- uses: actions/checkout@v3
@@ -44,3 +58,4 @@ jobs:
4458
- name: Test with pytest
4559
run: |
4660
pytest --apikey ${{ secrets.TEST_ORG_API_KEY }} --o ${{ secrets.TEST_ORG_ID }}
61+

README.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Meraki Dashboard API Python Library
22

3-
The Meraki Dashboard API Python library provides all current Meraki [dashboard API](https://developer.cisco.com/meraki/api-v1/) calls to interface with the Cisco Meraki cloud-managed platform. Meraki generates the library based on dashboard API's OpenAPI spec to keep it up to date with the latest API releases, and provides the full source code for the library including the tools used to generate the library, if you are participating in the Early Access program or would like to contribute to the development of the library. Meraki welcomes constructive pull requests that maintain backwards compatibility with prior versions. The library requires Python 3.7+, receives support from the community, and you can install it via [PyPI](https://pypi.org/project/meraki/):
3+
The Meraki Dashboard API Python library provides all current Meraki [dashboard API](https://developer.cisco.com/meraki/api-v1/) calls to interface with the Cisco Meraki cloud-managed platform. Meraki generates the library based on dashboard API's OpenAPI spec to keep it up to date with the latest API releases, and provides the full source code for the library including the tools used to generate the library, if you are participating in the Early Access program or would like to contribute to the development of the library. Meraki welcomes constructive pull requests that maintain backwards compatibility with prior versions. The library requires Python 3.8+, receives support from the community, and you can install it via [PyPI](https://pypi.org/project/meraki/):
44

55
pip install --upgrade meraki
66

@@ -41,7 +41,7 @@ While you can make direct HTTP requests to dashboard API in any programming lang
4141
1. Export your API key as an [environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html), for example:
4242

4343
```shell
44-
export MERAKI_DASHBOARD_API_KEY=093b24e85df15a3e66f1fc359f4c48493eaa1b73
44+
export MERAKI_DASHBOARD_API_KEY=YOUR_KEY_HERE
4545
```
4646

4747
2. Alternatively, define your API key as a variable in your source code; this method is not recommended due to its inherent insecurity.
@@ -79,7 +79,7 @@ The usage is similiar to the sequential version above. However it has has some d
7979
1. Export your API key as an [environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html), for example:
8080

8181
```shell
82-
export MERAKI_DASHBOARD_API_KEY=093b24e85df15a3e66f1fc359f4c48493eaa1b73
82+
export MERAKI_DASHBOARD_API_KEY=YOUR_KEY_HERE
8383
```
8484

8585
2. Alternatively, define your API key as a variable in your source code; this method is not recommended due to its inherent insecurity.
@@ -107,11 +107,8 @@ The usage is similiar to the sequential version above. However it has has some d
107107
import asyncio
108108
109109
if __name__ == "__main__":
110-
loop = asyncio.get_event_loop()
111-
loop.run_until_complete(my_async_entry_point())
112-
113-
# if you are using Python 3.7+ you can also simply
114-
# use the following line instead of the two lines above
110+
111+
# replace my_async_entry_point with the name of your entry point method
115112
asyncio.run(my_async_entry_point())
116113
```
117114

meraki/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from datetime import datetime
21
import logging
32
import os
43

@@ -30,6 +29,7 @@
3029
WAIT_ON_RATE_LIMIT,
3130
NGINX_429_RETRY_WAIT_TIME,
3231
ACTION_BATCH_RETRY_WAIT_TIME,
32+
NETWORK_DELETE_RETRY_WAIT_TIME,
3333
RETRY_4XX_ERROR,
3434
RETRY_4XX_ERROR_WAIT_TIME,
3535
MAXIMUM_RETRIES,

meraki/aio/rest_session.py

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
import logging
2-
import sys
3-
from datetime import datetime
4-
import json
5-
import platform
61
import random
7-
import urllib.parse
2+
import time
83
import asyncio
4+
import json
5+
import sys
96
import ssl
10-
import time
11-
127

8+
import urllib.parse
9+
from datetime import datetime
1310
import aiohttp
1411

1512
from meraki.__init__ import __version__
13+
from meraki.common import *
1614
from meraki.config import *
17-
from meraki.exceptions import *
1815
from meraki.rest_session import user_agent_extended
1916

2017

@@ -66,18 +63,7 @@ def __init__(
6663
self.use_iterator_for_get_pages = use_iterator_for_get_pages
6764

6865
# Check minimum Python version
69-
version_warning_string = f'This library requires Python 3.7 at minimum. Python versions 3.6 and below ' \
70-
f'are end of life and end of support per the Python maintainers, and your ' \
71-
f'interpreter version details are: \n' \
72-
f'platform.python_version_tuple()[0] = {platform.python_version_tuple()[0]}\n' \
73-
f'platform.python_version_tuple()[1] = {platform.python_version_tuple()[1]}\n' \
74-
f'platform.python_version is {platform.python_version()}\n' \
75-
f'Please consult the readme at your convenience: ' \
76-
f'https://github.com/meraki/dashboard-api-python'
77-
if int(platform.python_version_tuple()[0]) != 3:
78-
sys.exit(version_warning_string)
79-
elif int(platform.python_version_tuple()[1]) < 7:
80-
sys.exit(version_warning_string)
66+
check_python_version()
8167

8268
# Check base URL
8369
if "v0" in self._base_url:

meraki/common.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import platform
2+
from meraki.exceptions import *
3+
4+
5+
def check_python_version():
6+
# Check minimum Python version
7+
8+
if not (int(platform.python_version_tuple()[0]) == 3 and int(platform.python_version_tuple()[1]) >= 8):
9+
message = (
10+
f"This library requires Python 3.8 at minimum. Python versions 3.7 and below "
11+
f"no longer receive security updates since reaching end of life and of support "
12+
f"per the Python maintainers. Your interpreter version is: {platform.python_version()}. "
13+
f"Please consult the readme at your convenience: https://github.com/meraki/dashboard-api-python "
14+
f"Additional details: "
15+
f"python_version_tuple()[0] = {platform.python_version_tuple()[0]}; "
16+
f"python_version_tuple()[1] = {platform.python_version_tuple()[1]} "
17+
)
18+
19+
raise PythonVersionError(message)

meraki/exceptions.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ class APIResponseError(Exception):
1313
Exception class raised from HTTP class methods. Used as a single catch-all error for any possible
1414
requests exception error that might happen during communication with Meraki API to simplify caller coding.
1515
"""
16+
1617
def __init__(self, obj_name, status_code, error_msg):
1718
self.obj_name = obj_name
1819
self.status_code = status_code
1920
self.reason = error_msg
2021

2122
def exc_message(self):
22-
return f'HTTP call within object "{self.obj_name}" failed. Status code is "{self.status_code}". Error message is: "{self.reason}".'
23+
return (
24+
f'HTTP call within object "{self.obj_name}" failed. Status code is "{self.status_code}". '
25+
f'Error message is: "{self.reason}".'
26+
)
2327

2428
def json(self):
2529
return dict(error=self.reason, status_code=self.status_code)
@@ -94,3 +98,13 @@ def __init__(self, metadata, response, message):
9498

9599
def __repr__(self):
96100
return f"{self.tag}, {self.operation} - {self.status} {self.reason}, {self.message}"
101+
102+
103+
class PythonVersionError(Exception):
104+
"""Exception raised for unsupported Python versions."""
105+
106+
def __init__(self, message):
107+
108+
self.message = message
109+
110+
super().__init__(self.message)

meraki/rest_session.py

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import sys
2-
from datetime import datetime
3-
import json
4-
import platform
51
import random
6-
import urllib.parse
72
import time
8-
93
import requests
4+
import json
5+
import sys
6+
7+
import urllib.parse
8+
from datetime import datetime
109

11-
from meraki.config import *
12-
from meraki.exceptions import *
1310
from meraki.__init__ import __version__
11+
from meraki.common import *
12+
from meraki.config import *
1413

1514

1615
def user_agent_extended(be_geo_id, caller):
@@ -55,22 +54,6 @@ def user_agent_extended(be_geo_id, caller):
5554

5655

5756
# Main module interface
58-
def check_python_version():
59-
# Check minimum Python version
60-
version_warning_string = f'This library requires Python 3.7 at minimum. Python versions 3.6 and below ' \
61-
f'are end of life and end of support per the Python maintainers, and your ' \
62-
f'interpreter version details are: \n' \
63-
f'platform.python_version_tuple()[0] = {platform.python_version_tuple()[0]}\n' \
64-
f'platform.python_version_tuple()[1] = {platform.python_version_tuple()[1]}\n' \
65-
f'platform.python_version is {platform.python_version()}\n' \
66-
f'Please consult the readme at your convenience: ' \
67-
f'https://github.com/meraki/dashboard-api-python'
68-
if int(platform.python_version_tuple()[0]) != 3:
69-
sys.exit(version_warning_string)
70-
elif int(platform.python_version_tuple()[1]) < 7:
71-
sys.exit(version_warning_string)
72-
73-
7457
class RestSession(object):
7558
def __init__(
7659
self,
@@ -207,7 +190,8 @@ def request(self, metadata, method, url, **kwargs):
207190
retries -= 1
208191
if retries == 0:
209192
if e.response and e.response.status_code:
210-
raise APIError(metadata, APIResponseError(e.__class__.__name__, e.response.status_code, str(e)))
193+
raise APIError(metadata, APIResponseError(e.__class__.__name__,
194+
e.response.status_code, str(e)))
211195
else:
212196
raise APIError(metadata, APIResponseError(e.__class__.__name__, 503, str(e)))
213197
else:

0 commit comments

Comments
 (0)