Skip to content

Commit b6ab2a9

Browse files
committed
check requirements.txt for local references
allows assemble_from_subset when requirements.txt doesn't contain any local references
1 parent 5cf4f78 commit b6ab2a9

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

repo2docker/buildpacks/python/__init__.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,62 @@ def python_version(self):
3434
self._python_version = py_version
3535
return self._python_version
3636

37+
def get_assemble_files(self):
38+
assemble_files = super().get_assemble_files()
39+
for name in ('requirements.txt', 'requirements3.txt'):
40+
requirements_txt = self.binder_path(name)
41+
if os.path.exists(requirements_txt):
42+
assemble_files.append(requirements_txt)
43+
return assemble_files
44+
45+
def _is_local_requirement(self, line):
46+
"""Return whether a line in a requirements.txt file references a local file"""
47+
# trim comments and skip empty lines
48+
line = line.split('#', 1)[0].strip()
49+
if not line:
50+
return False
51+
if line.startswith(('-r', '-c')):
52+
# local -r or -c references break isolation
53+
return True
54+
# strip off `-e, etc.`
55+
if line.startswith('-'):
56+
line = line.split(None, 1)[1]
57+
if 'file://' in line:
58+
# file references break isolation
59+
return True
60+
if '://' in line:
61+
# handle git://../local/file
62+
path = line.split('://', 1)[1]
63+
else:
64+
path = line
65+
if path.startswith('.'):
66+
# references a local file
67+
return True
68+
return False
69+
70+
@property
71+
def assemble_from_subset(self):
72+
"""Peek in requirements.txt to determine if we can assemble from only env files
73+
74+
If there are any local references, e.g. `-e .`,
75+
stage the whole repo prior to installation.
76+
"""
77+
if not os.path.exists('binder') and os.path.exists('setup.py'):
78+
# can't install from subset if we're using setup.py
79+
return False
80+
for name in ('requirements.txt', 'requirements3.txt'):
81+
requirements_txt = self.binder_path(name)
82+
if not os.path.exists(requirements_txt):
83+
continue
84+
with open(requirements_txt) as f:
85+
for line in f:
86+
if self._is_local_requirement(line):
87+
return False
88+
89+
# didn't find any local references,
90+
# allow assembly from subset
91+
return True
92+
3793
def get_assemble_scripts(self):
3894
"""Return series of build-steps specific to this repository.
3995
"""

0 commit comments

Comments
 (0)