Skip to content

Commit 79c2617

Browse files
committed
parse pipfiles to determine Python version
these are structured files, no need to use regular expressions to parse them
1 parent 88eaa23 commit 79c2617

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

repo2docker/buildpacks/pipfile/__init__.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
"""Buildpack for git repos with Pipfile.lock or Pipfile within them. `pipenv`
2-
will be used to install the dependencies but we will manually install declared
3-
Python versions instead of using PyEnv."""
1+
"""Buildpack for git repos with Pipfile.lock or Pipfile
42
3+
`pipenv` will be used to install the dependencies
4+
conda will provide the base Python environment,
5+
same as the Python or Conda build packs.
6+
"""
7+
8+
import json
59
import os
610
import re
711

12+
import toml
13+
814
from ..conda import CondaBuildPack
915

16+
VERSION_PAT = re.compile(r"\d+(\.\d+)*")
17+
1018

1119
class PipfileBuildPack(CondaBuildPack):
1220
"""Setup Python with pipfile for use with a repository."""
@@ -23,38 +31,39 @@ def python_version(self):
2331
return self._python_version
2432

2533
files_to_search_in_order = [
26-
{
27-
"path": self.binder_path("Pipfile.lock"),
28-
"pattern": r"\s*[\",\']python_(?:full_)?version[\",\']: [\",\']?([0-9a-z\.]*)[\",\']?", # ' "python_version": "3.6"'
29-
},
30-
{
31-
"path": self.binder_path("Pipfile"),
32-
"pattern": r"python_(?:full_)?version\s*=+\s*[\",\']?([0-9a-z\.]*)[\",\']?", # 'python_version = "3.6"'
33-
},
34-
{
35-
"path": self.binder_path("runtime.txt"),
36-
"pattern": r"\s*python-([0-9a-z\.]*)\s*", # 'python-3.6'
37-
},
34+
self.binder_path("Pipfile.lock"),
35+
self.binder_path("Pipfile"),
3836
]
3937

38+
lockfile = self.binder_path("Pipfile.lock")
39+
requires_sources = []
40+
if os.path.exists(lockfile):
41+
with open(lockfile) as f:
42+
lock_info = json.load(f)
43+
requires_sources.append(lock_info.get("_meta", {}).get("requires", {}))
44+
45+
pipfile = self.binder_path("Pipfile")
46+
if os.path.exists(pipfile):
47+
with open(pipfile) as f:
48+
pipfile_info = toml.load(f)
49+
requires_sources.append(pipfile_info.get("requires", {}))
50+
4051
py_version = None
41-
for file in files_to_search_in_order:
42-
try:
43-
with open(file["path"]) as f:
44-
for line in f:
45-
match = re.match(file["pattern"], line)
46-
if not match:
47-
continue
48-
py_version = match.group(1)
49-
break
50-
except FileNotFoundError:
51-
pass
52+
for requires in requires_sources:
53+
for key in ("python_full_version", "python_version"):
54+
version_str = requires.get(key, None)
55+
if version_str:
56+
match = VERSION_PAT.match(version_str)
57+
if match:
58+
py_version = match.group()
59+
if py_version:
60+
break
5261
if py_version:
5362
break
5463

5564
# extract major.minor
5665
if py_version:
57-
if len(py_version) == 1:
66+
if len(py_version.split(".")) == 1:
5867
self._python_version = self.major_pythons.get(py_version[0])
5968
else:
6069
# return major.minor

0 commit comments

Comments
 (0)