-
Notifications
You must be signed in to change notification settings - Fork 381
Add buildpack for pyproject.toml to configure container image #1444
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
base: main
Are you sure you want to change the base?
Conversation
83b5f11 to
577cb1b
Compare
|
577cb1b implements a minimal working version. It was tested with https://github.com/rgaiacs/binder-examples-pyproject. Required changes before merge
Changes that can be done in another pull request
|
| """PATH="${KERNEL_PYTHON_PREFIX}/bin:$PATH" \\ | ||
| pip install --no-cache-dir --editable . | ||
| """, |
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.
Can we do:
| """PATH="${KERNEL_PYTHON_PREFIX}/bin:$PATH" \\ | |
| pip install --no-cache-dir --editable . | |
| """, | |
| "${KERNEL_PYTHON_PREFIX}/bin/python3 -m pip install --no-cache-dir --editable .", |
to be even more explicit than relying on $PATH?
|
All tests are passing after support to Python < 3.11 was dropped. |
I've got a PR that refactors the handling of runtime.txt |
ad70986 to
974a559
Compare
|
I rebased this pull request and I made minor changes to reduce the code duplication. It need to be reviewed again. |
|
Can we merge this? Or should we talk about it in jupyterhub/team-compass#814? |
We can depend on try:
import tomllib
except ImportError:
import tomli as tomllibwithout losing any supported environments. I think reverting the baseline version change and depending on tomli, and fixing detection of pyproject.toml contents, I think this should be all set. |
|
|
||
| pyproject_file = self.binder_path("pyproject.toml") | ||
|
|
||
| return os.path.exists(pyproject_file) |
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.
As discussed here, we should not consider the presence of pyproject.toml sufficient. We should return False if pyproject.toml does not contain both project and build-system.requires.
because of tomllib.
since Python 3.9 is no longer supported as it does not have tomllib.
because now repo2docker requires Python >= 3.11 given the requirement of tomllib.
974a559 to
1a393bb
Compare
|
I addressed the comments from @minrk
I also added
I suggest to add more tests in another pull request. |
| To install your reprository like a Python package, you may include a | ||
| `pyproject.toml` file. `repo2docker`install `pyproject.toml` files by running |
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.
| To install your reprository like a Python package, you may include a | |
| `pyproject.toml` file. `repo2docker`install `pyproject.toml` files by running | |
| To install your repository like a Python package, you may include a | |
| `pyproject.toml` file. `repo2docker`installs `pyproject.toml` files by running |
| @@ -0,0 +1,148 @@ | |||
| """Buildpack for Git repositories with pyproject.toml | |||
| Support to pyproject.toml was added to pip v10.0, | |||
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.
| Support to pyproject.toml was added to pip v10.0, | |
| Support for pyproject.toml was added to pip v10.0, |
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.
This implementation looks great to me. My only comment is that I don't think we necessarily need a new buildpack to do this - the assemble steps, etc. should be identical to when setup.py is present. The only effect it should have is detecting the Python version, so it seems to me that it would be simpler to keep everything consistent if this logic is added to the python buildpack, rather than a whole new buildpack that should do all the same things.
But we can also do that as a simplification later. What do you think?
| ## `pyproject.toml` - Install Python packages | ||
|
|
||
| To install your repository like a Python package, you may include a | ||
| `pyproject.toml` file. `repo2docker`installs `pyproject.toml` files by running |
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.
missing space:
| `pyproject.toml` file. `repo2docker`installs `pyproject.toml` files by running | |
| `pyproject.toml` file. `repo2docker` installs `pyproject.toml` files by running |
| and ("build-system" in pyproject_toml) | ||
| and ("requires" in pyproject_toml["build-system"]) | ||
| ): | ||
| return os.path.exists(pyproject_file) |
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.
this condition is always true at this point, we can avoid checking it again:
| return os.path.exists(pyproject_file) | |
| return True |
I don't like code duplication but my line of thoughts was "when we decided to drop support to Tomorrow, I will refactor the code so that there are only one Python buildpack. |
We don't have a setup.py buildpack. setup.py is one small part of the So the real change here ought to be changing the "should we run pip install ." in the Python buildpack from "setup.py exists" to a more general "is it a python package?" which checks:
Then the only other change is detecting Python version from project info, I think, at a lower priority than runtime.txt, binder dir, etc. The rest of |
85a9e6c to
b755b7a
Compare
|
I'm not sure I quite follow - The We could isolate this into a single This is because |
| pyproject_minimum_version.split(".") | ||
| ) | ||
|
|
||
| if (py_version_info[0] < pyproject_minimum_version_info[0]) or ( |
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.
I think there are a few cases not handled here:
pyproject_minimum_version_infocontains strings, not numbers, so it will compare incorrectly sometimes, e.g.'10' < '9'- I think
py_version_infowill be empty when runtime.txt is not specified (i.e. usually), so this conflict check should only be done if runtime.txt is given
Version checking should usually be done via a version-comparison tool like packaging rather than parsing strings ourselves. The version specifier can be parsed by packaging.version.specifier.SpecifierSet, e.g.:
if "requires-python" in pyproject["project"]:
python_specifier = SpecifierSet(pyproject["project"]["requires-python"])
if runtime_specified:
if not python_specifier.contains(py_version):
# error, conflict
else:
# use constraint to pick version, default first
for python_version in [major_pythons["3"], "3.10", "3.11", "3.12", "3.13", "3.14"]:
if python_specifier.contains(python_version):
self._python_version = python_version
break
else:
# error, can't find acceptable versionThere 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.
Thanks for the feedback. I'm finishing my day and I'm on holiday the rest of the week. I can pick this on Monday.
Related to #1427
This is not yet ready for review!The code is based on the Pipfile buildpack. We probably want to refactor some portions to avoid code duplication.