Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add python support to cdk init #2130

Merged
merged 11 commits into from
Apr 2, 2019
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from aws_cdk import cdk


class PyStack(cdk.Stack):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to template this guy too.... Sorry


def __init__(self, app: cdk.App, id: str, **kwargs) -> None:
super().__init__(app, id)

# The code that defines your stack goes here
Empty file.
6 changes: 6 additions & 0 deletions packages/aws-cdk/lib/init-templates/app/python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.swp
package-lock.json
__pycache__
.pytest_cache
.env
*.egg-info
37 changes: 37 additions & 0 deletions packages/aws-cdk/lib/init-templates/app/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

# Welcome to your CDK Python project!

This is a blank project for Python development with CDK.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

This project is set up like a standard Python project. The initialization process also creates
a virtualenv within this project, stored under the .env directory.

After the init process completes, you can use the following steps to get your project set up.

```
$ source .env/bin/activate
$ pip install -r requirements.txt
$ python setup.py develop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't develop for libraries (as opposed to apps)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

develop is just a variant of install that allows you to edit your code and run it without having to re-install. This example really consists of both an app and a library. I have restructured the code slightly to make that more clear, I hope.

```

At this point you can now synthesize the CloudFormation template for this code.

```
$ cdk synth
```

To add additional dependencies, for example other CDK libraries, just add to
your requirements.txt file and rerun the `pip install -r requirements.txt`
command.

garnaat marked this conversation as resolved.
Show resolved Hide resolved
# Useful commands

* `cdk ls` list all stacks in the app
* `cdk synth` emits the synthesized CloudFormation template
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk docs` open CDK documentation

Enjoy!
11 changes: 11 additions & 0 deletions packages/aws-cdk/lib/init-templates/app/python/app.template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env python3

from aws_cdk import cdk

from %name%.%name%_stack import PyStack


app = cdk.App()
PyStack(app, "%name%-cdk-1")

app.run()
3 changes: 3 additions & 0 deletions packages/aws-cdk/lib/init-templates/app/python/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "python3 app.py"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-e .
45 changes: 45 additions & 0 deletions packages/aws-cdk/lib/init-templates/app/python/setup.template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import setuptools


with open("README.md") as fp:
long_description = fp.read()


setuptools.setup(
name="%name%",
version="0.0.1",

description="An empty CDK Python app",
long_description=long_description,
long_description_content_type="text/markdown",

author="author",

package_dir={"": "%name%"},
packages=setuptools.find_packages(where="%name%"),

install_requires=[
"aws-cdk.cdk",
],

python_requires=">=3.6",

classifiers=[
"Development Status :: 4 - Beta",

"Intended Audience :: Developers",

"License :: OSI Approved :: Apache Software License",

"Programming Language :: JavaScript",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",

"Topic :: Software Development :: Code Generators",
"Topic :: Utilities",

"Typing :: Typed",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.swp
package-lock.json
__pycache__
.pytest_cache
.env
*.egg-info
44 changes: 44 additions & 0 deletions packages/aws-cdk/lib/init-templates/sample-app/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

# Welcome to your CDK Python project!

You should explore the contents of this template. It demonstrates a CDK app with two instances of
a stack (`HelloStack`) which also uses a user-defined construct (`HelloConstruct`).

The `cdk.json` file tells the CDK Toolkit how to execute your app.

This project is set up like a standard Python project. The initialization process also creates
a virtualenv within this project, stored under the .env directory.

After the init process completes, you can use the following steps to get your project set up.

```
$ source .env/bin/activate
$ pip install -r requirements.txt
```

At this point you can now synthesize the CloudFormation template for this code.

```
$ cdk synth
```

You can now begin exploring the source code, contained in the hello directory.
There is also a very trivial test included that can be run like this:

```
$ pytest
```

To add additional dependencies, for example other CDK libraries, just add to
your requirements.txt file and rerun the `pip install -r requirements.txt`
command.

# Useful commands

* `cdk ls` list all stacks in the app
* `cdk synth` emits the synthesized CloudFormation template
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk docs` open CDK documentation

Enjoy!
12 changes: 12 additions & 0 deletions packages/aws-cdk/lib/init-templates/sample-app/python/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3

from aws_cdk import cdk

from hello.hello_stack import MyStack


app = cdk.App()
MyStack(app, "hello-cdk-1", env={'region': 'us-east-2'})
MyStack(app, "hello-cdk-2", env={'region': 'us-west-2'})

app.run()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "python3 app.py"
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from aws_cdk import (
aws_iam as iam,
aws_s3 as s3,
cdk,
)


class HelloConstruct(cdk.Construct):

@property
def buckets(self):
return tuple(self._buckets)

def __init__(self, scope: cdk.Construct, id: str, num_buckets: int) -> None:
super().__init__(scope, id)
self._buckets = []
for i in range(0, num_buckets):
self._buckets.append(s3.Bucket(self, f"Bucket-{i}"))

def grant_read(self, principal: iam.IPrincipal):
for b in self.buckets:
b.grant_read(principal, "*")
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from aws_cdk import (
aws_iam as iam,
aws_sqs as sqs,
aws_sns as sns,
cdk
)

from hello_construct import HelloConstruct


class MyStack(cdk.Stack):

def __init__(self, app: cdk.App, id: str, **kwargs) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch

super().__init__(app, id, **kwargs)

queue = sqs.Queue(
self, "MyFirstQueue",
visibility_timeout_sec=300,
)

topic = sns.Topic(
self, "MyFirstTopic",
display_name="My First Topic"
)

topic.subscribe_queue(queue)

hello = HelloConstruct(self, "MyHelloConstruct", num_buckets=4)
user = iam.User(self, "MyUser")
hello.grant_read(user)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-e .
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oooo magic

pytest
49 changes: 49 additions & 0 deletions packages/aws-cdk/lib/init-templates/sample-app/python/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import setuptools


with open("README.md") as fp:
long_description = fp.read()


setuptools.setup(
name="hello",
version="0.0.1",

description="A sample CDK Python app",
long_description=long_description,
long_description_content_type="text/markdown",

author="author",

package_dir={"": "hello"},
packages=setuptools.find_packages(where="hello"),

install_requires=[
"aws-cdk.cdk",
"aws-cdk.aws_iam",
"aws-cdk.aws_sqs",
"aws-cdk.aws_sns",
"aws-cdk.aws_s3",
],

python_requires=">=3.6",

classifiers=[
"Development Status :: 4 - Beta",

"Intended Audience :: Developers",

"License :: OSI Approved :: Apache Software License",

"Programming Language :: JavaScript",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",

"Topic :: Software Development :: Code Generators",
"Topic :: Utilities",

"Typing :: Typed",
],
)
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import unittest

from aws_cdk import cdk

from hello.hello_construct import HelloConstruct

class TestHelloConstruct(unittest.TestCase):

def setUp(self):
self.app = cdk.App()
self.stack = cdk.Stack(self.app, "TestStack")

def test_num_buckets(self):
num_buckets = 10
hello = HelloConstruct(self.stack, "Test1", num_buckets)
assert len(hello.buckets) == num_buckets
16 changes: 16 additions & 0 deletions packages/aws-cdk/lib/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ async function postInstall(language: string, canUseNetwork: boolean) {
return await postInstallTypescript(canUseNetwork);
case 'java':
return await postInstallJava(canUseNetwork);
case 'python':
return await postInstallPython(canUseNetwork);
}
}

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

async function postInstallPython(canUseNetwork: boolean) {
if (!canUseNetwork) {
print(`Please run ${colors.green('python -m venv .env')}!`);
return;
}

print(`Executing ${colors.green('python -m venv .env')}`);
try {
await execute('python3', '-m venv', '.env');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to also do the pip install stuff here so people can get started quicker?

} catch (e) {
throw new Error(`${colors.green('python3 -m venv .env')} failed: ` + e.message);
}
}

/**
* @param dir a directory to be checked
* @returns true if ``dir`` is within a git repository.
Expand Down