Skip to content

Support PEP-621 pyproject.toml #634

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

Open
KerberosMorphy opened this issue Oct 12, 2021 · 1 comment
Open

Support PEP-621 pyproject.toml #634

KerberosMorphy opened this issue Oct 12, 2021 · 1 comment

Comments

@KerberosMorphy
Copy link

KerberosMorphy commented Oct 12, 2021

I know you already support poetry and pipenv, but I would like to request the following feature to support PDM to.
Supporting official PEP-621 pyproject.toml and their extra.

I've try to create this addition since I wanted to contribute, but my javascript isn't really up to date and I have some difficulties to implements tests and understand some part of your code.

What I would like to:

custom:
  pythonRequirements:
    usePyproject: true  # don't know if it's necessary
    extra:
      - rich

so for this pyproject:

[project]
name = "pyproject"
version = "0.1.0"
description = ""
requires-python = ">=3.6"
authors = [
  {name = "Your Name"},
  {email = "[email protected]"},
]
dependencies = [
  "Flask>=1.0",
  "bottle @ git+https://[email protected]/bottlepy/[email protected]",
  "boto3>=1.9",
]

[project.optional-dependencies]
test = [
  "tox",
]
rich = [
  "rich",
]

It would generate:

requirements.txt

Flask>=1.0
bottle @ git+https://[email protected]/bottlepy/[email protected]
boto3>=1.9
rich

What I have tried to do:

const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const { spawnSync } = require('child_process');
const tomlParse = require('@iarna/toml/parse-string');

/**
 * pyproject install
 */
function pyprojectTomlToRequirements() {
  if (!this.options.usePyproject) {
    return;
  }

  this.serverless.cli.log('Generating requirements.txt from pyproject.toml...');

  const destination = path.join(this.servicePath, 'requirements.txt');
  const requirementsContents = extractDependencies(this.servicePath);

  const editableFlag = new RegExp(/^-e /gm);
  const sourceRequirements = path.join(this.servicePath, 'requirements.txt');

  if (requirementsContents.match(editableFlag)) {
    this.serverless.cli.log(
      'The generated file contains -e flags, removing them...'
    );
    fse.writeFileSync(
      sourceRequirements,
      requirementsContents.replace(editableFlag, '')
    );
  }

  fse.ensureDirSync(path.join(this.servicePath, '.serverless'));
  fse.moveSync(
    sourceRequirements,
    path.join(this.servicePath, '.serverless', 'requirements.txt'),
    { overwrite: true }
  );
}

/**
 * Extract dependencies and extra from pyproject.toml
 */
function extractDependencies(servicePath, extra) {
  const pyprojectPath = path.join(servicePath, 'pyproject.toml');

  if (!fse.existsSync(pyprojectPath)) {
    return false;
  }

  const pyprojectToml = fs.readFileSync(pyprojectPath);
  const pyproject = tomlParse(pyprojectToml);

  const dependencies =
    (pyproject['project'] && pyproject['project']['dependencies']) || [];

  const extraDependencies =
    (pyproject['project'] && pyproject['project']['optional-dependencies']) || {};

  for (const [extraName, dependencies] of Object.entries(extraDependencies)) {
    if (extra.includes(extraName)) {
      dependencies = dependencies.concat(dependencies);
    }
  }
  return dependencies.join("\n");
}

module.exports = { pyprojectTomlToRequirements, isPyprojectProject };

Hope that what I've done could help, sorry if I couldn't do more.

@spookyuser
Copy link

This looks amazing, and would be so nice, I love PDM ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants