diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a9c5e63e5..15dc525b1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,6 +76,7 @@ jobs: - julia - nix - pipfile + - poetry - r - unit - venv diff --git a/repo2docker/app.py b/repo2docker/app.py index 946713732..bc732bc6a 100755 --- a/repo2docker/app.py +++ b/repo2docker/app.py @@ -33,6 +33,7 @@ LegacyBinderDockerBuildPack, NixBuildPack, PipfileBuildPack, + PoetryBuildPack, PythonBuildPack, RBuildPack, ) @@ -97,6 +98,7 @@ def _default_log_level(self): RBuildPack, CondaBuildPack, PipfileBuildPack, + PoetryBuildPack, PythonBuildPack, ], config=True, diff --git a/repo2docker/buildpacks/__init__.py b/repo2docker/buildpacks/__init__.py index 10fe89a4e..11066642a 100644 --- a/repo2docker/buildpacks/__init__.py +++ b/repo2docker/buildpacks/__init__.py @@ -1,6 +1,7 @@ from .base import BuildPack, BaseImage from .python import PythonBuildPack from .pipfile import PipfileBuildPack +from .poetry import PoetryBuildPack from .conda import CondaBuildPack from .julia import JuliaProjectTomlBuildPack from .julia import JuliaRequireBuildPack diff --git a/repo2docker/buildpacks/poetry/__init__.py b/repo2docker/buildpacks/poetry/__init__.py new file mode 100644 index 000000000..941bf5fcc --- /dev/null +++ b/repo2docker/buildpacks/poetry/__init__.py @@ -0,0 +1,186 @@ +"""Buildpack for git repos with poetry.lock or pyproject.toml + +`poetry` will be used to install the dependencies conda will provide the base +Python environment, same as the Python or Conda build packs. +""" + +import os + +from poetry.core.semver import parse_constraint +import toml + +from ..conda import CondaBuildPack + +# Minimum compatible version of python2 for use with Poetry +COMPATIBLE_PYTHON2_VERSIONS = parse_constraint(">=2.7") + +# Minimum compatible version of python3 for use with Poetry +COMPATIBLE_PYTHON3_VERSIONS = parse_constraint(">=3.5") + + +class PoetryBuildPack(CondaBuildPack): + """Setup Python with poetry for use with a repository.""" + + @property + def python_version(self): + """ + Detect the Python version declared in a `poetry.lock`, `pyproject.toml'. + Will return 'x.y' if version is found (e.g '3.6'), or a Falsy empty + string `''` if not found. + """ + + if hasattr(self, "_python_version"): + return self._python_version + + requested_version = "*" + + pyproject = self.binder_path("pyproject.toml") + if os.path.exists(pyproject): + with open(pyproject) as f: + pyproject_info = toml.load(f) + specified_version = ( + pyproject_info.get("tool", {}) + .get("poetry", {}) + .get("dependencies", {}) + .get("python", None) + ) + + if not specified_version is None: + requested_version = specified_version + + lockfile = self.binder_path("poetry.lock") + if os.path.exists(lockfile): + with open(lockfile) as f: + lock_info = toml.load(f) + specified_version = lock_info.get("metadata", {}).get( + "python-versions", None + ) + + if not specified_version is None: + requested_version = specified_version + + requested_constraint = parse_constraint(requested_version) + + version_range = parse_constraint("*") + + if requested_constraint.allows(parse_constraint("2")): + version_range = version_range.intersect(COMPATIBLE_PYTHON2_VERSIONS) + + if requested_constraint.allows(parse_constraint("3")): + # If the given constraint allows for python 3, then this will + # overwrite the range provided by python 2 + version_range = version_range.intersect(COMPATIBLE_PYTHON3_VERSIONS) + + if requested_constraint.allows_any(version_range): + # If the requested constraint is in the version range, then the + # intersection is non-zero and should be valid, so we narrow the + # constraint here + requested_constraint = version_range.intersect(requested_constraint) + else: + # If the requested constraint not in the version range then most + # likely the requested constraint is outside of the the + # COMPATIBLE_PYTHON3_VERSIONS, this should only happen if a newer + # versions of python is explicitly required, we trust this request + requested_constraint = requested_constraint.min + + self._python_version = str(requested_constraint.min) + + return self._python_version + + def get_preassemble_script_files(self): + """Return files needed for preassembly""" + files = super().get_preassemble_script_files() + for name in ("requirements3.txt", "pyproject.toml", "poetry.lock"): + path = self.binder_path(name) + if os.path.exists(path): + files[path] = path + return files + + def get_preassemble_scripts(self): + """scripts to run prior to staging the repo contents""" + scripts = super().get_preassemble_scripts() + # install poetry to install dependencies within poetry.lock or + # pyproject.toml + scripts.append( + ("${NB_USER}", "${KERNEL_PYTHON_PREFIX}/bin/pip install poetry==1.1.3") + ) + return scripts + + def get_assemble_scripts(self): + """Return series of build-steps specific to this repository.""" + # If we have either poetry.lock, pyproject.toml, or runtime.txt declare + # the use of Python 2, Python 2.7 will be made available in the *kernel* + # environment. The notebook servers environment on the other hand + # requires Python 3 but may require something additional installed in it + # still such as `nbgitpuller`. For this purpose, a "requirements3.txt" + # file will be used to install dependencies for the notebook servers + # environment, if Python 2 had been specified for the kernel + # environment. + assemble_scripts = super().get_assemble_scripts() + + if self.py2: + # using Python 2 as a kernel, but Python 3 for the notebook server + + # requirements3.txt allows for packages to be installed to the + # notebook servers Python environment + nb_requirements_file = self.binder_path("requirements3.txt") + if os.path.exists(nb_requirements_file): + assemble_scripts.append( + ( + "${NB_USER}", + '${{NB_PYTHON_PREFIX}}/bin/pip install --no-cache-dir -r "{}"'.format( + nb_requirements_file + ), + ) + ) + + # pyproject.toml and poetry.lock files can have relative path references + # so we should be careful about the working directory during the install + # [tool.poetry.dependencies] + # python = "^3.8" + # extra-data = {path = "sampleproject"} + working_directory = self.binder_dir or "." + + # NOTES: + # - poetry either uses a configuration file or environment variables for + # configuration settings, here we use the inline + # `POETRY_VIRTUALENVS_CREATE=false` to tell poetry to not create + # another virtual environment during the install and to just install + # into the system python environment + assemble_scripts.append( + ( + "${NB_USER}", + """(cd {working_directory} && \\ + PATH="${{KERNEL_PYTHON_PREFIX}}/bin:$PATH" \\ + POETRY_VIRTUALENVS_CREATE=false poetry install \\ + )""".format( + working_directory=working_directory, + ), + ) + ) + + return assemble_scripts + + def detect(self): + """Check if current repo should be built with the Poetry buildpack.""" + # first make sure python is not explicitly unwanted + runtime_txt = self.binder_path("runtime.txt") + if os.path.exists(runtime_txt): + with open(runtime_txt) as f: + runtime = f.read().strip() + if not runtime.startswith("python-"): + return False + + pyproject = self.binder_path("pyproject.toml") + poetry_lock = self.binder_path("poetry.lock") + + is_poetry = False + if os.path.exists(pyproject): + with open(pyproject) as f: + pyproject_info = toml.load(f) + backend = pyproject_info.get("build-system", {}).get( + "build-backend", "" + ) + is_poetry = backend == "poetry.masonry.api" + + return is_poetry or os.path.exists(poetry_lock) diff --git a/setup.py b/setup.py index e4eb16a0f..bab9b5dd0 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,7 @@ def get_identifier(json): "escapism", "iso8601", "jinja2", + "poetry-core", "python-json-logger", "requests", "ruamel.yaml>=0.15", diff --git a/tests/poetry/binder-folder-lock/README.rst b/tests/poetry/binder-folder-lock/README.rst new file mode 100644 index 000000000..e46c9dbde --- /dev/null +++ b/tests/poetry/binder-folder-lock/README.rst @@ -0,0 +1,4 @@ +Python - binder/poetry.lock + poetry.lock +----------------------------------------- + +We should make ``binder/poetry.lock`` take precedence over ``poetry.lock``. diff --git a/tests/poetry/binder-folder-lock/binder/poetry.lock b/tests/poetry/binder-folder-lock/binder/poetry.lock new file mode 100644 index 000000000..b9be159a7 --- /dev/null +++ b/tests/poetry/binder-folder-lock/binder/poetry.lock @@ -0,0 +1,18 @@ +[[package]] +name = "cowsay" +version = "2.0.3" +description = "The famous cowsay for GNU/Linux is now available for python" +category = "main" +optional = false +python-versions = "*" + +[metadata] +lock-version = "1.0" +python-versions = "^3.8" +content-hash = "5a5eb4f9610516deb922c9e6a1ec43c788c2c1d7096b9f429a747905c0cd9b3e" + +[metadata.files] +cowsay = [ + {file = "cowsay-2.0.3-py2.py3-none-any.whl", hash = "sha256:7ec3ec1bb085cbb788b0de1e762941b4469faf41c6cdbec08a7ac072a7d1d6eb"}, + {file = "cowsay-2.0.3.tar.gz", hash = "sha256:debde99bae664bd91487613223c1cb291170d8703bf7d524c3a4877ad37b4dad"}, +] diff --git a/tests/poetry/binder-folder-lock/binder/pyproject.toml b/tests/poetry/binder-folder-lock/binder/pyproject.toml new file mode 100644 index 000000000..e67496fb0 --- /dev/null +++ b/tests/poetry/binder-folder-lock/binder/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/binder-folder-lock/poetry.lock b/tests/poetry/binder-folder-lock/poetry.lock new file mode 100644 index 000000000..c8d416b1c --- /dev/null +++ b/tests/poetry/binder-folder-lock/poetry.lock @@ -0,0 +1,40 @@ +[[package]] +name = "peppercorn" +version = "0.6" +description = "A library for converting a token stream into a data structure for use in web form posts" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +docs = ["Sphinx (>=1.7.6)", "pylons-sphinx-themes"] + +[[package]] +name = "sampleproject" +version = "2.0.0" +description = "A sample Python project" +category = "main" +optional = false +python-versions = ">=3.5, <4" + +[package.extras] +dev = ["check-manifest"] +test = ["coverage"] + +[package.dependencies] +peppercorn = "*" + +[metadata] +lock-version = "1.0" +python-versions = "^3.8" +content-hash = "9ab21f1c5bd9ba54d90234a17f1774f2fc3f53a77afff1dafed4d955462cee65" + +[metadata.files] +peppercorn = [ + {file = "peppercorn-0.6-py3-none-any.whl", hash = "sha256:46125cad688a9cf3b08e463bcb797891ee73ece93602a8ea6f14e40d1042d454"}, + {file = "peppercorn-0.6.tar.gz", hash = "sha256:96d7681d7a04545cfbaf2c6fb66de67b29cfc42421aa263e4c78f2cbb85be4c6"}, +] +sampleproject = [ + {file = "sampleproject-2.0.0-py3-none-any.whl", hash = "sha256:2b0c55537193b792098977fdb62f0acbaeb2c3cfc56d0e24ccab775201462e04"}, + {file = "sampleproject-2.0.0.tar.gz", hash = "sha256:d99de34ffae5515db43916ec47380d3c603e9dead526f96581b48c070cc816d3"}, +] diff --git a/tests/poetry/binder-folder-lock/pyproject.toml b/tests/poetry/binder-folder-lock/pyproject.toml new file mode 100644 index 000000000..ab24b9878 --- /dev/null +++ b/tests/poetry/binder-folder-lock/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +sampleproject = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/binder-folder-lock/verify b/tests/poetry/binder-folder-lock/verify new file mode 100755 index 000000000..f5912ee52 --- /dev/null +++ b/tests/poetry/binder-folder-lock/verify @@ -0,0 +1,5 @@ +#!/usr/bin/env python +import cowsay + +# pypi_pkg_test is installed from the binder folder's Pipfile, but not from the +# root folder's Pipfile! diff --git a/tests/poetry/binder-folder/README.rst b/tests/poetry/binder-folder/README.rst new file mode 100644 index 000000000..8c07a71b0 --- /dev/null +++ b/tests/poetry/binder-folder/README.rst @@ -0,0 +1,4 @@ +Python - binder/pyproject.toml + pyproject.toml +----------------------------------------------- + +We should make ``binder/pyproject.toml`` take precedence over ``pyproject.toml``. diff --git a/tests/poetry/binder-folder/binder/pyproject.toml b/tests/poetry/binder-folder/binder/pyproject.toml new file mode 100644 index 000000000..e67496fb0 --- /dev/null +++ b/tests/poetry/binder-folder/binder/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/binder-folder/pyproject.toml b/tests/poetry/binder-folder/pyproject.toml new file mode 100644 index 000000000..ab24b9878 --- /dev/null +++ b/tests/poetry/binder-folder/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +sampleproject = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/binder-folder/verify b/tests/poetry/binder-folder/verify new file mode 100755 index 000000000..f5912ee52 --- /dev/null +++ b/tests/poetry/binder-folder/verify @@ -0,0 +1,5 @@ +#!/usr/bin/env python +import cowsay + +# pypi_pkg_test is installed from the binder folder's Pipfile, but not from the +# root folder's Pipfile! diff --git a/tests/poetry/environment-yml/README.rst b/tests/poetry/environment-yml/README.rst new file mode 100644 index 000000000..9a60af2a3 --- /dev/null +++ b/tests/poetry/environment-yml/README.rst @@ -0,0 +1,6 @@ +Python - pyproject.toml (poetry.lock) + environment.yml +------------------------------------------------------- + +We should ignore the ``pyproject.toml`` or ``poetry.lock`` if there is an +``environment.yml`` alongside it. Conda can install more things than ``pip`` or +can so we would limit ourselves if we prioritized the ``Pipfile``s. diff --git a/tests/poetry/environment-yml/environment.yml b/tests/poetry/environment-yml/environment.yml new file mode 100644 index 000000000..57866fd85 --- /dev/null +++ b/tests/poetry/environment-yml/environment.yml @@ -0,0 +1,3 @@ +dependencies: + - pip: + - sampleproject diff --git a/tests/poetry/environment-yml/poetry.lock b/tests/poetry/environment-yml/poetry.lock new file mode 100644 index 000000000..b9be159a7 --- /dev/null +++ b/tests/poetry/environment-yml/poetry.lock @@ -0,0 +1,18 @@ +[[package]] +name = "cowsay" +version = "2.0.3" +description = "The famous cowsay for GNU/Linux is now available for python" +category = "main" +optional = false +python-versions = "*" + +[metadata] +lock-version = "1.0" +python-versions = "^3.8" +content-hash = "5a5eb4f9610516deb922c9e6a1ec43c788c2c1d7096b9f429a747905c0cd9b3e" + +[metadata.files] +cowsay = [ + {file = "cowsay-2.0.3-py2.py3-none-any.whl", hash = "sha256:7ec3ec1bb085cbb788b0de1e762941b4469faf41c6cdbec08a7ac072a7d1d6eb"}, + {file = "cowsay-2.0.3.tar.gz", hash = "sha256:debde99bae664bd91487613223c1cb291170d8703bf7d524c3a4877ad37b4dad"}, +] diff --git a/tests/poetry/environment-yml/pyproject.toml b/tests/poetry/environment-yml/pyproject.toml new file mode 100644 index 000000000..e67496fb0 --- /dev/null +++ b/tests/poetry/environment-yml/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/environment-yml/verify b/tests/poetry/environment-yml/verify new file mode 100755 index 000000000..84a64f67f --- /dev/null +++ b/tests/poetry/environment-yml/verify @@ -0,0 +1,2 @@ +#!/usr/bin/env python +import sample diff --git a/tests/poetry/poetry-lock/README.rst b/tests/poetry/poetry-lock/README.rst new file mode 100644 index 000000000..a65a2c9a3 --- /dev/null +++ b/tests/poetry/poetry-lock/README.rst @@ -0,0 +1,4 @@ +Python - pyproject.toml + poetry.lock +------------------------------------- + +We should make ``poetry.lock`` take precedence over ``pyproject.toml``. diff --git a/tests/poetry/poetry-lock/poetry.lock b/tests/poetry/poetry-lock/poetry.lock new file mode 100644 index 000000000..5fbe571e9 --- /dev/null +++ b/tests/poetry/poetry-lock/poetry.lock @@ -0,0 +1,51 @@ +[[package]] +name = "cowsay" +version = "1.0" +description = "The famous cowsay for GNU/Linux is now available for python" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "peppercorn" +version = "0.6" +description = "A library for converting a token stream into a data structure for use in web form posts" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +docs = ["Sphinx (>=1.7.6)", "pylons-sphinx-themes"] + +[[package]] +name = "sampleproject" +version = "2.0.0" +description = "A sample Python project" +category = "main" +optional = false +python-versions = ">=3.5, <4" + +[package.extras] +dev = ["check-manifest"] +test = ["coverage"] + +[package.dependencies] +peppercorn = "*" + +[metadata] +lock-version = "1.0" +python-versions = "^3.8" +content-hash = "3d0b36e40885f1a5e42ef7875f6019b8b66fc79dc9eda35906003832548c2af6" + +[metadata.files] +cowsay = [ + {file = "cowsay-1.0.tar.gz", hash = "sha256:93bf7695c179ff8c93ea5cb1d0d4a895c30c6756087da8cb1deb4165f4fc8c24"}, +] +peppercorn = [ + {file = "peppercorn-0.6-py3-none-any.whl", hash = "sha256:46125cad688a9cf3b08e463bcb797891ee73ece93602a8ea6f14e40d1042d454"}, + {file = "peppercorn-0.6.tar.gz", hash = "sha256:96d7681d7a04545cfbaf2c6fb66de67b29cfc42421aa263e4c78f2cbb85be4c6"}, +] +sampleproject = [ + {file = "sampleproject-2.0.0-py3-none-any.whl", hash = "sha256:2b0c55537193b792098977fdb62f0acbaeb2c3cfc56d0e24ccab775201462e04"}, + {file = "sampleproject-2.0.0.tar.gz", hash = "sha256:d99de34ffae5515db43916ec47380d3c603e9dead526f96581b48c070cc816d3"}, +] diff --git a/tests/poetry/poetry-lock/pyproject.toml b/tests/poetry/poetry-lock/pyproject.toml new file mode 100644 index 000000000..891103696 --- /dev/null +++ b/tests/poetry/poetry-lock/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" +sampleproject = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/poetry-lock/verify b/tests/poetry/poetry-lock/verify new file mode 100755 index 000000000..713bf3401 --- /dev/null +++ b/tests/poetry/poetry-lock/verify @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import sample +import cowsay + +# The pyproject.toml asks for any version of cowsay, and will by default pick +# the highest compatible version, but the lockfile specifically requests +# version 1.0, so we check that the lockfile-requested version is installed +if cowsay.main.__version__ == 1.0: + pass +else: + raise Exception( + f"Installed `cowsay` version is {cowsay.main.__version__}, not 1.0 as " + "requested by the lockfile, is the lockfile being used?" + ) diff --git a/tests/poetry/py2-with-server-and-kernel-req/README.rst b/tests/poetry/py2-with-server-and-kernel-req/README.rst new file mode 100644 index 000000000..22aaf98b6 --- /dev/null +++ b/tests/poetry/py2-with-server-and-kernel-req/README.rst @@ -0,0 +1,8 @@ +Python 2 - Pipfile and requirements3.txt +---------------------------------------- + +- We should get Python 2 setup for the Kernel + - with 'cowsay' and 'sampleproject' installed through poetry.lock as listed + in 'packages' - with installed through poetry.lock as listed in +- We should get Python 3 setup for the Notebook Server, with 'nbgitpuller' +installed through requirements3.txt diff --git a/tests/poetry/py2-with-server-and-kernel-req/poetry.lock b/tests/poetry/py2-with-server-and-kernel-req/poetry.lock new file mode 100644 index 000000000..395817756 --- /dev/null +++ b/tests/poetry/py2-with-server-and-kernel-req/poetry.lock @@ -0,0 +1,53 @@ +[[package]] +name = "cowsay" +version = "2.0.3" +description = "The famous cowsay for GNU/Linux is now available for python" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "peppercorn" +version = "0.6" +description = "A library for converting a token stream into a data structure for use in web form posts" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +docs = ["Sphinx (>=1.7.6)", "pylons-sphinx-themes"] + +[[package]] +name = "sampleproject" +version = "1.3.1" +description = "A sample Python project" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +dev = ["check-manifest"] +test = ["coverage"] + +[package.dependencies] +peppercorn = "*" + +[metadata] +lock-version = "1.0" +python-versions = "^2.7" +content-hash = "782c75d8e8b5fbe5b8d5486b81b6375764194a0d36d1054be9dcdd1ef9654c72" + +[metadata.files] +cowsay = [ + {file = "cowsay-2.0.3-py2.py3-none-any.whl", hash = "sha256:7ec3ec1bb085cbb788b0de1e762941b4469faf41c6cdbec08a7ac072a7d1d6eb"}, + {file = "cowsay-2.0.3.tar.gz", hash = "sha256:debde99bae664bd91487613223c1cb291170d8703bf7d524c3a4877ad37b4dad"}, +] +peppercorn = [ + {file = "peppercorn-0.6-py3-none-any.whl", hash = "sha256:46125cad688a9cf3b08e463bcb797891ee73ece93602a8ea6f14e40d1042d454"}, + {file = "peppercorn-0.6.tar.gz", hash = "sha256:96d7681d7a04545cfbaf2c6fb66de67b29cfc42421aa263e4c78f2cbb85be4c6"}, +] +sampleproject = [ + {file = "sampleproject-1.3.1-py2.py3-none-any.whl", hash = "sha256:26c9172e08244873b0e09c574a229bf2c251c67723a05e08fd3ec0c5ee423796"}, + {file = "sampleproject-1.3.1-py3-none-any.whl", hash = "sha256:75bb5bb4e74a1b77dc0cff25ebbacb54fe1318aaf99a86a036cefc86ed885ced"}, + {file = "sampleproject-1.3.1.tar.gz", hash = "sha256:3593ca2f1e057279d70d6144b14472fb28035b1da213dde60906b703d6f82c55"}, +] diff --git a/tests/poetry/py2-with-server-and-kernel-req/pyproject.toml b/tests/poetry/py2-with-server-and-kernel-req/pyproject.toml new file mode 100644 index 000000000..b18a4d697 --- /dev/null +++ b/tests/poetry/py2-with-server-and-kernel-req/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^2.7" +cowsay = "*" +sampleproject = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/py2-with-server-and-kernel-req/requirements3.txt b/tests/poetry/py2-with-server-and-kernel-req/requirements3.txt new file mode 100644 index 000000000..87e197c3a --- /dev/null +++ b/tests/poetry/py2-with-server-and-kernel-req/requirements3.txt @@ -0,0 +1,3 @@ +# install this in the environment in which the notebook server +# is running nbgitpuller does not work with Python 2 +nbgitpuller==0.6.1 diff --git a/tests/poetry/py2-with-server-and-kernel-req/verify b/tests/poetry/py2-with-server-and-kernel-req/verify new file mode 100755 index 000000000..08cd2df9a --- /dev/null +++ b/tests/poetry/py2-with-server-and-kernel-req/verify @@ -0,0 +1,48 @@ +#!/usr/bin/env python2 +import os +import sys + + +# Verify - kernel's Python: use Python 2 +print(sys.version_info) +assert sys.version_info[:2] == (2, 7) + + +# Verify - notebook server's Python: 'cowsay' isn't installed +status_code = os.system("python3 -c 'import cowsay'") +if status_code == 0: + raise Exception("notebook server's Python: 'cowsay' IS installed") + +# Verify - notebook server's Python: 'sampleproject' isn't installed +status_code = os.system("python3 -c 'import sample'") +if status_code == 0: + raise Exception("notebook server's Python: 'sampleproject' IS installed") + +# Verify - notebook server's Python: 'nbgitpuller' is installed +status_code = os.system("python3 -c 'import nbgitpuller'") +if not status_code == 0: + raise Exception("notebook server's Python: 'nbgitpuller' ISN'T installed") + + +# Verify - kernel's Python: 'nbgitpuller' isn't installed +try: + import nbgitpuller +except ImportError: + pass +else: + raise Exception("kernel's Python: 'nbgitpuller' IS installed") + +# Verify - kernel's Python: 'cowsay' is installed +try: + import cowsay +except ImportError: + raise Exception( + "kernel's Python: 'cowsay' ISN'T installed --- We probably setup a " + "virtual env through pipenv but failed to enter it." + ) + +# Verify - kernel's Python: 'sampleproject' is installed +try: + import sample +except ImportError: + raise Exception("kernel's Python: 'sampleproject' ISN'T installed") diff --git a/tests/poetry/py38/README.rst b/tests/poetry/py38/README.rst new file mode 100644 index 000000000..c7859c2f3 --- /dev/null +++ b/tests/poetry/py38/README.rst @@ -0,0 +1,6 @@ +Python - pyproject.toml with python_version and runtime.txt +----------------------------------------------------------- + +We are ignoring the runtime.txt if there is a pyproject.toml or poetry.lock +available. And since `python_version = "3.8"` in pyproject.toml, the `python-3.7` +in runtime.txt should be ignored. Is it? diff --git a/tests/poetry/py38/poetry.lock b/tests/poetry/py38/poetry.lock new file mode 100644 index 000000000..5e703ee77 --- /dev/null +++ b/tests/poetry/py38/poetry.lock @@ -0,0 +1,52 @@ +[[package]] +name = "cowsay" +version = "2.0.3" +description = "The famous cowsay for GNU/Linux is now available for python" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "peppercorn" +version = "0.6" +description = "A library for converting a token stream into a data structure for use in web form posts" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +docs = ["Sphinx (>=1.7.6)", "pylons-sphinx-themes"] + +[[package]] +name = "sampleproject" +version = "2.0.0" +description = "A sample Python project" +category = "main" +optional = false +python-versions = ">=3.5, <4" + +[package.extras] +dev = ["check-manifest"] +test = ["coverage"] + +[package.dependencies] +peppercorn = "*" + +[metadata] +lock-version = "1.0" +python-versions = "^3.8" +content-hash = "25023cf820511aeb49a277da60d606aabda3df500c7fb22c76398047c1b4af6b" + +[metadata.files] +cowsay = [ + {file = "cowsay-2.0.3-py2.py3-none-any.whl", hash = "sha256:7ec3ec1bb085cbb788b0de1e762941b4469faf41c6cdbec08a7ac072a7d1d6eb"}, + {file = "cowsay-2.0.3.tar.gz", hash = "sha256:debde99bae664bd91487613223c1cb291170d8703bf7d524c3a4877ad37b4dad"}, +] +peppercorn = [ + {file = "peppercorn-0.6-py3-none-any.whl", hash = "sha256:46125cad688a9cf3b08e463bcb797891ee73ece93602a8ea6f14e40d1042d454"}, + {file = "peppercorn-0.6.tar.gz", hash = "sha256:96d7681d7a04545cfbaf2c6fb66de67b29cfc42421aa263e4c78f2cbb85be4c6"}, +] +sampleproject = [ + {file = "sampleproject-2.0.0-py3-none-any.whl", hash = "sha256:2b0c55537193b792098977fdb62f0acbaeb2c3cfc56d0e24ccab775201462e04"}, + {file = "sampleproject-2.0.0.tar.gz", hash = "sha256:d99de34ffae5515db43916ec47380d3c603e9dead526f96581b48c070cc816d3"}, +] diff --git a/tests/poetry/py38/pyproject.toml b/tests/poetry/py38/pyproject.toml new file mode 100644 index 000000000..891103696 --- /dev/null +++ b/tests/poetry/py38/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" +sampleproject = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/py38/runtime.txt b/tests/poetry/py38/runtime.txt new file mode 100644 index 000000000..59a6441f4 --- /dev/null +++ b/tests/poetry/py38/runtime.txt @@ -0,0 +1 @@ +python-3.7 \ No newline at end of file diff --git a/tests/poetry/py38/verify b/tests/poetry/py38/verify new file mode 100755 index 000000000..7ff3e0e36 --- /dev/null +++ b/tests/poetry/py38/verify @@ -0,0 +1,8 @@ +#!/usr/bin/env python +import sys + +import cowsay +import sample + +print(sys.version_info) +assert sys.version_info[:2] == (3, 8) diff --git a/tests/poetry/requirements-txt/README.rst b/tests/poetry/requirements-txt/README.rst new file mode 100644 index 000000000..2f72f8f10 --- /dev/null +++ b/tests/poetry/requirements-txt/README.rst @@ -0,0 +1,4 @@ +Python - pyproject.toml + requirements.txt +------------------------------------------ + +We should make ``pyproject.toml`` take precedence over ``requirements.txt``. diff --git a/tests/poetry/requirements-txt/pyproject.toml b/tests/poetry/requirements-txt/pyproject.toml new file mode 100644 index 000000000..e67496fb0 --- /dev/null +++ b/tests/poetry/requirements-txt/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "binder-folder" +version = "0.1.0" +description = "Test project for poetry buildpack" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/requirements-txt/requirements.txt b/tests/poetry/requirements-txt/requirements.txt new file mode 100644 index 000000000..24ce15ab7 --- /dev/null +++ b/tests/poetry/requirements-txt/requirements.txt @@ -0,0 +1 @@ +numpy diff --git a/tests/poetry/requirements-txt/verify b/tests/poetry/requirements-txt/verify new file mode 100755 index 000000000..68e022729 --- /dev/null +++ b/tests/poetry/requirements-txt/verify @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import cowsay + +try: + import sample +except ImportError: + # We want an ImportError to be thrown for this test to pass + pass +else: + raise Exception( + "'numpy' shouldn't have been installed! It was listed in " + "requirements.txt but not in the Pipfile that has precedence." + ) diff --git a/tests/poetry/setup-py-explicit-in-binder-dir/.binder/pyproject.toml b/tests/poetry/setup-py-explicit-in-binder-dir/.binder/pyproject.toml new file mode 100644 index 000000000..8bbf7598f --- /dev/null +++ b/tests/poetry/setup-py-explicit-in-binder-dir/.binder/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "setup-py-explicit" +version = "0.1.0" +description = "" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" +dummy = {path = "../dummy"} + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/setup-py-explicit-in-binder-dir/README.rst b/tests/poetry/setup-py-explicit-in-binder-dir/README.rst new file mode 100644 index 000000000..29b359bdd --- /dev/null +++ b/tests/poetry/setup-py-explicit-in-binder-dir/README.rst @@ -0,0 +1,5 @@ +Python - pyproject.toml + setup.py +---------------------------------- + +pyproject.toml asked the relative package in the parent directory to be installed +with ``setup.py``, was it? diff --git a/tests/poetry/setup-py-explicit-in-binder-dir/dummy/setup.py b/tests/poetry/setup-py-explicit-in-binder-dir/dummy/setup.py new file mode 100644 index 000000000..c67a722a7 --- /dev/null +++ b/tests/poetry/setup-py-explicit-in-binder-dir/dummy/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup, find_packages + +setup( + name="Dummy", + version="1.0.0", + url="https://git-place.org/dummy/dummy.git", + author="Dummy Name", + author_email="dummy@my-email.com", + description="Dummy package for testing purposes only", + packages=find_packages(), + install_requires=["pypi-pkg-test==0.0.4"], +) diff --git a/tests/poetry/setup-py-explicit-in-binder-dir/verify b/tests/poetry/setup-py-explicit-in-binder-dir/verify new file mode 100755 index 000000000..4d4cc28fa --- /dev/null +++ b/tests/poetry/setup-py-explicit-in-binder-dir/verify @@ -0,0 +1,6 @@ +#!/usr/bin/env python +import cowsay +import dummy + +# This package should be available, as it was a dependency for dummy +import pypi_pkg_test diff --git a/tests/poetry/setup-py-implicit/README.rst b/tests/poetry/setup-py-implicit/README.rst new file mode 100644 index 000000000..02e3f4413 --- /dev/null +++ b/tests/poetry/setup-py-implicit/README.rst @@ -0,0 +1,5 @@ +Python - pyproject.toml + setup.py +---------------------------------- + +pyproject.toml did not ask for the relative package to be installed with +``setup.py``, so lets ensure it wasn't. diff --git a/tests/poetry/setup-py-implicit/dummy/__init__.py b/tests/poetry/setup-py-implicit/dummy/__init__.py new file mode 100644 index 000000000..012898812 --- /dev/null +++ b/tests/poetry/setup-py-implicit/dummy/__init__.py @@ -0,0 +1,2 @@ +def dummy(): + pass diff --git a/tests/poetry/setup-py-implicit/dummy/setup.py b/tests/poetry/setup-py-implicit/dummy/setup.py new file mode 100644 index 000000000..c67a722a7 --- /dev/null +++ b/tests/poetry/setup-py-implicit/dummy/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup, find_packages + +setup( + name="Dummy", + version="1.0.0", + url="https://git-place.org/dummy/dummy.git", + author="Dummy Name", + author_email="dummy@my-email.com", + description="Dummy package for testing purposes only", + packages=find_packages(), + install_requires=["pypi-pkg-test==0.0.4"], +) diff --git a/tests/poetry/setup-py-implicit/pyproject.toml b/tests/poetry/setup-py-implicit/pyproject.toml new file mode 100644 index 000000000..bb836a387 --- /dev/null +++ b/tests/poetry/setup-py-implicit/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "setup-py-explicit" +version = "0.1.0" +description = "" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/setup-py-implicit/verify b/tests/poetry/setup-py-implicit/verify new file mode 100755 index 000000000..01bb8dc7b --- /dev/null +++ b/tests/poetry/setup-py-implicit/verify @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import cowsay + +try: + import dummy + import pypi_pkg_test +except ImportError: + # We want an ImportError to be thrown for this test to pass + pass +else: + raise Exception( + "'dummy' and its dependency 'pypi_pkg_test' shouldn't have been " + "installed! A Pipfile was present without explicit instructions to " + "install the local package 'dummy'." + ) diff --git a/tests/poetry/setup-py-relative/README.rst b/tests/poetry/setup-py-relative/README.rst new file mode 100644 index 000000000..ac6901aa0 --- /dev/null +++ b/tests/poetry/setup-py-relative/README.rst @@ -0,0 +1,5 @@ +Python - pyproject.toml + setup.py +---------------------------------- + +The pyproject.toml asked the relative package to be installed with ``setup.py``, +was it? diff --git a/tests/poetry/setup-py-relative/dummy/setup.py b/tests/poetry/setup-py-relative/dummy/setup.py new file mode 100644 index 000000000..c67a722a7 --- /dev/null +++ b/tests/poetry/setup-py-relative/dummy/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup, find_packages + +setup( + name="Dummy", + version="1.0.0", + url="https://git-place.org/dummy/dummy.git", + author="Dummy Name", + author_email="dummy@my-email.com", + description="Dummy package for testing purposes only", + packages=find_packages(), + install_requires=["pypi-pkg-test==0.0.4"], +) diff --git a/tests/poetry/setup-py-relative/pyproject.toml b/tests/poetry/setup-py-relative/pyproject.toml new file mode 100644 index 000000000..171ce2eaf --- /dev/null +++ b/tests/poetry/setup-py-relative/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "setup-py-explicit" +version = "0.1.0" +description = "" +authors = ["Robert Rosca <32569096+RobertRosca@users.noreply.github.com>"] + +[tool.poetry.dependencies] +python = "^3.8" +cowsay = "*" +dummy = {path = "dummy"} + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/poetry/setup-py-relative/verify b/tests/poetry/setup-py-relative/verify new file mode 100755 index 000000000..4d4cc28fa --- /dev/null +++ b/tests/poetry/setup-py-relative/verify @@ -0,0 +1,6 @@ +#!/usr/bin/env python +import cowsay +import dummy + +# This package should be available, as it was a dependency for dummy +import pypi_pkg_test