Skip to content

Commit

Permalink
feat(lambda-python): support poetry packaging for PythonFunction (aws…
Browse files Browse the repository at this point in the history
…#11850)

This PR adds [poetry](https://python-poetry.org/) support to building Lambda dependencies for the PythonFunction.

I used the pipenv setup for inspiration. I'm not very familiar with writing integration tests, so there's a possibility that I could've missed something.

Closes aws#11753.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
setu4993 authored and flochaz committed Jan 5, 2021
1 parent f7261fd commit 8bcc34a
Show file tree
Hide file tree
Showing 9 changed files with 540 additions and 6 deletions.
16 changes: 13 additions & 3 deletions packages/@aws-cdk/aws-lambda-python/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Amazon Lambda Python Library

<!--BEGIN STABILITY BANNER-->

---
Expand All @@ -25,13 +26,13 @@ Define a `PythonFunction`:

```ts
import * as lambda from "@aws-cdk/aws-lambda";
import { PythonFunction } from "@aws-cdk/aws-lambda-python"
import { PythonFunction } from "@aws-cdk/aws-lambda-python";

new PythonFunction(this, 'MyFunction', {
entry: '/path/to/my/function', // required
index: 'my_index.py', // optional, defaults to 'index.py'
handler: 'my_exported_func', // optional, defaults to 'handler'
runtime: lambda.Runtime.PYTHON_3_6 // optional, defaults to lambda.Runtime.PYTHON_3_7
runtime: lambda.Runtime.PYTHON_3_6, // optional, defaults to lambda.Runtime.PYTHON_3_7
});
```

Expand Down Expand Up @@ -60,10 +61,19 @@ according to the `runtime`.
├── Pipfile.lock # your lock file
```

**Lambda with a poetry.lock**

```plaintext
.
├── lambda_function.py # exports a function named 'handler'
├── pyproject.toml # has to be present at the entry path
├── poetry.lock # your poetry lock file
```

**Lambda Layer Support**

You may create a python-based lambda layer with `PythonLayerVersion`. If `PythonLayerVersion` detects a `requirements.txt`
or `Pipfile` at the entry path, then `PythonLayerVersion` will include the dependencies inline with your code in the
or `Pipfile` or `poetry.lock` with the associated `pyproject.toml` at the entry path, then `PythonLayerVersion` will include the dependencies inline with your code in the
layer.

```ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ FROM $IMAGE
# Ensure rsync is installed
RUN yum -q list installed rsync &>/dev/null || yum install -y rsync

# Install pipenv so we can create a requirements.txt if we detect pipfile
RUN pip install pipenv
# Install pipenv and poetry so we can create a requirements.txt if we detect pipfile or poetry.lock respectively
RUN pip install pipenv poetry

# Install the dependencies in a cacheable layer
WORKDIR /var/dependencies
COPY Pipfile* requirements.tx[t] ./
COPY Pipfile* pyproject* poetry* requirements.tx[t] ./
RUN [ -f 'Pipfile' ] && pipenv lock -r >requirements.txt; \
[ -f 'poetry.lock' ] && poetry export --with-credentials --format requirements.txt --output requirements.txt; \
[ -f 'requirements.txt' ] && pip install -r requirements.txt -t .;

CMD [ "python" ]
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-lambda-python/lib/bundling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export function hasDependencies(entry: string): boolean {
return true;
}

if (fs.existsSync(path.join(entry, 'poetry.lock'))) {
return true;
}

if (fs.existsSync(path.join(entry, 'requirements.txt'))) {
return true;
}
Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ describe('Dependency detection', () => {
expect(hasDependencies('/asset-input')).toEqual(true);
});

test('Detects poetry', () => {
existsSyncMock.mockImplementation((p: fs.PathLike) => {
if (/poetry.lock/.test(p.toString())) {
return true;
}
return existsSyncOriginal(p);
});

expect(hasDependencies('/asset-input')).toEqual(true);
});

test('Detects requirements.txt', () => {
existsSyncMock.mockImplementation((p: fs.PathLike) => {
if (/requirements.txt/.test(p.toString())) {
Expand Down
Loading

0 comments on commit 8bcc34a

Please sign in to comment.