Skip to content

Commit f55d717

Browse files
committed
Adding tests
1 parent 22d04fc commit f55d717

19 files changed

+1297
-395
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,12 +1731,12 @@
17311731
{
17321732
"group": "Python",
17331733
"command": "python.createEnvironment-button",
1734-
"when": "showCreateEnvButton && resourceLangId == pip-requirements && !virtualWorkspace && shellExecutionSupported && !inDiffEditor && pipDepsNotInstalled"
1734+
"when": "showCreateEnvButton && resourceLangId == pip-requirements && !virtualWorkspace && shellExecutionSupported && !inDiffEditor && pythonDepsNotInstalled"
17351735
},
17361736
{
17371737
"group": "Python",
17381738
"command": "python.createEnvironment-button",
1739-
"when": "showCreateEnvButton && resourceFilename == pyproject.toml && pipInstallableToml && !virtualWorkspace && shellExecutionSupported && !inDiffEditor"
1739+
"when": "showCreateEnvButton && resourceFilename == pyproject.toml && pipInstallableToml && !virtualWorkspace && shellExecutionSupported && !inDiffEditor && pythonDepsNotInstalled"
17401740
}
17411741
],
17421742
"editor/context": [

pythonFiles/installed_check.py

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@
66
import os
77
import pathlib
88
import sys
9-
from typing import Optional, Sequence
9+
from typing import Dict, List, Optional, Sequence, Tuple, Union
1010

1111
LIB_ROOT = pathlib.Path(__file__).parent / "lib" / "python"
1212
sys.path.insert(0, os.fspath(LIB_ROOT))
1313

14+
import tomli
1415
from importlib_metadata import metadata
1516
from packaging.requirements import Requirement
1617

18+
DEFAULT_SEVERITY = 3
19+
1720

1821
def parse_args(argv: Optional[Sequence[str]] = None):
1922
if argv is None:
2023
argv = sys.argv[1:]
2124
parser = argparse.ArgumentParser(
2225
description="Check for installed packages against requirements"
2326
)
24-
parser.add_argument(
25-
"REQUIREMENTS", type=str, help="Path to requirements.[txt, in]", nargs="+"
26-
)
27+
parser.add_argument("FILEPATH", type=str, help="Path to requirements.[txt, in]")
2728

2829
return parser.parse_args(argv)
2930

@@ -39,32 +40,88 @@ def parse_requirements(line: str) -> Optional[Requirement]:
3940
return None
4041

4142

42-
def main():
43-
args = parse_args()
43+
def process_requirements(req_file: pathlib.Path) -> List[Dict[str, Union[str, int]]]:
44+
diagnostics = []
45+
for n, line in enumerate(req_file.read_text(encoding="utf-8").splitlines()):
46+
if line.startswith(("#", "-", " ")) or line == "":
47+
continue
48+
49+
req = parse_requirements(line)
50+
if req:
51+
try:
52+
# Check if package is installed
53+
metadata(req.name)
54+
except:
55+
diagnostics.append(
56+
{
57+
"line": n,
58+
"character": 0,
59+
"endLine": n,
60+
"endCharacter": len(req.name),
61+
"package": req.name,
62+
"code": "not-installed",
63+
"severity": DEFAULT_SEVERITY,
64+
}
65+
)
66+
return diagnostics
4467

68+
69+
def get_pos(lines: List[str], text: str) -> Tuple[int, int, int, int]:
70+
for n, line in enumerate(lines):
71+
index = line.find(text)
72+
if index >= 0:
73+
return n, index, n, index + len(text)
74+
return (0, 0, 0, 0)
75+
76+
77+
def process_pyproject(req_file: pathlib.Path) -> List[Dict[str, Union[str, int]]]:
4578
diagnostics = []
46-
for req_file in args.REQUIREMENTS:
47-
req_file = pathlib.Path(req_file)
48-
if req_file.exists():
49-
lines = req_file.read_text(encoding="utf-8").splitlines()
50-
for n, line in enumerate(lines):
51-
if line.startswith(("#", "-", " ")) or line == "":
52-
continue
53-
54-
req = parse_requirements(line)
55-
if req:
56-
try:
57-
# Check if package is installed
58-
metadata(req.name)
59-
except:
60-
diagnostics.append(
61-
{
62-
"line": n,
63-
"package": req.name,
64-
"code": "not-installed",
65-
"severity": 3,
66-
}
67-
)
79+
try:
80+
raw_text = req_file.read_text(encoding="utf-8")
81+
pyproject = tomli.loads(raw_text)
82+
except:
83+
return diagnostics
84+
85+
lines = raw_text.splitlines()
86+
reqs = pyproject.get("project", {}).get("dependencies", [])
87+
for raw_req in reqs:
88+
req = parse_requirements(raw_req)
89+
n, start, _, end = get_pos(lines, raw_req)
90+
if req:
91+
try:
92+
# Check if package is installed
93+
metadata(req.name)
94+
except:
95+
diagnostics.append(
96+
{
97+
"line": n,
98+
"character": start,
99+
"endLine": n,
100+
"endCharacter": end,
101+
"package": req.name,
102+
"code": "not-installed",
103+
"severity": DEFAULT_SEVERITY,
104+
}
105+
)
106+
return diagnostics
107+
108+
109+
def get_diagnostics(req_file: pathlib.Path) -> List[Dict[str, Union[str, int]]]:
110+
diagnostics = []
111+
if not req_file.exists():
112+
return diagnostics
113+
114+
if req_file.name == "pyproject.toml":
115+
diagnostics = process_pyproject(req_file)
116+
else:
117+
diagnostics = process_requirements(req_file)
118+
119+
return diagnostics
120+
121+
122+
def main():
123+
args = parse_args()
124+
diagnostics = get_diagnostics(pathlib.Path(args.FILEPATH))
68125
print(json.dumps(diagnostics, ensure_ascii=False))
69126

70127

0 commit comments

Comments
 (0)