Skip to content

Commit

Permalink
Handle PIP requirements text file options
Browse files Browse the repository at this point in the history
  • Loading branch information
arkq committed Feb 3, 2020
1 parent 358c1f0 commit d7283e3
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 19 deletions.
36 changes: 28 additions & 8 deletions src/flake8_requirements/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@ def project2module(project):
return project


def joinlines(lines):
"""Strip comments and join line continuations."""
joined_line = ""
for line in map(lambda x: x.strip(), lines):
if not line or line.startswith("#"):
continue
if line.endswith("\\"):
joined_line += line[:-1]
continue
yield joined_line + line
joined_line = ""


class ImportVisitor(ast.NodeVisitor):
"""Import statement visitor."""

Expand Down Expand Up @@ -318,25 +331,32 @@ def parse_options(cls, options):
@classmethod
def resolve_requirement(cls, requirement, max_depth=0):
"""Resolves flags like -r in an individual requirement line."""
requirement = requirement.strip()

if requirement.startswith("#") or not requirement:
return []
option = None
option_matcher = re.match(r"(-[\w-]+)(.*)", requirement)
if option_matcher:
option = option_matcher.group(1)
requirement = option_matcher.group(2).lstrip()

if requirement.startswith("-r "):
if option in ("-e", "--editable"):
# We do not care about installation mode.
option = None

if option in ("-r", "--requirement"):
# Error out if we need to recurse deeper than allowed.
if max_depth <= 0:
msg = "Cannot resolve {}: beyond max depth"
raise RuntimeError(msg.format(requirement.strip()))

raise RuntimeError(msg.format(requirement))
resolved = []
# Error out if requirements file cannot be opened.
with open(requirement[3:].lstrip()) as f:
for line in f.readlines():
with open(requirement) as f:
for line in joinlines(f.readlines()):
resolved.extend(cls.resolve_requirement(
line, max_depth - 1))
return resolved

if option:
return []
return [requirement]

@classmethod
Expand Down
27 changes: 16 additions & 11 deletions test/test_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,16 @@ class RequirementsTestCase(unittest.TestCase):
def setUp(self):
memoize.mem = {}

def test_resolve_requirement_with_blank(self):
self.assertEqual(Flake8Checker.resolve_requirement(""), [])

def test_resolve_requirement_with_comment(self):
def test_resolve_requirement(self):
self.assertEqual(
Flake8Checker.resolve_requirement("#-r requirements.txt"),
[],
Flake8Checker.resolve_requirement("foo >= 1.0.0"),
["foo >= 1.0.0"],
)

def test_resolve_requirement_with_simple(self):
def test_resolve_requirement_option(self):
self.assertEqual(
Flake8Checker.resolve_requirement("foo >= 1.0.0"),
["foo >= 1.0.0"],
Flake8Checker.resolve_requirement("--extra-index-url"),
[],
)

def test_resolve_requirement_with_file_beyond_max_depth(self):
Expand All @@ -53,14 +50,22 @@ def test_resolve_requirement_with_file_content(self):
["foo >= 1.0.0", "bar <= 1.0.0"],
)

def test_resolve_requirement_with_file_content_line_continuation(self):
content = "foo[bar] \\\n>= 1.0.0\n"
with mock.patch(builtins_open, mock.mock_open(read_data=content)):
self.assertEqual(
Flake8Checker.resolve_requirement("-r requirements.txt", 1),
["foo[bar] >= 1.0.0"],
)

def test_resolve_requirement_with_file_recursion_beyond_max_depth(self):
content = "-r requirements.txt\n"
with mock.patch(builtins_open, mock.mock_open(read_data=content)):
with self.assertRaises(RuntimeError):
Flake8Checker.resolve_requirement("-r requirements.txt", 1),

def test_resolve_requirement_with_file_recursion(self):
content = "foo >= 1.0.0\n-r inner.txt\nbar <= 1.0.0\n"
content = "--requirement inner.txt\nbar <= 1.0.0\n"
inner_content = "# inner\nbaz\n\nqux\n"

with mock.patch(builtins_open, mock.mock_open()) as m:
Expand All @@ -71,7 +76,7 @@ def test_resolve_requirement_with_file_recursion(self):

self.assertEqual(
Flake8Checker.resolve_requirement("-r requirements.txt", 2),
["foo >= 1.0.0", "baz", "qux", "bar <= 1.0.0"],
["baz", "qux", "bar <= 1.0.0"],
)

def test_init_with_no_requirements(self):
Expand Down

0 comments on commit d7283e3

Please sign in to comment.