Skip to content

Commit ebf8346

Browse files
authored
Add support for python up to 3.11 (#265)
* Add support for python up to 3.11 * update pre-commit * Fix None type check from typing Optional * Disable pylint deprecated option * Force certain names in exceptions * PR cleanup tasks
1 parent e5bbb8f commit ebf8346

File tree

17 files changed

+94
-81
lines changed

17 files changed

+94
-81
lines changed

.github/workflows/pr-ci.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
matrix:
1515
os: [ubuntu-latest, macos-latest, windows-latest]
16-
python: [ 3.7, 3.8, 3.9 ]
16+
python: [ "3.8", "3.9", "3.10", "3.11" ]
1717
steps:
1818
- uses: actions/checkout@v3
1919
- name: Set up Python ${{ matrix.python }}
@@ -34,11 +34,11 @@ jobs:
3434
- name: pre-commit checks
3535
run: |
3636
pre-commit run --all-files
37-
- name: End to End Resource Packaging Test Python 3.6
38-
run: ./e2e-test.sh python36
39-
- name: End to End Resource Packaging Test Python 3.7
40-
run: ./e2e-test.sh python37
4137
- name: End to End Resource Packaging Test Python 3.8
4238
run: ./e2e-test.sh python38
4339
- name: End to End Resource Packaging Test Python 3.9
4440
run: ./e2e-test.sh python39
41+
- name: End to End Resource Packaging Test Python 3.10
42+
run: ./e2e-test.sh python310
43+
- name: End to End Resource Packaging Test Python 3.11
44+
run: ./e2e-test.sh python311

.pre-commit-config.yaml

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ repos:
77
- id: isort
88
# language_version: python3.6
99
- repo: https://github.com/psf/black
10-
rev: 22.8.0
10+
rev: 23.9.1
1111
hooks:
1212
- id: black
1313
exclude: templates/
1414
- repo: https://github.com/pre-commit/pre-commit-hooks
15-
rev: v4.1.0
15+
rev: v4.4.0
1616
hooks:
1717
- id: check-case-conflict
1818
- id: end-of-file-fixer
@@ -28,7 +28,7 @@ repos:
2828
- id: check-merge-conflict
2929
- id: check-yaml
3030
- repo: https://github.com/pycqa/flake8
31-
rev: "5.0.4"
31+
rev: 6.1.0
3232
hooks:
3333
- id: flake8
3434
additional_dependencies:
@@ -41,18 +41,18 @@ repos:
4141
# language_version: python3.6
4242
exclude: templates/
4343
- repo: https://github.com/pre-commit/pygrep-hooks
44-
rev: v1.9.0
44+
rev: v1.10.0
4545
hooks:
4646
- id: python-check-blanket-noqa
4747
- id: python-check-mock-methods
4848
- id: python-no-log-warn
4949
- repo: https://github.com/PyCQA/bandit
50-
rev: "1.7.1"
50+
rev: 1.7.5
5151
hooks:
5252
- id: bandit
5353
files: ^(src|python)/
5454
- repo: https://github.com/pre-commit/mirrors-mypy
55-
rev: v0.812
55+
rev: v1.5.1
5656
hooks:
5757
- id: mypy
5858
files: ^src/

.pylintrc

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ persistent=yes
99
disable=
1010
missing-docstring, # not everything needs a docstring
1111
fixme, # work in progress
12-
bad-continuation, # clashes with black
1312
too-few-public-methods, # triggers when inheriting
1413
ungrouped-imports, # clashes with isort
1514
duplicate-code, # broken, setup.py

python/rpdk/python/codegen.py

+20-15
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ def validate_no(value):
3939
return value.lower() not in ("n", "no")
4040

4141

42-
class Python36LanguagePlugin(LanguagePlugin):
42+
class _PythonLanguagePlugin(LanguagePlugin):
4343
MODULE_NAME = __name__
44-
NAME = "python36"
45-
RUNTIME = "python3.6"
44+
NAME = ""
45+
RUNTIME = ""
4646
HOOK_ENTRY_POINT = "{}.handlers.hook"
4747
RESOURCE_ENTRY_POINT = "{}.handlers.resource"
4848
TEST_ENTRY_POINT = "{}.handlers.test_entrypoint"
4949
CODE_URI = "build/"
50-
DOCKER_TAG = 3.6
50+
DOCKER_TAG = ""
5151

5252
def __init__(self):
5353
self.env = self._setup_jinja_env(
@@ -237,9 +237,8 @@ def _generate_target_models(self, project):
237237
target_name = "".join(
238238
[s.capitalize() for s in target_namespace]
239239
) # awssqsqueue -> AwsSqsQueue
240-
target_model_file = "{}.py".format(
241-
"_".join(target_namespace)
242-
) # awssqsqueue -> aws_sqs_queue.py
240+
target_model_file = f'{"_".join(target_namespace)}.py'
241+
# awssqsqueue -> aws_sqs_queue.py
243242

244243
models = resolve_models(target_schema, target_name)
245244

@@ -425,19 +424,25 @@ def _pip_build(cls, base_path):
425424
LOG.debug("--- pip stderr:\n%s", completed_proc.stderr)
426425

427426

428-
class Python37LanguagePlugin(Python36LanguagePlugin):
429-
NAME = "python37"
430-
RUNTIME = "python3.7"
431-
DOCKER_TAG = 3.7
432-
433-
434-
class Python38LanguagePlugin(Python36LanguagePlugin):
427+
class Python38LanguagePlugin(_PythonLanguagePlugin):
435428
NAME = "python38"
436429
RUNTIME = "python3.8"
437430
DOCKER_TAG = 3.8
438431

439432

440-
class Python39LanguagePlugin(Python36LanguagePlugin):
433+
class Python39LanguagePlugin(_PythonLanguagePlugin):
441434
NAME = "python39"
442435
RUNTIME = "python3.9"
443436
DOCKER_TAG = 3.9
437+
438+
439+
class Python310LanguagePlugin(_PythonLanguagePlugin):
440+
NAME = "python310"
441+
RUNTIME = "python3.10"
442+
DOCKER_TAG = 3.10
443+
444+
445+
class Python311LanguagePlugin(_PythonLanguagePlugin):
446+
NAME = "python311"
447+
RUNTIME = "python3.11"
448+
DOCKER_TAG = 3.11

python/rpdk/python/parser.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ def setup_subparser(subparsers, parents, python_version, python_version_number):
22
parser = subparsers.add_parser(
33
python_version,
44
description=(
5-
"This sub command generates IDE and build files for Python "
6-
"{}".format(python_version_number)
5+
"This sub command generates IDE and build files for "
6+
f"Python {python_version_number}"
77
),
88
parents=parents,
99
)
@@ -30,17 +30,17 @@ def setup_subparser(subparsers, parents, python_version, python_version_number):
3030
return parser
3131

3232

33-
def setup_subparser_python36(subparsers, parents):
34-
return setup_subparser(subparsers, parents, "python36", "3.6")
35-
36-
37-
def setup_subparser_python37(subparsers, parents):
38-
return setup_subparser(subparsers, parents, "python37", "3.7")
39-
40-
4133
def setup_subparser_python38(subparsers, parents):
4234
return setup_subparser(subparsers, parents, "python38", "3.8")
4335

4436

4537
def setup_subparser_python39(subparsers, parents):
4638
return setup_subparser(subparsers, parents, "python39", "3.9")
39+
40+
41+
def setup_subparser_python310(subparsers, parents):
42+
return setup_subparser(subparsers, parents, "python310", "3.10")
43+
44+
45+
def setup_subparser_python311(subparsers, parents):
46+
return setup_subparser(subparsers, parents, "python311", "3.11")

setup.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@ def find_version(*file_paths):
3636
# package_data -> use MANIFEST.in instead
3737
include_package_data=True,
3838
zip_safe=True,
39-
python_requires=">=3.6",
39+
python_requires=">=3.8",
4040
install_requires=["cloudformation-cli>=0.2.26", "types-dataclasses>=0.1.5"],
4141
entry_points={
4242
"rpdk.v1.languages": [
43+
"python311 = rpdk.python.codegen:Python311LanguagePlugin",
44+
"python310 = rpdk.python.codegen:Python310LanguagePlugin",
4345
"python39 = rpdk.python.codegen:Python39LanguagePlugin",
4446
"python38 = rpdk.python.codegen:Python38LanguagePlugin",
45-
"python37 = rpdk.python.codegen:Python37LanguagePlugin",
46-
"python36 = rpdk.python.codegen:Python36LanguagePlugin",
4747
],
4848
"rpdk.v1.parsers": [
49+
"python311 = rpdk.python.parser:setup_subparser_python311",
50+
"python310 = rpdk.python.parser:setup_subparser_python310",
4951
"python39 = rpdk.python.parser:setup_subparser_python39",
5052
"python38 = rpdk.python.parser:setup_subparser_python38",
51-
"python37 = rpdk.python.parser:setup_subparser_python37",
52-
"python36 = rpdk.python.parser:setup_subparser_python36",
5353
],
5454
},
5555
license="Apache License 2.0",
@@ -63,8 +63,10 @@ def find_version(*file_paths):
6363
"Topic :: Software Development :: Code Generators",
6464
"Operating System :: OS Independent",
6565
"Programming Language :: Python :: 3 :: Only",
66-
"Programming Language :: Python :: 3.6",
67-
"Programming Language :: Python :: 3.7",
66+
"Programming Language :: Python :: 3.8",
67+
"Programming Language :: Python :: 3.9",
68+
"Programming Language :: Python :: 3.10",
69+
"Programming Language :: Python :: 3.11",
6870
],
6971
keywords="Amazon Web Services AWS CloudFormation",
7072
)

src/cloudformation_cli_python_lib/hook.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ def _invoke_handler( # pylint: disable=too-many-arguments
9191
handler = self._handlers[invocation_point]
9292
except KeyError:
9393
return ProgressEvent.failed(
94-
HandlerErrorCode.InternalFailure, f"No handler for {invocation_point}"
94+
HandlerErrorCode.InternalFailure,
95+
f"No handler for {invocation_point.name}",
9596
)
9697

9798
return handler(session, request, callback_context, type_configuration)
@@ -257,10 +258,10 @@ def print_or_log(message: str) -> None:
257258
print_or_log("Handler error")
258259
progress = e.to_progress_event()
259260
except Exception as e: # pylint: disable=broad-except
260-
print_or_log("Exception caught {0}".format(e))
261+
print_or_log(f"Exception caught {e}")
261262
progress = ProgressEvent.failed(HandlerErrorCode.InternalFailure)
262263
except BaseException as e: # pylint: disable=broad-except
263-
print_or_log("Base exception caught (this is usually bad) {0}".format(e))
264+
print_or_log(f"Base exception caught (this is usually bad) {e}")
264265
progress = ProgressEvent.failed(HandlerErrorCode.InternalFailure)
265266

266267
# use the raw event_data as a last-ditch attempt to call back if the

src/cloudformation_cli_python_lib/identifier_utils.py

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def generate_resource_identifier(
2020
max_length: int,
2121
) -> str:
2222
if max_length < MIN_PHYSICAL_RESOURCE_ID_LENGTH:
23+
# pylint: disable=broad-exception-raised
2324
raise Exception(
2425
f"Cannot generate resource IDs shorter than\
2526
{MIN_PHYSICAL_RESOURCE_ID_LENGTH} characters."

src/cloudformation_cli_python_lib/interface.py

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
class _AutoName(Enum):
1212
@staticmethod
13+
# pylint: disable=arguments-differ
1314
def _generate_next_value_(
1415
name: str, _start: int, _count: int, _last_values: List[str]
1516
) -> str:

src/cloudformation_cli_python_lib/metrics.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def __init__(self, session: SessionProxy, hook_type: str, account_id: str) -> No
140140
self._account_id = account_id
141141
self._namespace = self._make_hook_namespace(hook_type, account_id)
142142

143-
# pylint: disable=arguments-differ
143+
# pylint: disable=arguments-differ,arguments-renamed
144144
def publish_exception_metric( # type: ignore
145145
self,
146146
timestamp: datetime.datetime,

src/cloudformation_cli_python_lib/recast.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def _field_to_type(field: Any, key: str, classes: Dict[str, Any]) -> Any: # noq
129129
# Assuming that the union is generated from typing.Optional, so only
130130
# contains one type and None
131131
# pylint: disable=unidiomatic-typecheck
132-
fields = [t for t in possible_types if type(None) != t]
132+
fields = [t for t in possible_types if type(None) is not t]
133133
if len(fields) != 1:
134134
raise InvalidRequest(f"Cannot process type {field} for field {key}")
135135
field = fields[0]

src/cloudformation_cli_python_lib/resource.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def _invoke_handler(
8989
handler = self._handlers[action]
9090
except KeyError:
9191
return ProgressEvent.failed(
92-
HandlerErrorCode.InternalFailure, f"No handler for {action}"
92+
HandlerErrorCode.InternalFailure, f"No handler for {action.name}"
9393
)
9494
progress = handler(session, request, callback_context)
9595
is_in_progress = progress.status == OperationStatus.IN_PROGRESS
@@ -227,10 +227,10 @@ def print_or_log(message: str) -> None:
227227
print_or_log("Handler error")
228228
progress = e.to_progress_event()
229229
except Exception as e: # pylint: disable=broad-except
230-
print_or_log("Exception caught {0}".format(e))
230+
print_or_log(f"Exception caught {e}")
231231
progress = ProgressEvent.failed(HandlerErrorCode.InternalFailure)
232232
except BaseException as e: # pylint: disable=broad-except
233-
print_or_log("Base exception caught (this is usually bad) {0}".format(e))
233+
print_or_log(f"Base exception caught (this is usually bad) {e}")
234234
progress = ProgressEvent.failed(HandlerErrorCode.InternalFailure)
235235

236236
if progress.result: # pragma: no cover

src/setup.py

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
"Programming Language :: Python :: 3 :: Only",
3030
"Programming Language :: Python :: 3.6",
3131
"Programming Language :: Python :: 3.7",
32+
"Programming Language :: Python :: 3.8",
33+
"Programming Language :: Python :: 3.9",
34+
"Programming Language :: Python :: 3.10",
35+
"Programming Language :: Python :: 3.11",
3236
],
3337
keywords="Amazon Web Services AWS CloudFormation",
3438
)

tests/lib/metrics_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,4 @@ def test_metrics_publisher_proxy_add_metrics_publisher_none_safe():
382382
proxy = MetricsPublisherProxy()
383383
proxy.add_metrics_publisher(None, None)
384384
proxy.add_hook_metrics_publisher(None, None, None)
385-
assert proxy._publishers == [] # pylint: disable=protected-access
385+
assert not proxy._publishers # pylint: disable=protected-access

tests/lib/utils_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def test_hook_handler_request_serde_roundtrip():
141141
else json.loads(v)
142142
if k.endswith("Credentials")
143143
else v
144-
for k, v in payload[k].items()
144+
for k, v in v.items()
145145
if v is not None and k not in undesired
146146
}
147147
if k in ("requestData", "requestContext")

tests/plugin/codegen_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from rpdk.python.codegen import (
1414
SUPPORT_LIB_NAME,
1515
SUPPORT_LIB_PKG,
16-
Python36LanguagePlugin as PythonLanguagePlugin,
16+
_PythonLanguagePlugin as PythonLanguagePlugin,
1717
validate_no,
1818
)
1919
from shutil import copyfile

0 commit comments

Comments
 (0)