Skip to content

Commit 997dbcc

Browse files
authored
feat: Add python support to cdk init (#2130)
* First take on an init template for a Python CDK project. * The cdk.context.json should not be ignored. * Fixing some review issues * Restructured to move app into a separate file outside of package directory. Also some formatting changes. * Slight change to code formatting. * Remove reference to app.sh * Moving this over to sample-app since it actually creates a sample app, not an empty project. Will need to create a separate issue to move the others over and create templates for empty projects. * Adding an app template for Python. * Keep all dependencies in setup.py and use -e . in requirements.txt to use those and automatically run the python setup.py develop step. Also use templating feature for blank app. * Templatize the class name.
1 parent 2e92d44 commit 997dbcc

21 files changed

+312
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from aws_cdk import cdk
2+
3+
4+
class %name.PascalCased%Stack(cdk.Stack):
5+
6+
def __init__(self, app: cdk.App, id: str, **kwargs) -> None:
7+
super().__init__(app, id)
8+
9+
# The code that defines your stack goes here

packages/aws-cdk/lib/init-templates/app/python/%name%/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.swp
2+
package-lock.json
3+
__pycache__
4+
.pytest_cache
5+
.env
6+
*.egg-info
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
# Welcome to your CDK Python project!
3+
4+
This is a blank project for Python development with CDK.
5+
6+
The `cdk.json` file tells the CDK Toolkit how to execute your app.
7+
8+
This project is set up like a standard Python project. The initialization process also creates
9+
a virtualenv within this project, stored under the .env directory.
10+
11+
After the init process completes, you can use the following steps to get your project set up.
12+
13+
```
14+
$ source .env/bin/activate
15+
$ pip install -r requirements.txt
16+
$ python setup.py develop
17+
```
18+
19+
At this point you can now synthesize the CloudFormation template for this code.
20+
21+
```
22+
$ cdk synth
23+
```
24+
25+
To add additional dependencies, for example other CDK libraries, just add to
26+
your requirements.txt file and rerun the `pip install -r requirements.txt`
27+
command.
28+
29+
# Useful commands
30+
31+
* `cdk ls` list all stacks in the app
32+
* `cdk synth` emits the synthesized CloudFormation template
33+
* `cdk deploy` deploy this stack to your default AWS account/region
34+
* `cdk diff` compare deployed stack with current state
35+
* `cdk docs` open CDK documentation
36+
37+
Enjoy!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env python3
2+
3+
from aws_cdk import cdk
4+
5+
from %name%.%name%_stack import PyStack
6+
7+
8+
app = cdk.App()
9+
PyStack(app, "%name%-cdk-1")
10+
11+
app.run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"app": "python3 app.py"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-e .
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import setuptools
2+
3+
4+
with open("README.md") as fp:
5+
long_description = fp.read()
6+
7+
8+
setuptools.setup(
9+
name="%name%",
10+
version="0.0.1",
11+
12+
description="An empty CDK Python app",
13+
long_description=long_description,
14+
long_description_content_type="text/markdown",
15+
16+
author="author",
17+
18+
package_dir={"": "%name%"},
19+
packages=setuptools.find_packages(where="%name%"),
20+
21+
install_requires=[
22+
"aws-cdk.cdk",
23+
],
24+
25+
python_requires=">=3.6",
26+
27+
classifiers=[
28+
"Development Status :: 4 - Beta",
29+
30+
"Intended Audience :: Developers",
31+
32+
"License :: OSI Approved :: Apache Software License",
33+
34+
"Programming Language :: JavaScript",
35+
"Programming Language :: Python :: 3 :: Only",
36+
"Programming Language :: Python :: 3.6",
37+
"Programming Language :: Python :: 3.7",
38+
"Programming Language :: Python :: 3.8",
39+
40+
"Topic :: Software Development :: Code Generators",
41+
"Topic :: Utilities",
42+
43+
"Typing :: Typed",
44+
],
45+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.swp
2+
package-lock.json
3+
__pycache__
4+
.pytest_cache
5+
.env
6+
*.egg-info
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
# Welcome to your CDK Python project!
3+
4+
You should explore the contents of this template. It demonstrates a CDK app with two instances of
5+
a stack (`HelloStack`) which also uses a user-defined construct (`HelloConstruct`).
6+
7+
The `cdk.json` file tells the CDK Toolkit how to execute your app.
8+
9+
This project is set up like a standard Python project. The initialization process also creates
10+
a virtualenv within this project, stored under the .env directory.
11+
12+
After the init process completes, you can use the following steps to get your project set up.
13+
14+
```
15+
$ source .env/bin/activate
16+
$ pip install -r requirements.txt
17+
```
18+
19+
At this point you can now synthesize the CloudFormation template for this code.
20+
21+
```
22+
$ cdk synth
23+
```
24+
25+
You can now begin exploring the source code, contained in the hello directory.
26+
There is also a very trivial test included that can be run like this:
27+
28+
```
29+
$ pytest
30+
```
31+
32+
To add additional dependencies, for example other CDK libraries, just add to
33+
your requirements.txt file and rerun the `pip install -r requirements.txt`
34+
command.
35+
36+
# Useful commands
37+
38+
* `cdk ls` list all stacks in the app
39+
* `cdk synth` emits the synthesized CloudFormation template
40+
* `cdk deploy` deploy this stack to your default AWS account/region
41+
* `cdk diff` compare deployed stack with current state
42+
* `cdk docs` open CDK documentation
43+
44+
Enjoy!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env python3
2+
3+
from aws_cdk import cdk
4+
5+
from hello.hello_stack import MyStack
6+
7+
8+
app = cdk.App()
9+
MyStack(app, "hello-cdk-1", env={'region': 'us-east-2'})
10+
MyStack(app, "hello-cdk-2", env={'region': 'us-west-2'})
11+
12+
app.run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"app": "python3 app.py"
3+
}

packages/aws-cdk/lib/init-templates/sample-app/python/hello/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from aws_cdk import (
2+
aws_iam as iam,
3+
aws_s3 as s3,
4+
cdk,
5+
)
6+
7+
8+
class HelloConstruct(cdk.Construct):
9+
10+
@property
11+
def buckets(self):
12+
return tuple(self._buckets)
13+
14+
def __init__(self, scope: cdk.Construct, id: str, num_buckets: int) -> None:
15+
super().__init__(scope, id)
16+
self._buckets = []
17+
for i in range(0, num_buckets):
18+
self._buckets.append(s3.Bucket(self, f"Bucket-{i}"))
19+
20+
def grant_read(self, principal: iam.IPrincipal):
21+
for b in self.buckets:
22+
b.grant_read(principal, "*")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from aws_cdk import (
2+
aws_iam as iam,
3+
aws_sqs as sqs,
4+
aws_sns as sns,
5+
cdk
6+
)
7+
8+
from hello_construct import HelloConstruct
9+
10+
11+
class MyStack(cdk.Stack):
12+
13+
def __init__(self, app: cdk.App, id: str, **kwargs) -> None:
14+
super().__init__(app, id, **kwargs)
15+
16+
queue = sqs.Queue(
17+
self, "MyFirstQueue",
18+
visibility_timeout_sec=300,
19+
)
20+
21+
topic = sns.Topic(
22+
self, "MyFirstTopic",
23+
display_name="My First Topic"
24+
)
25+
26+
topic.subscribe_queue(queue)
27+
28+
hello = HelloConstruct(self, "MyHelloConstruct", num_buckets=4)
29+
user = iam.User(self, "MyUser")
30+
hello.grant_read(user)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-e .
2+
pytest
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import setuptools
2+
3+
4+
with open("README.md") as fp:
5+
long_description = fp.read()
6+
7+
8+
setuptools.setup(
9+
name="hello",
10+
version="0.0.1",
11+
12+
description="A sample CDK Python app",
13+
long_description=long_description,
14+
long_description_content_type="text/markdown",
15+
16+
author="author",
17+
18+
package_dir={"": "hello"},
19+
packages=setuptools.find_packages(where="hello"),
20+
21+
install_requires=[
22+
"aws-cdk.cdk",
23+
"aws-cdk.aws_iam",
24+
"aws-cdk.aws_sqs",
25+
"aws-cdk.aws_sns",
26+
"aws-cdk.aws_s3",
27+
],
28+
29+
python_requires=">=3.6",
30+
31+
classifiers=[
32+
"Development Status :: 4 - Beta",
33+
34+
"Intended Audience :: Developers",
35+
36+
"License :: OSI Approved :: Apache Software License",
37+
38+
"Programming Language :: JavaScript",
39+
"Programming Language :: Python :: 3 :: Only",
40+
"Programming Language :: Python :: 3.6",
41+
"Programming Language :: Python :: 3.7",
42+
"Programming Language :: Python :: 3.8",
43+
44+
"Topic :: Software Development :: Code Generators",
45+
"Topic :: Utilities",
46+
47+
"Typing :: Typed",
48+
],
49+
)

packages/aws-cdk/lib/init-templates/sample-app/python/tests/__init__.py

Whitespace-only changes.

packages/aws-cdk/lib/init-templates/sample-app/python/tests/unit/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import unittest
2+
3+
from aws_cdk import cdk
4+
5+
from hello.hello_construct import HelloConstruct
6+
7+
class TestHelloConstruct(unittest.TestCase):
8+
9+
def setUp(self):
10+
self.app = cdk.App()
11+
self.stack = cdk.Stack(self.app, "TestStack")
12+
13+
def test_num_buckets(self):
14+
num_buckets = 10
15+
hello = HelloConstruct(self.stack, "Test1", num_buckets)
16+
assert len(hello.buckets) == num_buckets

packages/aws-cdk/lib/init.ts

+16
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ async function postInstall(language: string, canUseNetwork: boolean) {
231231
return await postInstallTypescript(canUseNetwork);
232232
case 'java':
233233
return await postInstallJava(canUseNetwork);
234+
case 'python':
235+
return await postInstallPython(canUseNetwork);
234236
}
235237
}
236238

@@ -260,6 +262,20 @@ async function postInstallJava(canUseNetwork: boolean) {
260262
await execute('mvn', 'package');
261263
}
262264

265+
async function postInstallPython(canUseNetwork: boolean) {
266+
if (!canUseNetwork) {
267+
print(`Please run ${colors.green('python -m venv .env')}!`);
268+
return;
269+
}
270+
271+
print(`Executing ${colors.green('python -m venv .env')}`);
272+
try {
273+
await execute('python3', '-m venv', '.env');
274+
} catch (e) {
275+
throw new Error(`${colors.green('python3 -m venv .env')} failed: ` + e.message);
276+
}
277+
}
278+
263279
/**
264280
* @param dir a directory to be checked
265281
* @returns true if ``dir`` is within a git repository.

0 commit comments

Comments
 (0)