Skip to content

Commit

Permalink
Add support for specifying custom dependency groups in Poetry
Browse files Browse the repository at this point in the history
  • Loading branch information
mLupine committed Nov 30, 2022
1 parent 762ca3e commit e719337
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ custom:
requirePoetryLockFile: false
```

If your Poetry configuration includes custom dependency groups, they will not be installed automatically. To include them in the deployment package, use the `poetryWithGroups`, `poetryWithoutGroups` and `poetryOnlyGroups` options which wrap `poetry export`'s `--with`, `--without` and `--only` parameters.

```yaml
custom:
pythonRequirements:
poetryWithGroups:
- internal_dependencies
- lambda_dependencies
```

### Poetry with git dependencies

Poetry by default generates the exported requirements.txt file with `-e` and that breaks pip with `-t` parameter
Expand Down
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class ServerlessPythonRequirements {
noDeploy: [],
vendor: '',
requirePoetryLockFile: false,
poetryWithGroups: [],
poetryWithoutGroups: [],
poetryOnlyGroups: [],
},
(this.serverless.service.custom &&
this.serverless.service.custom.pythonRequirements) ||
Expand Down
9 changes: 9 additions & 0 deletions lib/poetry.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ async function pyprojectTomlToRequirements(modulePath, pluginInstance) {
'-o',
'requirements.txt',
'--with-credentials',
...(options.poetryWithGroups.length
? [`--with=${options.poetryWithGroups.join(',')}`]
: []),
...(options.poetryWithoutGroups.length
? [`--without=${options.poetryWithoutGroups.join(',')}`]
: []),
...(options.poetryOnlyGroups.length
? [`--only=${options.poetryOnlyGroups.join(',')}`]
: []),
],
{
cwd: moduleProjectPath,
Expand Down
49 changes: 49 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1654,3 +1654,52 @@ test('poetry py3.7 fails packaging if poetry.lock is missing and flag requirePoe
);
t.end();
});

test('poetry py3.7 packages additional optional packages', async (t) => {
process.chdir('tests/poetry_packages');
const path = npm(['pack', '../..']);
npm(['i', path]);
sls(['package'], {
env: {
poetryWithGroups: 'poetryWithGroups',
},
});
const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip');
t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged');
t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged');
t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged');
t.end();
});

test('poetry py3.7 skips additional optional packages specified in withoutGroups', async (t) => {
process.chdir('tests/poetry_packages');
const path = npm(['pack', '../..']);
npm(['i', path]);
sls(['package'], {
env: {
poetryWithGroups: 'poetryWithGroups',
poetryWithoutGroups: 'poetryWithoutGroups',
},
});
const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip');
t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged');
t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged');
t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged');
t.end();
});

test('poetry py3.7 only installs optional packages specified in onlyGroups', async (t) => {
process.chdir('tests/poetry_packages');
const path = npm(['pack', '../..']);
npm(['i', path]);
sls(['package'], {
env: {
poetryOnlyGroups: 'poetryOnlyGroups',
},
});
const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip');
t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged');
t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged');
t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged');
t.end();
});
8 changes: 8 additions & 0 deletions tests/poetry_packages/_poetryGroups.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
empty: []
poetryWithGroups:
- custom1
- custom2
poetryWithoutGroups:
- custom1
poetryOnlyGroups:
- custom2
2 changes: 2 additions & 0 deletions tests/poetry_packages/_slimPatterns.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
slimPatterns:
- '**/__main__.py'
5 changes: 5 additions & 0 deletions tests/poetry_packages/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import requests


def hello(event, context):
return requests.get('https://httpbin.org/get').json()
14 changes: 14 additions & 0 deletions tests/poetry_packages/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"serverless-python-requirements": "file:serverless-python-requirements-6.0.0.tgz"
}
}
19 changes: 19 additions & 0 deletions tests/poetry_packages/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[tool.poetry]
name = "poetry"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.6"
Flask = "^1.0"

[tool.poetry.group.custom1.dependencies]
bottle = {git = "https://[email protected]/bottlepy/bottle.git", tag = "0.12.16"}

[tool.poetry.group.custom2.dependencies]
boto3 = "^1.9"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
34 changes: 34 additions & 0 deletions tests/poetry_packages/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
service: sls-py-req-test

provider:
name: aws
runtime: python3.7

plugins:
- serverless-python-requirements
custom:
pythonRequirements:
zip: ${env:zip, self:custom.defaults.zip}
slim: ${env:slim, self:custom.defaults.slim}
slimPatterns: ${file(./slimPatterns.yml):slimPatterns, self:custom.defaults.slimPatterns}
slimPatternsAppendDefaults: ${env:slimPatternsAppendDefaults, self:custom.defaults.slimPatternsAppendDefaults}
dockerizePip: ${env:dockerizePip, self:custom.defaults.dockerizePip}
requirePoetryLockFile: ${env:requirePoetryLockFile, false}
poetryWithGroups: ${file(./_poetryGroups.yml):${env:poetryWithGroups, "empty"}}
poetryWithoutGroups: ${file(./_poetryGroups.yml):${env:poetryWithoutGroups, "empty"}}
poetryOnlyGroups: ${file(./_poetryGroups.yml):${env:poetryOnlyGroups, "empty"}}
defaults:
zip: false
slimPatterns: false
slimPatternsAppendDefaults: true
slim: false
dockerizePip: false

package:
patterns:
- '!**/*'
- 'handler.py'

functions:
hello:
handler: handler.hello

0 comments on commit e719337

Please sign in to comment.