diff --git a/LICENSE b/LICENSE index 39fd8e300c0159bea6c242c25bddfbfd134d563f..700311ab291623086237fd8bd4c73e9f6d48222f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2020 Frost Ming +Copyright (c) 2019-2021 Frost Ming Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/news/289.feature.md b/news/289.feature.md new file mode 100644 index 0000000000000000000000000000000000000000..7e623520de10cc4a3fc2f5b9763e92ca7431b169 --- /dev/null +++ b/news/289.feature.md @@ -0,0 +1 @@ +Support `-f setuppy` for `pdm export` to export the metadata as setup.py diff --git a/pdm/formats/__init__.py b/pdm/formats/__init__.py index 7ee26958fb1b25596ab6e7296536d7860070ae0e..b07856c14f69af8c9740b8e626b7cf0506d0690a 100644 --- a/pdm/formats/__init__.py +++ b/pdm/formats/__init__.py @@ -1,9 +1,38 @@ -from pdm.formats import flit, legacy, pipfile, poetry, requirements +from __future__ import annotations -FORMATS = { +import os +from typing import TYPE_CHECKING, Dict, Iterable, Protocol, Tuple + +from pdm.formats import flit, legacy, pipfile, poetry, requirements, setup_py + +if TYPE_CHECKING: + import argparse + + from pdm.models.candidates import Candidate + from pdm.project import Project + + +class FormatConverter(Protocol): + def check_fingerprint(self, project: Project, filename: os.PathLike) -> bool: + ... + + def convert(self, project: Project, filename: os.PathLike) -> Tuple[dict, dict]: + ... + + def export( + self, + project: Project, + candidates: Iterable[Candidate], + options: argparse.Namespace, + ) -> str: + ... + + +FORMATS: Dict[str, FormatConverter] = { "pipfile": pipfile, "poetry": poetry, "flit": flit, "requirements": requirements, "legacy": legacy, + "setuppy": setup_py, } diff --git a/pdm/formats/setup_py.py b/pdm/formats/setup_py.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..54b4e5d63d524e945e685a27882179575c39837c 100644 --- a/pdm/formats/setup_py.py +++ b/pdm/formats/setup_py.py @@ -0,0 +1,16 @@ +import os + + +def check_fingerprint(project, filename): + return os.path.basename(filename) == "setup.py" + + +def convert(project, filename): + raise NotImplementedError() + + +def export(project, candidates, options): + from pdm.pep517.base import Builder + + builder = Builder(project.root) + return builder.format_setup_py() diff --git a/tests/fixtures/projects/demo-package/setup.py b/tests/fixtures/projects/demo-package/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..add2c91ea845567c956c9aa9c0fdedc59d1648c4 --- /dev/null +++ b/tests/fixtures/projects/demo-package/setup.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from setuptools import setup + +import codecs + +with codecs.open("README.md", encoding="utf-8") as fp: + long_description = fp.read() +INSTALL_REQUIRES = [ + "flask", +] + +setup_kwargs = { + "name": "demo-package", + "version": "0.1.0", + "description": "", + "long_description": long_description, + "license": "MIT", + "author": "", + "author_email": "frostming ", + "maintainer": None, + "maintainer_email": None, + "url": "", + "packages": [ + "my_package", + ], + "package_data": {"": ["*"]}, + "long_description_content_type": "text/markdown", + "install_requires": INSTALL_REQUIRES, + "python_requires": ">=3.5", +} + + +setup(**setup_kwargs) diff --git a/tests/test_formats.py b/tests/test_formats.py index 6a36775ab59a34db4a23f7b258ce9e291ea04a18..81e28fae98b204f976e384732970d74cd6be5f7b 100644 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -1,4 +1,5 @@ -from pdm.formats import flit, legacy, pipfile, poetry, requirements +from pdm.formats import flit, legacy, pipfile, poetry, requirements, setup_py +from pdm.project import Project from pdm.utils import cd from tests import FIXTURES @@ -126,3 +127,9 @@ def test_convert_legacy_format(project): assert not result["dev-dependencies"] assert result["optional-dependencies"]["test"] == ["pytest"] assert settings["source"][0]["url"] == "https://test.pypi.org/simple" + + +def test_export_setup_py(): + project = Project(FIXTURES / "projects/demo-package") + content = setup_py.export(project, [], None) + assert content == project.root.joinpath("setup.py").read_text()