Skip to content

Commit f7938bb

Browse files
committed
test: add workspaces test
1 parent bc412db commit f7938bb

File tree

17 files changed

+854
-470
lines changed

17 files changed

+854
-470
lines changed

.projenrc.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ const project = new awscdk.AwsCdkConstructLibrary({
66
constructsVersion: '10.3.0',
77
defaultReleaseBranch: 'main',
88
jsiiVersion: '~5.5.0',
9-
name: 'ft-python-lambda',
9+
name: 'uv-python-lambda',
1010
projenrcTs: true,
11-
repositoryUrl: 'git@github.com:fourtheorem/ft-python-lambda.git',
11+
repositoryUrl: 'git@github.com:fourtheorem/uv-python-lambda.git',
1212
publishToPypi: {
13-
distName: 'fourtheorem.ft-python-lambda',
14-
module: 'fourtheorem.ft_python_lambda',
13+
distName: 'fourtheorem.uv-python-lambda',
14+
module: 'fourtheorem.uv_python_lambda',
1515
},
1616
// cdkVersion: '2.1.0', /* CDK version to use. */
1717
// cdkDependencies: [], /* CDK dependencies of this module. */

API.md

Lines changed: 450 additions & 450 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,47 @@
1-
# replace this
1+
# uv-python-lambda
22

3+
CDK Construct for Python Lambda Functions using [uv](https://docs.astral.sh/uv/)
34

4-
```
5-
error: failed to create directory `/.local/share/uv/python`
6-
```
7-
ensure uv.lock exists
5+
## Goals
6+
7+
- ⚡️ Package and deploy Lambda Functions faster with `uv`'s speed
8+
- 📦 Support workspaces in a monorepo with [uv workspaces](https://docs.astral.sh/uv/concepts/workspaces/)
9+
10+
## API
11+
12+
See [API.md](API.md)
13+
14+
## Example
15+
16+
```python
17+
from fourtheorem.uv_python_lambda import PythonFunction
18+
from constructs import Construct
19+
20+
# The root path should be relative to your CDK source file
21+
root_path = Path(__file__).parent.parent.parent
22+
23+
24+
class CdkStack(Stack):
25+
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
26+
super().__init__(scope, construct_id, **kwargs)
27+
28+
fn = PythonFunction(
29+
self,
30+
"fn",
31+
root_dir=str(root_path),
32+
index="fetcher_lambda.py",
33+
workspace_package="fetcher", # Use a workspace package as the top-level Lambda entry point.
34+
handler="handle_event",
35+
bundling={
36+
"asset_excludes": [
37+
".venv/",
38+
"node_modules/",
39+
"cdk/",
40+
".git/",
41+
".idea/",
42+
"dist/",
43+
]
44+
},
45+
timeout=Duration.seconds(30),
46+
)
47+
```

package.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/function.test.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { PythonFunction } from '../src';
88
const resourcesPath = path.resolve(__dirname, 'resources');
99

1010

11-
test('Create a function', async () => {
11+
test('Create a function from basic_app', async () => {
1212
const app = new App({});
1313
const stack = new Stack(app, 'test');
1414
new PythonFunction(stack, 'basic_app', {
@@ -30,11 +30,54 @@ test('Create a function', async () => {
3030
},
3131
});
3232
const functions = Object.values(template.findResources('AWS::Lambda::Function'));
33-
expect(functions.length).toBe(1);
34-
expect(functions[0].Properties.Handler).toBe('handler.lambda_handler');
35-
expect(functions[0].Properties.Runtime).toBe('python3.12');
36-
const [assetHash] = functions[0].Properties.Code.S3Key.split('.');
37-
const assetPath = path.join(app.outdir, `asset.${assetHash}`);
38-
const contents = await fs.readdir(assetPath);
33+
expect(functions).toHaveLength(1);
34+
const contents = await getFunctionAssetContents(functions[0], app);
3935
expect(contents).toContain('handler.py');
4036
});
37+
38+
test('Create a function with workspaces_app', async () => {
39+
const app = new App({});
40+
const stack = new Stack(app, 'wstest');
41+
new PythonFunction(stack, 'workspaces_app', {
42+
rootDir: path.join(resourcesPath, 'workspaces_app'),
43+
workspacePackage: 'app',
44+
index: 'app_handler.py',
45+
handler: 'handle_event',
46+
runtime: Runtime.PYTHON_3_10,
47+
});
48+
49+
const template = Template.fromStack(stack);
50+
console.log(JSON.stringify(template.toJSON(), null, ' '));
51+
52+
template.hasResourceProperties('AWS::Lambda::Function', {
53+
Handler: 'app_handler.handle_event',
54+
Runtime: 'python3.10',
55+
Code: {
56+
S3Bucket: Match.anyValue(),
57+
S3Key: Match.anyValue(),
58+
},
59+
});
60+
61+
const functions = Object.values(template.findResources('AWS::Lambda::Function'));
62+
expect(functions).toHaveLength(1);
63+
const contents = await getFunctionAssetContents(functions[0], app);
64+
for (const entry of [
65+
'app',
66+
'common',
67+
'pydantic',
68+
'httpx',
69+
'_common.pth',
70+
'app_handler.py',
71+
]) {
72+
expect(contents).toContain(entry);
73+
}
74+
});
75+
76+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
77+
async function getFunctionAssetContents(functionResource: any, app: App) {
78+
const [assetHash] = functionResource.Properties.Code.S3Key.split('.');
79+
const assetPath = path.join(app.outdir, `asset.${assetHash}`);
80+
const contents = await fs.readdir(assetPath);
81+
return contents;
82+
}
83+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.10

test/resources/workspaces_app/README.md

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.10

test/resources/workspaces_app/app/README.md

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from pydantic import BaseModel
2+
3+
class Car(BaseModel):
4+
brand: str
5+
model: str
6+
year: int
7+
8+
def handle_event(event, context):
9+
car = Car(brand="Toyota", model="Corolla", year=2020)
10+
return car.model_dump()

0 commit comments

Comments
 (0)