Skip to content

Commit 0533d4b

Browse files
committed
Initial support for requirements.{in,txt}
1 parent 244d61b commit 0533d4b

File tree

8 files changed

+104
-24
lines changed

8 files changed

+104
-24
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to the "poetry-python" extension will be documented in this
44

55
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
66

7+
## [0.0.16]
8+
9+
- Added support for requirements.txt
10+
711
## [0.0.15]
812

913
- Initial release with support for pyproject.toml and Poetry

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
],
1717
"activationEvents": [
1818
"onLanguage:toml",
19-
"workspaceContains:pyproject.toml"
19+
"onLanguage:txt",
20+
"onLanguage:in",
21+
"workspaceContains:pyproject.toml",
22+
"workspaceContains:requirements.txt",
23+
"workspaceContains:requirements.in"
2024
],
2125
"main": "./out/extension.js",
2226
"scripts": {

src/core/decorations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export const getDecoration = (dep: Dependency) => {
77
message.appendMarkdown(dep.summary || "No information for this library");
88
message.isTrusted = true;
99

10-
const prefix = dep.version.latest === dep.version.installed ? "✅" : "⚠️";
10+
const prefix = dep.version.latest === dep.version.installed ? "✅" : "🚸";
1111

1212
return {
1313
range: new Range(

src/core/listener.ts

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { TextEditor, window, TextEditorDecorationType } from "vscode";
22
import { Dependency } from "../types";
3-
import { findDependencies } from "../utils/parsing";
3+
import { findDependencies } from "../utils/parsing/toml";
44
import { getInstalledVersions } from "./poetry";
55
import { getInfo } from "./api";
66
import { getDecoration } from "./decorations";
77
import { dirname } from "path";
8+
import { findDependenciesFromRequirementsTxt } from "../utils/parsing/requirements-txt";
89

910
let decorationType: TextEditorDecorationType | null = null;
1011

@@ -16,21 +17,22 @@ const updateVersions = (
1617
deps.map(async (dep) => {
1718
const info = await getInfo(dep.name);
1819

19-
dep.version.installed = installedVersions[dep.name];
20+
// dep.version.installed = installedVersions[dep.name];
2021
dep.version.latest = info.version;
2122
dep.summary = info.summary;
2223
}),
2324
);
2425
};
2526

26-
const doThings = async (deps: Dependency[], editor: TextEditor) => {
27+
const decorateEditor = async (deps: Dependency[], editor: TextEditor) => {
2728
if (decorationType) {
2829
decorationType.dispose();
2930
}
3031

31-
const installedVersions = await getInstalledVersions(
32-
dirname(editor.document.fileName),
33-
);
32+
const installedVersions = {}
33+
// await getInstalledVersions(
34+
// dirname(editor.document.fileName),
35+
// );
3436

3537
await updateVersions(deps, installedVersions);
3638

@@ -43,24 +45,40 @@ const doThings = async (deps: Dependency[], editor: TextEditor) => {
4345
editor.setDecorations(decorationType!, decorations);
4446
};
4547

46-
function parseAndDecorate(editor: TextEditor) {
48+
function parseAndDecorateToml(editor: TextEditor) {
4749
const text = editor.document.getText();
48-
// const config = workspace.getConfiguration("", editor.document.uri);
4950

5051
const deps = findDependencies(text);
5152

52-
console.log("parsing and decorating");
53+
decorateEditor(deps, editor);
54+
}
55+
56+
function parseAndDecorateRequirementsTxt(editor: TextEditor) {
57+
const text = editor.document.getText();
58+
59+
const deps = findDependenciesFromRequirementsTxt(text);
5360

54-
doThings(deps, editor);
61+
decorateEditor(deps, editor);
5562
}
5663

5764
export const pyProjectListener = (editor: TextEditor | undefined) => {
5865
if (editor) {
5966
const { fileName } = editor.document;
6067
if (fileName.toLocaleLowerCase().endsWith("pyproject.toml")) {
61-
parseAndDecorate(editor);
68+
parseAndDecorateToml(editor);
69+
}
70+
}
71+
};
72+
73+
export const requirementsTxtListener = (editor: TextEditor | undefined) => {
74+
if (editor) {
75+
const fileName = editor.document.fileName.toLocaleLowerCase();
76+
77+
if (
78+
fileName.endsWith("requirements.txt") ||
79+
fileName.endsWith("requirements.in")
80+
) {
81+
parseAndDecorateRequirementsTxt(editor);
6282
}
63-
} else {
64-
console.log("No active editor found.");
6583
}
6684
};

src/extension.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,39 @@ import {
55
TextDocumentChangeEvent,
66
} from "vscode";
77
import { setCache } from "./cache";
8-
import { pyProjectListener } from "./core/listener";
8+
import { pyProjectListener, requirementsTxtListener } from "./core/listener";
99

1010
export function activate(context: ExtensionContext) {
1111
setCache(context);
1212

1313
context.subscriptions.push(
1414
window.onDidChangeActiveTextEditor(pyProjectListener),
15+
window.onDidChangeActiveTextEditor(requirementsTxtListener),
1516
);
1617

1718
context.subscriptions.push(
1819
workspace.onDidChangeTextDocument((e: TextDocumentChangeEvent) => {
19-
const { fileName } = e.document;
20+
if (e.document.isDirty) {
21+
return;
22+
}
23+
24+
const fileName = e.document.fileName.toLocaleLowerCase();
25+
26+
if (fileName.endsWith("pyproject.toml")) {
27+
pyProjectListener(window.activeTextEditor);
28+
}
29+
2030
if (
21-
!e.document.isDirty &&
22-
fileName.toLocaleLowerCase().endsWith("pyproject.toml")
31+
fileName.endsWith("requirements.txt") ||
32+
fileName.endsWith("requirements.in")
2333
) {
24-
pyProjectListener(window.activeTextEditor);
34+
requirementsTxtListener(window.activeTextEditor);
2535
}
2636
}),
2737
);
2838

2939
pyProjectListener(window.activeTextEditor);
40+
requirementsTxtListener(window.activeTextEditor);
3041
}
3142

3243
export function deactivate() {}

src/utils/parsing/requirements-txt.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Dependency } from "../../types";
2+
import { splitFirst } from "../strings";
3+
4+
5+
const parseDependency = (line: string, lineNumber: number) => {
6+
const [name, version] = splitFirst(line, "==").map((x) => x.trim());
7+
8+
return {
9+
name,
10+
version: {
11+
toml: version,
12+
},
13+
line: lineNumber,
14+
rawText: line,
15+
};
16+
};
17+
18+
export const findDependenciesFromRequirementsTxt = (text: string) => {
19+
const lines = text.split("\n");
20+
21+
const dependencies: Dependency[] = [];
22+
23+
lines.forEach((line, index) => {
24+
line = line.replace(/ #.*$/, "").trim();
25+
26+
// remove extras like tablib[html]
27+
line = line.replace(/\[.*\]/, "");
28+
29+
if (line === "") {
30+
return;
31+
}
32+
33+
if (line.startsWith("#") || line.startsWith("-") || line.startsWith("git+")) {
34+
return;
35+
} else {
36+
const dependency = parseDependency(line, index);
37+
38+
dependencies.push(dependency);
39+
}
40+
});
41+
42+
return dependencies;
43+
};

src/utils/parsing.ts renamed to src/utils/parsing/toml.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Dependency } from "../types";
2-
import { splitFirst } from "./strings";
1+
import { Dependency } from "../../types";
2+
import { splitFirst } from "../strings";
33

44
const parseInfo = (str: string) => {
55
// TODO: this is a naive way of parsing this string, but for now it works, probably

src/utils/strings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
export const splitFirst = (line: string) => {
2-
const [a, ...b] = line.split("=");
1+
export const splitFirst = (line: string, separator: string = '=') => {
2+
const [a, ...b] = line.split(separator);
33

44
return [a, b.join("=")];
55
};

0 commit comments

Comments
 (0)