dependabot-python 0.367.0 → 0.369.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/build +4 -0
- data/helpers/requirements.txt +1 -0
- data/helpers/test/fixtures/no_dependencies.toml +3 -0
- data/helpers/test/fixtures/pep621_arbitrary_equality.toml +7 -0
- data/helpers/test/fixtures/pep621_dependencies.toml +21 -0
- data/helpers/test/fixtures/pep621_empty_deps.toml +8 -0
- data/helpers/test/fixtures/pep621_extras.toml +8 -0
- data/helpers/test/fixtures/pep621_markers.toml +7 -0
- data/helpers/test/fixtures/pep621_multiple_extras.toml +7 -0
- data/helpers/test/fixtures/pep621_no_version.toml +8 -0
- data/helpers/test/fixtures/pep621_only_build_system.toml +3 -0
- data/helpers/test/fixtures/pep735_cycle.toml +13 -0
- data/helpers/test/fixtures/pep735_dependency_groups.toml +18 -0
- data/helpers/test/fixtures/requirements/constraints.txt +1 -0
- data/helpers/test/fixtures/requirements/markers.txt +1 -0
- data/helpers/test/fixtures/requirements/requirements-dev.txt +2 -0
- data/helpers/test/fixtures/requirements/requirements.txt +5 -0
- data/helpers/test/fixtures/requirements/with_constraints.txt +2 -0
- data/helpers/test/fixtures/requirements_empty/.gitkeep +0 -0
- data/helpers/test/fixtures/setup_cfg/setup.cfg +16 -0
- data/helpers/test/fixtures/setup_py/setup.py +20 -0
- data/helpers/test/fixtures/setup_py_comments/setup.py +9 -0
- data/helpers/test/test_hasher.py +114 -0
- data/helpers/test/test_parse_requirements.py +103 -0
- data/helpers/test/test_parse_setup.py +127 -0
- data/helpers/test/test_parser.py +184 -0
- data/helpers/test/test_run.py +49 -0
- data/lib/dependabot/python/file_updater/poetry_file_updater.rb +16 -11
- data/lib/dependabot/python/file_updater/pyproject_preparer.rb +109 -0
- data/lib/dependabot/python/file_updater/requirement_file_updater.rb +36 -13
- data/lib/dependabot/python/file_updater/requirement_replacer.rb +29 -21
- data/lib/dependabot/python/metadata_finder.rb +152 -20
- data/lib/dependabot/python/shared_file_fetcher.rb +10 -5
- data/lib/dependabot/python/update_checker/latest_version_finder.rb +4 -2
- metadata +29 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64cdd01e07bc2f6472a1027884006af4c7df3648168f04135c7b91cdf5530f14
|
|
4
|
+
data.tar.gz: b5610dc0420858f42cb23a8462abcd7ebd4b9b1aab8be3ca28233a99c239982c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f4cb556708bba8d54dc3d04495d021e4808cf5651184ed9fe2d1b65d6b1114c688f92d9be8ab8fae6e96d818643ce4c4824db5971dc2fabf55370b6ffff26f39
|
|
7
|
+
data.tar.gz: 64514c6fad289e34af6bdbaeecc25f8ff815ba193d77088a86fa3399c9379ab1cad740ff0f18ae0ac176e85375714e15f36ceae638b96d6e2714f425ce86cd96
|
data/helpers/build
CHANGED
|
@@ -17,6 +17,10 @@ cp -r \
|
|
|
17
17
|
"$helpers_dir/requirements.txt" \
|
|
18
18
|
"$install_dir"
|
|
19
19
|
|
|
20
|
+
if [ -d "$helpers_dir/test" ]; then
|
|
21
|
+
cp -r "$helpers_dir/test" "$install_dir"
|
|
22
|
+
fi
|
|
23
|
+
|
|
20
24
|
cd "$install_dir"
|
|
21
25
|
PYENV_VERSION=$1 pyenv exec pip3 --disable-pip-version-check install --use-pep517 -r "requirements.txt"
|
|
22
26
|
|
data/helpers/requirements.txt
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "myapp"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
requires-python = ">=3.10"
|
|
5
|
+
|
|
6
|
+
dependencies = [
|
|
7
|
+
"requests>=2.13.0,<3.0",
|
|
8
|
+
"urllib3==1.26.0",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
[project.optional-dependencies]
|
|
12
|
+
socks = [
|
|
13
|
+
"PySocks >= 1.5.6, != 1.5.7, < 2",
|
|
14
|
+
]
|
|
15
|
+
tests = [
|
|
16
|
+
"pytest >= 7.0, < 8",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["setuptools>=68.0"]
|
|
21
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "myapp"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
requires-python = ">=3.10"
|
|
5
|
+
|
|
6
|
+
dependencies = [
|
|
7
|
+
"requests>=2.13.0",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
[dependency-groups]
|
|
11
|
+
dev = [
|
|
12
|
+
"pytest==7.1.3",
|
|
13
|
+
"black==22.10.0",
|
|
14
|
+
]
|
|
15
|
+
lint = [
|
|
16
|
+
{include-group = "dev"},
|
|
17
|
+
"flake8>=5.0",
|
|
18
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests<3.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pywin32>=1.0; sys_platform == "win32"
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="myapp",
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
install_requires=[
|
|
7
|
+
"requests>=2.13.0",
|
|
8
|
+
"urllib3==1.26.0",
|
|
9
|
+
],
|
|
10
|
+
setup_requires=[
|
|
11
|
+
"setuptools>=68.0",
|
|
12
|
+
],
|
|
13
|
+
tests_require=[
|
|
14
|
+
"pytest>=7.0",
|
|
15
|
+
],
|
|
16
|
+
extras_require={
|
|
17
|
+
"socks": ["PySocks>=1.5.6"],
|
|
18
|
+
"dev": ["black==22.10.0"],
|
|
19
|
+
},
|
|
20
|
+
)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import ssl
|
|
4
|
+
import sys
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
|
+
from urllib.error import URLError
|
|
7
|
+
|
|
8
|
+
sys.path.insert(
|
|
9
|
+
0, os.path.join(os.path.dirname(__file__), os.pardir, "lib")
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
import hasher # noqa: E402
|
|
13
|
+
import hashin as hashin_mod # noqa: E402
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestGetDependencyHash:
|
|
17
|
+
@patch("hasher.hashin.get_package_hashes")
|
|
18
|
+
def test_returns_hashes(self, mock_get):
|
|
19
|
+
mock_get.return_value = {
|
|
20
|
+
"hashes": [
|
|
21
|
+
{"hash": "abc123", "platform": "linux"},
|
|
22
|
+
{"hash": "def456", "platform": "macos"},
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
result = json.loads(hasher.get_dependency_hash(
|
|
27
|
+
"requests", "2.28.0", "sha256"
|
|
28
|
+
))
|
|
29
|
+
|
|
30
|
+
assert "result" in result
|
|
31
|
+
assert len(result["result"]) == 2
|
|
32
|
+
assert result["result"][0]["hash"] == "abc123"
|
|
33
|
+
mock_get.assert_called_once()
|
|
34
|
+
|
|
35
|
+
@patch("hasher.hashin.get_package_hashes")
|
|
36
|
+
def test_custom_index_url(self, mock_get):
|
|
37
|
+
mock_get.return_value = {"hashes": []}
|
|
38
|
+
|
|
39
|
+
hasher.get_dependency_hash(
|
|
40
|
+
"requests", "2.28.0", "sha256",
|
|
41
|
+
index_url="https://custom.registry/simple/"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
mock_get.assert_called_once_with(
|
|
45
|
+
"requests",
|
|
46
|
+
version="2.28.0",
|
|
47
|
+
algorithm="sha256",
|
|
48
|
+
index_url="https://custom.registry/simple/"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
@patch("hasher.hashin.get_package_hashes")
|
|
52
|
+
def test_package_not_found(self, mock_get):
|
|
53
|
+
mock_get.side_effect = hashin_mod.PackageNotFoundError(
|
|
54
|
+
"no-such-package"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
result = json.loads(hasher.get_dependency_hash(
|
|
58
|
+
"no-such-package", "1.0.0", "sha256"
|
|
59
|
+
))
|
|
60
|
+
|
|
61
|
+
assert "error" in result
|
|
62
|
+
|
|
63
|
+
@patch("hasher.hashin.get_package_hashes")
|
|
64
|
+
def test_ssl_certificate_error(self, mock_get):
|
|
65
|
+
ssl_error = ssl.SSLError(
|
|
66
|
+
"CERTIFICATE_VERIFY_FAILED: unable to get local issuer"
|
|
67
|
+
)
|
|
68
|
+
mock_get.side_effect = URLError(ssl_error)
|
|
69
|
+
|
|
70
|
+
result = json.loads(hasher.get_dependency_hash(
|
|
71
|
+
"requests", "2.28.0", "sha256"
|
|
72
|
+
))
|
|
73
|
+
|
|
74
|
+
assert "error" in result
|
|
75
|
+
assert "CERTIFICATE_VERIFY_FAILED" in result["error"]
|
|
76
|
+
|
|
77
|
+
@patch("hasher.hashin.get_package_hashes")
|
|
78
|
+
def test_non_ssl_url_error_raises(self, mock_get):
|
|
79
|
+
mock_get.side_effect = URLError("Connection refused")
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
hasher.get_dependency_hash("requests", "2.28.0", "sha256")
|
|
83
|
+
assert False, "Expected URLError to be raised"
|
|
84
|
+
except URLError:
|
|
85
|
+
pass # expected
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class TestGetPipfileHash:
|
|
89
|
+
@patch("builtins.open")
|
|
90
|
+
@patch("hasher.plette")
|
|
91
|
+
def test_returns_hash(self, mock_plette, mock_open):
|
|
92
|
+
mock_pipfile = MagicMock()
|
|
93
|
+
mock_pipfile.get_hash.return_value.value = "abc123hash"
|
|
94
|
+
mock_plette.Pipfile.load.return_value = mock_pipfile
|
|
95
|
+
|
|
96
|
+
result = json.loads(hasher.get_pipfile_hash("/tmp/project"))
|
|
97
|
+
|
|
98
|
+
assert result["result"] == "abc123hash"
|
|
99
|
+
mock_open.assert_called_once_with("/tmp/project/Pipfile")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TestGetPyprojectHash:
|
|
103
|
+
@patch("hasher.Factory")
|
|
104
|
+
def test_returns_hash(self, mock_factory_cls):
|
|
105
|
+
mock_poetry = MagicMock()
|
|
106
|
+
mock_poetry.locker._get_content_hash.return_value = "xyz789hash"
|
|
107
|
+
mock_factory_cls.return_value.create_poetry.return_value = mock_poetry
|
|
108
|
+
|
|
109
|
+
result = json.loads(hasher.get_pyproject_hash("/tmp/project"))
|
|
110
|
+
|
|
111
|
+
assert result["result"] == "xyz789hash"
|
|
112
|
+
mock_factory_cls.return_value.create_poetry.assert_called_once_with(
|
|
113
|
+
"/tmp/project"
|
|
114
|
+
)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
sys.path.insert(
|
|
6
|
+
0, os.path.join(os.path.dirname(__file__), os.pardir, "lib")
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from parser import parse_requirements # noqa: E402
|
|
10
|
+
|
|
11
|
+
FIXTURES = os.path.join(os.path.dirname(__file__), "fixtures")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def parse(fixture_dir):
|
|
15
|
+
path = os.path.join(FIXTURES, fixture_dir)
|
|
16
|
+
result = json.loads(parse_requirements(path))
|
|
17
|
+
return result
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def find_dep(deps, name):
|
|
21
|
+
return next((d for d in deps if d["name"] == name), None)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def find_dep_in_file(deps, name, file_substring):
|
|
25
|
+
return next(
|
|
26
|
+
(d for d in deps
|
|
27
|
+
if d["name"] == name and file_substring in d["file"]),
|
|
28
|
+
None
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TestParseRequirementsTxt:
|
|
33
|
+
def test_parses_basic_requirements(self):
|
|
34
|
+
result = parse("requirements")
|
|
35
|
+
deps = result["result"]
|
|
36
|
+
requests = find_dep_in_file(deps, "requests", "requirements.txt")
|
|
37
|
+
assert requests is not None
|
|
38
|
+
assert requests["requirement"] == "<3.0,>=2.13.0"
|
|
39
|
+
|
|
40
|
+
def test_parses_pinned_version(self):
|
|
41
|
+
result = parse("requirements")
|
|
42
|
+
deps = result["result"]
|
|
43
|
+
urllib3 = find_dep(deps, "urllib3")
|
|
44
|
+
assert urllib3 is not None
|
|
45
|
+
assert urllib3["version"] == "1.26.0"
|
|
46
|
+
assert urllib3["requirement"] == "==1.26.0"
|
|
47
|
+
|
|
48
|
+
def test_parses_extras(self):
|
|
49
|
+
result = parse("requirements")
|
|
50
|
+
deps = result["result"]
|
|
51
|
+
flask = find_dep(deps, "Flask")
|
|
52
|
+
assert flask is not None
|
|
53
|
+
assert flask["extras"] == ["async"]
|
|
54
|
+
|
|
55
|
+
def test_strips_inline_comments(self):
|
|
56
|
+
result = parse("requirements")
|
|
57
|
+
deps = result["result"]
|
|
58
|
+
boto3 = find_dep(deps, "boto3")
|
|
59
|
+
assert boto3 is not None
|
|
60
|
+
# boto3 has no version specifier, just a comment
|
|
61
|
+
assert boto3["requirement"] is None or boto3["requirement"] == ""
|
|
62
|
+
|
|
63
|
+
def test_file_path_is_relative(self):
|
|
64
|
+
result = parse("requirements")
|
|
65
|
+
deps = result["result"]
|
|
66
|
+
for dep in deps:
|
|
67
|
+
assert not os.path.isabs(dep["file"])
|
|
68
|
+
|
|
69
|
+
def test_parses_dev_requirements(self):
|
|
70
|
+
result = parse("requirements")
|
|
71
|
+
deps = result["result"]
|
|
72
|
+
black = find_dep(deps, "black")
|
|
73
|
+
assert black is not None
|
|
74
|
+
assert black["version"] == "22.10.0"
|
|
75
|
+
assert "requirements-dev.txt" in black["file"]
|
|
76
|
+
|
|
77
|
+
def test_parses_markers(self):
|
|
78
|
+
result = parse("requirements")
|
|
79
|
+
deps = result["result"]
|
|
80
|
+
pywin32 = find_dep(deps, "pywin32")
|
|
81
|
+
assert pywin32 is not None
|
|
82
|
+
assert pywin32["markers"] == 'sys_platform == "win32"'
|
|
83
|
+
|
|
84
|
+
def test_empty_directory_returns_empty(self):
|
|
85
|
+
result = parse("requirements_empty")
|
|
86
|
+
deps = result["result"]
|
|
87
|
+
assert deps == []
|
|
88
|
+
|
|
89
|
+
def test_constraint_file_deps(self):
|
|
90
|
+
"""Requirements with -c constraints should still parse the deps."""
|
|
91
|
+
result = parse("requirements")
|
|
92
|
+
deps = result["result"]
|
|
93
|
+
# with_constraints.txt has requests
|
|
94
|
+
req_files = [d["file"] for d in deps if d["name"] == "requests"]
|
|
95
|
+
assert any("with_constraints" in f for f in req_files)
|
|
96
|
+
|
|
97
|
+
def test_multiple_files_parsed(self):
|
|
98
|
+
"""All .txt files in the directory are parsed."""
|
|
99
|
+
result = parse("requirements")
|
|
100
|
+
deps = result["result"]
|
|
101
|
+
files = {d["file"] for d in deps}
|
|
102
|
+
assert any("requirements.txt" in f for f in files)
|
|
103
|
+
assert any("requirements-dev.txt" in f for f in files)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
sys.path.insert(
|
|
6
|
+
0, os.path.join(os.path.dirname(__file__), os.pardir, "lib")
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from parser import parse_setup # noqa: E402
|
|
10
|
+
|
|
11
|
+
FIXTURES = os.path.join(os.path.dirname(__file__), "fixtures")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def parse(fixture_dir):
|
|
15
|
+
path = os.path.join(FIXTURES, fixture_dir)
|
|
16
|
+
result = json.loads(parse_setup(path))
|
|
17
|
+
return result
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def find_dep(deps, name):
|
|
21
|
+
return next((d for d in deps if d["name"] == name), None)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
# setup.py parsing
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
class TestSetupPy:
|
|
28
|
+
def test_parses_install_requires(self):
|
|
29
|
+
result = parse("setup_py")
|
|
30
|
+
deps = result["result"]
|
|
31
|
+
requests = find_dep(deps, "requests")
|
|
32
|
+
assert requests is not None
|
|
33
|
+
assert requests["requirement"] == ">=2.13.0"
|
|
34
|
+
assert requests["requirement_type"] == "install_requires"
|
|
35
|
+
assert requests["file"] == "setup.py"
|
|
36
|
+
|
|
37
|
+
def test_parses_pinned_version(self):
|
|
38
|
+
result = parse("setup_py")
|
|
39
|
+
deps = result["result"]
|
|
40
|
+
urllib3 = find_dep(deps, "urllib3")
|
|
41
|
+
assert urllib3 is not None
|
|
42
|
+
assert urllib3["version"] == "1.26.0"
|
|
43
|
+
|
|
44
|
+
def test_parses_setup_requires(self):
|
|
45
|
+
result = parse("setup_py")
|
|
46
|
+
deps = result["result"]
|
|
47
|
+
setuptools = find_dep(deps, "setuptools")
|
|
48
|
+
assert setuptools is not None
|
|
49
|
+
assert setuptools["requirement_type"] == "setup_requires"
|
|
50
|
+
|
|
51
|
+
def test_parses_tests_require(self):
|
|
52
|
+
result = parse("setup_py")
|
|
53
|
+
deps = result["result"]
|
|
54
|
+
pytest = find_dep(deps, "pytest")
|
|
55
|
+
assert pytest is not None
|
|
56
|
+
assert pytest["requirement_type"] == "tests_require"
|
|
57
|
+
|
|
58
|
+
def test_parses_extras_require(self):
|
|
59
|
+
result = parse("setup_py")
|
|
60
|
+
deps = result["result"]
|
|
61
|
+
pysocks = find_dep(deps, "PySocks")
|
|
62
|
+
assert pysocks is not None
|
|
63
|
+
assert pysocks["requirement_type"] == "extras_require:socks"
|
|
64
|
+
|
|
65
|
+
def test_parses_multiple_extras_groups(self):
|
|
66
|
+
result = parse("setup_py")
|
|
67
|
+
deps = result["result"]
|
|
68
|
+
extras = [d for d in deps if d["requirement_type"].startswith(
|
|
69
|
+
"extras_require:"
|
|
70
|
+
)]
|
|
71
|
+
groups = {d["requirement_type"] for d in extras}
|
|
72
|
+
assert "extras_require:socks" in groups
|
|
73
|
+
assert "extras_require:dev" in groups
|
|
74
|
+
|
|
75
|
+
def test_strips_comments(self):
|
|
76
|
+
result = parse("setup_py_comments")
|
|
77
|
+
deps = result["result"]
|
|
78
|
+
requests = find_dep(deps, "requests")
|
|
79
|
+
assert requests is not None
|
|
80
|
+
assert requests["requirement"] == ">=2.13.0"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# setup.cfg parsing
|
|
85
|
+
# ---------------------------------------------------------------------------
|
|
86
|
+
class TestSetupCfg:
|
|
87
|
+
def test_parses_install_requires(self):
|
|
88
|
+
result = parse("setup_cfg")
|
|
89
|
+
deps = result["result"]
|
|
90
|
+
requests = find_dep(deps, "requests")
|
|
91
|
+
assert requests is not None
|
|
92
|
+
assert requests["requirement"] == ">=2.13.0"
|
|
93
|
+
assert requests["requirement_type"] == "install_requires"
|
|
94
|
+
assert requests["file"] == "setup.cfg"
|
|
95
|
+
|
|
96
|
+
def test_parses_pinned_version(self):
|
|
97
|
+
result = parse("setup_cfg")
|
|
98
|
+
deps = result["result"]
|
|
99
|
+
urllib3 = find_dep(deps, "urllib3")
|
|
100
|
+
assert urllib3 is not None
|
|
101
|
+
assert urllib3["version"] == "1.26.0"
|
|
102
|
+
|
|
103
|
+
def test_parses_setup_requires(self):
|
|
104
|
+
result = parse("setup_cfg")
|
|
105
|
+
deps = result["result"]
|
|
106
|
+
setuptools = find_dep(deps, "setuptools")
|
|
107
|
+
assert setuptools is not None
|
|
108
|
+
assert setuptools["requirement_type"] == "setup_requires"
|
|
109
|
+
|
|
110
|
+
def test_parses_tests_require(self):
|
|
111
|
+
result = parse("setup_cfg")
|
|
112
|
+
deps = result["result"]
|
|
113
|
+
pytest = find_dep(deps, "pytest")
|
|
114
|
+
assert pytest is not None
|
|
115
|
+
assert pytest["requirement_type"] == "tests_require"
|
|
116
|
+
|
|
117
|
+
def test_parses_extras_require(self):
|
|
118
|
+
result = parse("setup_cfg")
|
|
119
|
+
deps = result["result"]
|
|
120
|
+
pysocks = find_dep(deps, "PySocks")
|
|
121
|
+
assert pysocks is not None
|
|
122
|
+
assert pysocks["requirement_type"] == "extras_require:socks"
|
|
123
|
+
|
|
124
|
+
def test_empty_directory_returns_empty(self):
|
|
125
|
+
result = parse("requirements_empty")
|
|
126
|
+
deps = result["result"]
|
|
127
|
+
assert deps == []
|