Index: pip_api-0.0.34/pip_api/_parse_requirements.py =================================================================== --- pip_api-0.0.34.orig/pip_api/_parse_requirements.py +++ pip_api-0.0.34/pip_api/_parse_requirements.py @@ -276,7 +276,7 @@ def _parse_local_package_name(path): and expr.value.func.id == "setup" ][0] value = [kw.value for kw in setup_kwargs if kw.arg == "name"][0] - return value.s + return getattr(value, 's', None) if hasattr(value, 's') else value.value except (IndexError, AttributeError, IOError, OSError): raise PipError( "Directory %r is not installable. " Index: pip_api-0.0.34/tests/test_parse_requirements.py =================================================================== --- pip_api-0.0.34.orig/tests/test_parse_requirements.py +++ pip_api-0.0.34/tests/test_parse_requirements.py @@ -62,14 +62,14 @@ PEP508_PIP_EXAMPLE_WHEEL_FILE = "file:// "pip @ {url}\n".format(url=PEP508_PIP_EXAMPLE_URL), {"pip"}, PEP508_PIP_EXAMPLE_URL, - "pip@ " + PEP508_PIP_EXAMPLE_URL, + "pip @ " + PEP508_PIP_EXAMPLE_URL, "", ), ( "pip@{url}\n".format(url=PEP508_PIP_EXAMPLE_URL), {"pip"}, PEP508_PIP_EXAMPLE_URL, - "pip@ " + PEP508_PIP_EXAMPLE_URL, # Note extra space after @ + "pip @ " + PEP508_PIP_EXAMPLE_URL, # Note extra space after @ "", ), ( @@ -77,7 +77,7 @@ PEP508_PIP_EXAMPLE_WHEEL_FILE = "file:// "git+" + PEP508_PIP_EXAMPLE_EGG, {"pip"}, PEP508_PIP_EXAMPLE_EGG, - "pip@ " + PEP508_PIP_EXAMPLE_EGG, + "pip @ " + PEP508_PIP_EXAMPLE_EGG, "", ), ( @@ -91,7 +91,7 @@ PEP508_PIP_EXAMPLE_WHEEL_FILE = "file:// PEP508_PIP_EXAMPLE_EGG_FILE, {"pip"}, PEP508_PIP_EXAMPLE_EGG_FILE, - "pip@ " + PEP508_PIP_EXAMPLE_EGG_FILE, + "pip @ " + PEP508_PIP_EXAMPLE_EGG_FILE, "", ), (PEP508_PIP_EXAMPLE_WHEEL_FILE, {"pip"}, None, "pip==1.3.1", "==1.3.1"), @@ -181,7 +181,7 @@ def test_parse_requirements_editable(mon assert set(result) == {"django", "deal"} assert str(result["django"]) == "Django==1.11" assert not result["django"].editable - assert str(result["deal"]) == "deal@ git+https://github.com/foo/deal.git#egg=deal" + assert str(result["deal"]) == "deal @ git+https://github.com/foo/deal.git#egg=deal" assert result["deal"].editable @@ -193,7 +193,7 @@ def test_parse_requirements_editable_fil assert set(result) == {"django", "pip-api"} assert str(result["django"]) == "Django==1.11" - assert str(result["pip-api"]).startswith("pip-api@ file:///") + assert str(result["pip-api"]).startswith("pip-api @ file:/") def test_parse_requirements_editable_pyprojecttoml(monkeypatch, data): @@ -206,7 +206,7 @@ def test_parse_requirements_editable_pyp assert set(result) == {"dummyproject_pyproject"} assert str(result["dummyproject_pyproject"]).startswith( - "dummyproject_pyproject@ file:///" + "dummyproject_pyproject @ file:/" ) @@ -220,7 +220,7 @@ def test_parse_requirements_editable_esc assert set(result) == {"dummyproject_pyproject"} assert str(result["dummyproject_pyproject"]).startswith( - "dummyproject_pyproject@ file:///" + "dummyproject_pyproject @ file:/" ) # The @ in `escapable@path` should be URL-encoded assert "escapable%40path" in str(result["dummyproject_pyproject"])