-
Notifications
You must be signed in to change notification settings - Fork 293
feat: Support individual packaging with poetry
#682
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
Changes from 6 commits
9d9c7fd
47d629a
494f517
a714e63
f969854
b6845ae
3b7a5d1
ac34f96
560ded5
79d1c84
940b039
3b102f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,7 +59,7 @@ dist/ | |
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
# lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -198,9 +198,11 @@ class ServerlessPythonRequirements { | |
if (!isFunctionRuntimePython(arguments)) { | ||
return; | ||
} | ||
const _pyprojectTomlToRequirements = () => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a quite weird pattern to me - could you explain the reasoning behind adding logic like that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Briefly, because I needed to reuse the The functions used in this block:
are implemented to use the I opted to convert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for clarification - instead of adding this temp var |
||
pyprojectTomlToRequirements('', this); | ||
return BbPromise.bind(this) | ||
.then(pipfileToRequirements) | ||
.then(pyprojectTomlToRequirements) | ||
.then(_pyprojectTomlToRequirements) | ||
.then(addVendorHelper) | ||
.then(installAllRequirements) | ||
.then(packRequirements) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,24 +8,25 @@ const tomlParse = require('@iarna/toml/parse-string'); | |
/** | ||
* poetry install | ||
*/ | ||
async function pyprojectTomlToRequirements() { | ||
if (!this.options.usePoetry || !isPoetryProject(this.servicePath)) { | ||
async function pyprojectTomlToRequirements(modulePath, pluginInstance) { | ||
const { serverless, servicePath, options, log, progress } = pluginInstance; | ||
|
||
const moduleProjectPath = path.join(servicePath, modulePath); | ||
if (!options.usePoetry || !isPoetryProject(moduleProjectPath)) { | ||
return; | ||
} | ||
|
||
let generateRequirementsProgress; | ||
if (this.progress && this.log) { | ||
generateRequirementsProgress = this.progress.get( | ||
if (progress && log) { | ||
generateRequirementsProgress = progress.get( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you validate how that behaves when there's multiple functions packaged individually at the same time? Are they being packaged in parallel or not? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I was not aware of this mechanism. I will try to investigate and get back to you. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I conducted an experiment with multiple functions packaged individually. It appears that this plugin is written to package the functions sequentially and does not support parallel packaging: From
Note how the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for checking that 🙇 |
||
'python-generate-requirements-toml' | ||
); | ||
generateRequirementsProgress.update( | ||
'Generating requirements.txt from "pyproject.toml"' | ||
); | ||
this.log.info('Generating requirements.txt from "pyproject.toml"'); | ||
log.info('Generating requirements.txt from "pyproject.toml"'); | ||
} else { | ||
this.serverless.cli.log( | ||
'Generating requirements.txt from pyproject.toml...' | ||
); | ||
serverless.cli.log('Generating requirements.txt from pyproject.toml...'); | ||
} | ||
|
||
try { | ||
|
@@ -42,15 +43,15 @@ async function pyprojectTomlToRequirements() { | |
'--with-credentials', | ||
], | ||
{ | ||
cwd: this.servicePath, | ||
cwd: moduleProjectPath, | ||
} | ||
); | ||
} catch (e) { | ||
if ( | ||
e.stderrBuffer && | ||
e.stderrBuffer.toString().includes('command not found') | ||
) { | ||
throw new this.serverless.classes.Error( | ||
throw new serverless.classes.Error( | ||
`poetry not found! Install it according to the poetry docs.`, | ||
'PYTHON_REQUIREMENTS_POETRY_NOT_FOUND' | ||
); | ||
|
@@ -59,16 +60,16 @@ async function pyprojectTomlToRequirements() { | |
} | ||
|
||
const editableFlag = new RegExp(/^-e /gm); | ||
const sourceRequirements = path.join(this.servicePath, 'requirements.txt'); | ||
const sourceRequirements = path.join(moduleProjectPath, 'requirements.txt'); | ||
const requirementsContents = fse.readFileSync(sourceRequirements, { | ||
encoding: 'utf-8', | ||
}); | ||
|
||
if (requirementsContents.match(editableFlag)) { | ||
if (this.log) { | ||
this.log.info('The generated file contains -e flags, removing them'); | ||
if (log) { | ||
log.info('The generated file contains -e flags, removing them'); | ||
} else { | ||
this.serverless.cli.log( | ||
serverless.cli.log( | ||
'The generated file contains -e flags, removing them...' | ||
); | ||
} | ||
|
@@ -78,10 +79,10 @@ async function pyprojectTomlToRequirements() { | |
); | ||
} | ||
|
||
fse.ensureDirSync(path.join(this.servicePath, '.serverless')); | ||
fse.ensureDirSync(path.join(servicePath, '.serverless')); | ||
fse.moveSync( | ||
sourceRequirements, | ||
path.join(this.servicePath, '.serverless', 'requirements.txt'), | ||
path.join(servicePath, '.serverless', modulePath, 'requirements.txt'), | ||
{ overwrite: true } | ||
); | ||
} finally { | ||
|
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() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[tool.poetry] | ||
name = "poetry" | ||
version = "0.1.0" | ||
description = "" | ||
authors = ["Your Name <[email protected]>"] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.6" | ||
Flask = "^1.0" | ||
bottle = {git = "https://[email protected]/bottlepy/bottle.git", tag = "0.12.16"} | ||
boto3 = "^1.9" | ||
|
||
[tool.poetry.dev-dependencies] | ||
|
||
[build-system] | ||
requires = ["poetry>=0.12"] | ||
build-backend = "poetry.masonry.api" |
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-5.3.1.tgz" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
service: sls-py-req-test | ||
|
||
provider: | ||
name: aws | ||
runtime: python3.6 | ||
|
||
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} | ||
defaults: | ||
zip: false | ||
slimPatterns: false | ||
slimPatternsAppendDefaults: true | ||
slim: false | ||
dockerizePip: false | ||
|
||
package: | ||
individually: true | ||
|
||
functions: | ||
hello: | ||
handler: handler.hello | ||
module: module1 | ||
package: | ||
patterns: | ||
- 'module1/**' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that change needed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the source files for this project are located in ./lib/ , this .gitignore was causing any changes to the JS files to be ignored for git purposes. It seemed quite peculiar to me that a project would .gitignore it's own source folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's right - I guess it would be better to just remove this line instead of commenting it