def test_recurse(tmp_path):
    reqs = tmp_path / "reqs.txt"
    subreqs = tmp_path / "subreqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            req1
            -r subreqs.txt
            """))
    subreqs.write_text("req2")
    lines = list(parse(str(reqs)))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == ["req1", "req2"]
    lines = list(parse(str(reqs), recurse=False))
    assert [line.requirement for line in lines] == ["req1"]
def test_file_url(tmp_path):
    reqs = tmp_path / "reqs.txt"
    subreqs = tmp_path / "subreqs.txt"
    subreqs_uri = subreqs.as_uri()
    assert subreqs_uri.startswith("file://")
    reqs.write_text(
        textwrap.dedent("""\
            req1
            -r {}
            """.format(subreqs_uri)))
    subreqs.write_text("req2")
    lines = list(parse(str(reqs)))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == ["req1", "req2"]
    lines = list(parse(str(reqs), recurse=False))
    assert [line.requirement for line in lines] == ["req1"]
def test_basic(tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            # comment
            req1
            req2==1.0.0
            req3 @ https://e.c/req3.tgz
            ./req4
            https://e.c/req5.tgz
            req6 @ https://e.c/req6.tgz ; python_version < 3.7  # comment
            req6 ; python_version >= 3.7  # released version is ok
            """))
    lines = list(parse(str(reqs)))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == [
        "req1",
        "req2==1.0.0",
        "req3 @ https://e.c/req3.tgz",
        "./req4",
        "https://e.c/req5.tgz",
        "req6 @ https://e.c/req6.tgz ; python_version < 3.7",
        "req6 ; python_version >= 3.7",
    ]
    assert lines[0].raw_line == "req1"
    assert lines[0].lineno == 2
def test_subreq_notfound(tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text("-r notfound.txt")
    with pytest.raises(RequirementsFileParserError) as e:
        _ = list(parse(str(reqs)))
    assert "Could not open requirements file" in str(e.value)
    assert "notfound.txt" in str(e.value)
def test_http_url_notfound(tmp_path):
    subreqs_url = "http://e.c/notfound.txt"
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(f"-r {subreqs_url}")
    with pytest.raises(RequirementsFileParserError) as e:
        list(parse(str(reqs), session=MockHttpSession(subreqs_url, None)))
    assert "Could not open requirements file" in str(e.value)
    assert "notfound.txt" in str(e.value)
def test_file_url_not_found(tmp_path):
    reqs = tmp_path / "reqs.txt"
    subreqs_uri = (tmp_path / "notfound.txt").as_uri()
    assert subreqs_uri.startswith("file://")
    reqs.write_text(f"--requirements {subreqs_uri}")
    with pytest.raises(RequirementsFileParserError) as e:
        list(parse(str(reqs)))
    assert "Could not open requirements file" in str(e.value)
    assert "notfound.txt" in str(e.value)
def test_multiline_req(tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            req @ \\
            ./req.tgz  # comment
            """))
    lines = list(parse(str(reqs)))
    assert [line.requirement for line in lines] == ["req @ ./req.tgz"]
def test_http_url(tmp_path):
    subreqs_url = "http://e.c/subreqs.txt"

    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent(f"""\
            req1
            -r {subreqs_url}
            """))
    with pytest.raises(RequirementsFileParserError) as e:
        list(parse(str(reqs)))
    assert f"Cannot get {subreqs_url} because no http session is available" in str(
        e.value)
    lines = list(parse(str(reqs), session=MockHttpSession(subreqs_url,
                                                          "req2")))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == ["req1", "req2"]
    lines = list(parse(str(reqs), recurse=False))
    assert [line.requirement for line in lines] == ["req1"]
def test_last_line_continuation(tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            # comment
            req1
            req2\\
            """))
    lines = list(parse(str(reqs)))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == ["req1", "req2"]
def test_editable(tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            # comment
            req1
            -e ./req2  # comment
            """))
    lines = list(parse(str(reqs)))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == ["req1", "./req2"]
    assert [line.is_editable for line in lines] == [False, True]
def test_hashes(tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            req @ ./req.tgz \\
                --hash sha1:62bd26d758...703a094285 \\
                --hash sha2:xyz
            """))
    lines = list(parse(str(reqs)))
    assert [line.requirement for line in lines] == ["req @ ./req.tgz"]
    assert lines[0].options["hashes"] == [
        "sha1:62bd26d758...703a094285", "sha2:xyz"
    ]
def test_relative_file(tmp_path):
    reqs = tmp_path / "reqs.txt"
    (tmp_path / "subdir").mkdir()
    subreqs = tmp_path / "subdir" / "subreqs.txt"
    subsubreqs = tmp_path / "subdir" / "subsubreqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            req1
            -r subdir/subreqs.txt
            """))
    subreqs.write_text(
        textwrap.dedent("""\
            req2
            -r ./subsubreqs.txt
            """))
    subsubreqs.write_text("req3")
    lines = list(parse(str(reqs)))
    assert [line.requirement for line in lines] == ["req1", "req2", "req3"]
def test_env_var(tmp_path, monkeypatch):
    monkeypatch.setenv("X_USER", "toto")
    monkeypatch.setenv("X_PASSWORD", "lehéro")
    monkeypatch.setenv("Z_USER", "")
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            https://${X_USER}@e.c/req.tgz
            https://${X_USER}:${X_PASSWORD}@e.c/req.tgz
            https://${Y_USER}@e.c/req.tgz
            https://${Z_USER}@e.c/req.tgz
            """))
    lines = list(parse(str(reqs)))
    assert all(isinstance(line, RequirementLine) for line in lines)
    assert [line.requirement for line in lines] == [
        "https://[email protected]/req.tgz",
        "https://*****:*****@e.c/req.tgz",
        "https://${Y_USER}@e.c/req.tgz",
        "https://@e.c/req.tgz",
    ]
def test_relative_file_uri(tmp_path):
    reqs = tmp_path / "reqs.txt"
    (tmp_path / "subdir").mkdir()
    subreqs = tmp_path / "subdir" / "subreqs.txt"
    subreqs_uri = subreqs.as_uri()
    assert subreqs_uri.startswith("file://")
    subsubreqs = tmp_path / "subdir" / "subsubreqs.txt"
    reqs.write_text(
        textwrap.dedent("""\
            req1
            -r {}
            """.format(subreqs_uri)))
    subreqs.write_text(
        textwrap.dedent("""\
            req2
            -r ./subsubreqs.txt
            """))
    subsubreqs.write_text("req3")
    lines = list(parse(str(reqs)))
    assert [line.requirement for line in lines] == ["req1", "req2", "req3"]
def test_options(line, expected, tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(line)
    lines = list(parse(str(reqs), reqs_only=False, recurse=False))
    assert len(lines) == 1
    assert lines[0].options == expected
def test_option_errors(badreqs, tmp_path):
    reqs = tmp_path / "reqs.txt"
    reqs.write_text(badreqs)
    with pytest.raises(OptionParsingError):
        _ = list(parse(str(reqs), recurse=False))